diff --git a/AUTHORS b/AUTHORS
index 1958d73..3d03022 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -552,6 +552,7 @@
 Jaewon Choi <jaewon.james.choi@gmail.com>
 Jaewon Jung <jw.jung@navercorp.com>
 Jaeyong Bae <jdragon.bae@gmail.com>
+Jagadesh P <jagadeshjai1999@gmail.com>
 Jagdish Chourasia <jagdish.c@samsung.com>
 Jaime Soriano Pastor <jsorianopastor@gmail.com>
 Jake Helfert <jake@helfert.us>
diff --git a/DEPS b/DEPS
index 33f38f6c..f0ec547e 100644
--- a/DEPS
+++ b/DEPS
@@ -405,7 +405,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': '087d06b98e6fdd264fde7d16895a1c3cec4d0766',
+  'devtools_frontend_revision': 'a2fe80db51e2111d5043181671e2ae52b8b2d79d',
   # 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.
@@ -845,7 +845,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '634fe7e05f59ab1a85a395b539490fe1aa85fef4',
+    '340aed4c542ac53f950fd007ee452c3f1099739f',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1051,7 +1051,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'hruMK_i8vh9qvHxGsCV7FqycDsk4ggbDeQ89PJ7leTkC',
+          'version': 'DqV7MfoS-OdweHanUQqLvihUZG2azL412tGbq3_z7K8C',
       },
     ],
     'condition': 'checkout_android',
@@ -1260,7 +1260,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '494c618cbb635ccc6f925e6cf7590c0a64d89687',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '4eda4462cb2fea1ff99bfb477545f36b282b8db4',
       'condition': 'checkout_chromeos',
   },
 
@@ -1295,13 +1295,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'c5505889cf38b44fd841b161d4d2e2776b65f943',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'f936d540e1811967bd3cc819089b498b98b1e1be',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'c3526d66491c1c30fbb2b257ce94fbbb91474323',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'e0aad9e4d829ac0dd9f1ee4a2e67c10650a7d266',
     'condition': 'checkout_src_internal',
   },
 
@@ -1975,7 +1975,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '0447990a43973392ca18aec8a0422f67e5b6776e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '29d4a013bc90abdd78cffbe0a671d81a08010539',
+    Var('webrtc_git') + '/src.git' + '@' + '7892f05411d93fe9a2b876daccd817286ca43182',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -2019,7 +2019,7 @@
   },
 
   'src/third_party/zstd/src':
-    Var('chromium_git') + '/external/github.com/facebook/zstd.git' + '@' + '25822342be59d831bad65426ae51f5cc22157b09',
+    Var('chromium_git') + '/external/github.com/facebook/zstd.git' + '@' + 'cdceb0fce59785c841bf697e00067163106064e1',
 
   'src/tools/skia_goldctl/linux': {
       'packages': [
@@ -2087,7 +2087,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/eche_app/app',
-        'version': 'ZFrQCoHgRo7gmVyYl3FnKsSBemrchFd6qejKVSBdZP8C',
+        'version': 'AYWi8kEgPYAulRPja1nb_aKPv1iOWNu4bJxhiHw7Cv0C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4269,7 +4269,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        'b4ee1c0e0af715ddf8c0bf37925f6271c4b9a288',
+        '8cb00a50524709f4aed93935c0abc0d09980bbb1',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index d30ce6f..d8f19601 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -321,7 +321,9 @@
           'ash/webui/multidevice_debug/resources/webui.js',
           'ash/webui/projector_app/resources/annotator/trusted/annotator_browser_proxy.js',
           'ash/webui/projector_app/resources/app/trusted/projector_browser_proxy.js',
-          'ash/webui/scanning/resources/scanning_browser_proxy.js',
+          # TODO(b/301634378): Remove violation exception once Scanning App
+          # migrated off usage of `chrome.send`.
+          'ash/webui/scanning/resources/scanning_browser_proxy.ts',
       ),
     ),
 )
diff --git a/WATCHLISTS b/WATCHLISTS
index 2c929e75..3008ffb8 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1781,6 +1781,13 @@
                   '|chrome/browser/renderer_context_menu/quick_answers'\
                   '|chromeos/components/quick_answers/'
     },
+    'related_website_sets': {
+      'filepath': 'first_party_sets|' \
+                  'top_level_storage_access_api|' \
+                  'top-level-storage-access-api|' \
+                  'storage_access_api|' \
+                  'storage-access-api'
+    },
     'relaunch_notification': {
       'filepath': 'chrome/browser/ui/views/relaunch_notification'
     },
@@ -1943,6 +1950,10 @@
     'startup': {
       'filepath': 'chrome/browser/ui/startup/',
     },
+    'storage_access_api': {
+      'filepath': '/storage_access_api/|' \
+                  '/storage-access-api/'
+    },
     'storage_service' : {
       'filepath': 'components/services/storage/',
     },
@@ -3016,6 +3027,7 @@
     'psm_libs': ['amraboelkher+watch@chromium.org'],
     'push_messaging': ['peter@chromium.org'],
     'quick_answers': ['croissant-eng+reviews@chromium.org'],
+    'related_website_sets': ['cfredric+watch@chromium.org'],
     'relaunch_notification': ['grt+watch@chromium.org'],
     'remoteplayback': ['mfoltz+watch@chromium.org'],
     'remoting': ['chromoting-reviews@chromium.org'],
@@ -3088,6 +3100,7 @@
     'startup': ['cmfcmf+watch@chromium.org',
                 'nicolaso+watch@chromium.org',
                 'ydago+watch@chromium.org'],
+    'storage_access_api': ['cfredric+watch@chromium.org'],
     'storage_service': ['dmurph+watching-storageservice@chromium.org'],
     'structured_headers': ['iclelland+watch@chromium.org'],
     'styleguide': ['danakj+watch@chromium.org',
diff --git a/android_webview/browser/aw_feature_map.cc b/android_webview/browser/aw_feature_map.cc
index c270098..dd3bd4c 100644
--- a/android_webview/browser/aw_feature_map.cc
+++ b/android_webview/browser/aw_feature_map.cc
@@ -8,6 +8,7 @@
 #include "android_webview/common/aw_features.h"
 #include "base/android/feature_map.h"
 #include "base/feature_list.h"
+#include "base/features.h"
 #include "base/no_destructor.h"
 #include "components/embedder_support/android/metrics/features.h"
 #include "components/safe_browsing/core/common/features.h"
@@ -35,10 +36,10 @@
     &metrics::kAndroidMetricsAsyncMetricLogging,
     &features::kWebViewZoomKeyboardShortcuts,
     &features::kWebViewClearFunctorInBackground,
-    &features::kWebViewReportFrameMetrics,
     &safe_browsing::kHashPrefixRealTimeLookups,
     &features::kWebViewSupervisedUserSiteDetection,
     &features::kWebViewSupervisedUserSiteBlock,
+    &base::features::kCollectAndroidFrameTimelineMetrics,
 };
 
 // static
diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_features.cc
index 1f48ac4..19fee19 100644
--- a/android_webview/common/aw_features.cc
+++ b/android_webview/common/aw_features.cc
@@ -107,12 +107,6 @@
              "WebViewRecordAppDataDirectorySize",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Whether to report frame metrics to the Android.Jank.FrameDuration and
-// Android.Jank.FrameJankStatus histograms.
-BASE_FEATURE(kWebViewReportFrameMetrics,
-             "WebViewReportFrameMetrics",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 // Flag to restrict main frame Web Content to verified web content. Verification
 // happens via Digital Asset Links.
 BASE_FEATURE(kWebViewRestrictSensitiveContent,
diff --git a/android_webview/common/aw_features.h b/android_webview/common/aw_features.h
index 60e8e78..8ac90740 100644
--- a/android_webview/common/aw_features.h
+++ b/android_webview/common/aw_features.h
@@ -34,7 +34,6 @@
 BASE_DECLARE_FEATURE(kWebViewMixedContentAutoupgrades);
 BASE_DECLARE_FEATURE(kWebViewOriginTrials);
 BASE_DECLARE_FEATURE(kWebViewRecordAppDataDirectorySize);
-BASE_DECLARE_FEATURE(kWebViewReportFrameMetrics);
 BASE_DECLARE_FEATURE(kWebViewRestrictSensitiveContent);
 BASE_DECLARE_FEATURE(kWebViewSupervisedUserSiteDetection);
 BASE_DECLARE_FEATURE(kWebViewSupervisedUserSiteBlock);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 614eeda..43596f43 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -66,6 +66,7 @@
 import org.chromium.android_webview.permission.AwGeolocationCallback;
 import org.chromium.android_webview.permission.AwPermissionRequest;
 import org.chromium.android_webview.renderer_priority.RendererPriority;
+import org.chromium.base.BaseFeatures;
 import org.chromium.base.Callback;
 import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
@@ -81,6 +82,11 @@
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.jank_tracker.FrameMetricsListener;
 import org.chromium.base.jank_tracker.FrameMetricsStore;
+import org.chromium.base.jank_tracker.JankReportingScheduler;
+import org.chromium.base.jank_tracker.JankScenario;
+import org.chromium.base.jank_tracker.JankTracker;
+import org.chromium.base.jank_tracker.JankTrackerImpl;
+import org.chromium.base.jank_tracker.JankTrackerStateController;
 import org.chromium.base.memory.MemoryInfoBridge;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.ScopedSysTraceEvent;
@@ -1052,37 +1058,54 @@
         }
     }
 
+    // A Webview class that implements the listener part of the JankTracker requirement. It mirrors
+    // JankActivityTracker in starting and stopping the listener and collection.
     private class AwFrameMetricsListener {
-        private FrameMetricsListener mFrameMetricsListener;
         private boolean mAttached;
+        private JankTrackerStateController mController;
+        private JankTracker mJankTracker;
         private WeakReference<Window> mWindow;
 
         public AwFrameMetricsListener() {
             FrameMetricsStore metricsStore = new FrameMetricsStore();
-            mFrameMetricsListener = new FrameMetricsListener(metricsStore);
+            mController = new JankTrackerStateController(new FrameMetricsListener(metricsStore),
+                    new JankReportingScheduler(metricsStore));
+            mJankTracker = new JankTrackerImpl(mController);
             mAttached = false;
         }
 
         public void attachListener(Window window) {
             if (mAttached) return;
             mWindow = new WeakReference<Window>(window);
-            final Handler handler = new Handler();
-            window.addOnFrameMetricsAvailableListener(mFrameMetricsListener, handler);
+            mController.startMetricCollection(window);
             mAttached = true;
         }
 
         public void detachListener(Window window) {
             if (!mAttached || window != mWindow.get()) return;
-            window.removeOnFrameMetricsAvailableListener(mFrameMetricsListener);
+            mController.stopMetricCollection(window);
             mAttached = false;
         }
 
-        public FrameMetricsListener getFrameMetricsListener() {
-            return mFrameMetricsListener;
+        public void startListening() {
+            if (!mAttached) return;
+            mController.startPeriodicReporting();
+            mController.startMetricCollection(null);
+        }
+
+        public void stopListening() {
+            if (!mAttached) return;
+            mController.stopMetricCollection(null);
+            mController.stopPeriodicReporting();
         }
 
         public void onWebContentsScrollStateUpdate(boolean isScrolling) {
-            mFrameMetricsListener.onWebContentsScrollStateUpdate(isScrolling);
+            if (isScrolling) {
+                mJankTracker.startTrackingScenario(JankScenario.WEBVIEW_SCROLLING);
+            } else {
+                mJankTracker.finishTrackingScenario(JankScenario.WEBVIEW_SCROLLING,
+                        TimeUtils.uptimeMillis() * TimeUtils.NANOSECONDS_PER_MILLISECOND);
+            }
         }
     }
 
@@ -1216,7 +1239,7 @@
             onContainerViewChanged();
         }
 
-        if (AwFeatureMap.isEnabled(AwFeatures.WEBVIEW_REPORT_FRAME_METRICS)) {
+        if (AwFeatureMap.isEnabled(BaseFeatures.COLLECT_ANDROID_FRAME_TIMELINE_METRICS)) {
             mAwFrameMetricsListener = new AwFrameMetricsListener();
         }
     }
@@ -3524,9 +3547,9 @@
 
             if (mAwFrameMetricsListener != null) {
                 if (mIsWindowVisible) {
-                    mAwFrameMetricsListener.getFrameMetricsListener().setIsListenerRecording(true);
+                    mAwFrameMetricsListener.startListening();
                 } else {
-                    mAwFrameMetricsListener.getFrameMetricsListener().setIsListenerRecording(false);
+                    mAwFrameMetricsListener.stopListening();
                 }
             }
         }
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index e08a822..d4909cf 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -406,9 +406,6 @@
             Flag.baseFeature(MetricsFeatures.METRICS_SERVICE_ASYNC_INDEPENDENT_LOGS,
                     "Controls whether the metrics service should finalize certain independent"
                             + " logs asynchronously."),
-            Flag.baseFeature(MetricsFeatures.METRICS_CLEAR_LOGS_ON_CLONED_INSTALL,
-                    "Controls whether UMA logs are cleared when a cloned "
-                            + "install is detected."),
             Flag.baseFeature(MetricsFeatures.MERGE_SUBPROCESS_METRICS_ON_BG_AND_FG,
                     "Controls whether child process histograms are merged on background "
                             + "and foreground."),
@@ -510,7 +507,7 @@
             Flag.baseFeature(VizFeatures.ON_BEGIN_FRAME_THROTTLE_VIDEO,
                     "Enables throttling OnBeginFrame for video frame sinks"
                             + "with a preferred framerate defined."),
-            Flag.baseFeature(AwFeatures.WEBVIEW_REPORT_FRAME_METRICS,
+            Flag.baseFeature(BaseFeatures.COLLECT_ANDROID_FRAME_TIMELINE_METRICS,
                     "Report frame metrics to Google, if metrics reporting has been enabled."),
             Flag.baseFeature(AwFeatures.WEBVIEW_CLEAR_FUNCTOR_IN_BACKGROUND,
                     "Clear the draw functor after some time in background."),
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
index f4d07c2..4c86095 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -47,6 +47,7 @@
 import org.chromium.android_webview.test.TestAwContentsClient.OnDownloadStartHelper;
 import org.chromium.android_webview.test.util.CommonResources;
 import org.chromium.android_webview.test.util.GraphicsTestUtils;
+import org.chromium.base.BaseFeatures;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.FakeTimeTestRule;
 import org.chromium.base.Log;
@@ -1766,7 +1767,7 @@
     @DisableHardwareAcceleration
     @SmallTest
     @Feature({"AndroidWebView"})
-    @Features.EnableFeatures({AwFeatures.WEBVIEW_REPORT_FRAME_METRICS})
+    @Features.EnableFeatures({BaseFeatures.COLLECT_ANDROID_FRAME_TIMELINE_METRICS})
     public void testNoCrashWithoutHardwareAcceleration() throws Throwable {
         mActivityTestRule.startBrowserProcess();
         AwContents.resetRecordMemoryForTesting();
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 730cbe6d..f1cc76c6 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -2925,6 +2925,7 @@
     "//components/sync",
     "//components/url_matcher",
     "//components/user_education/common",
+    "//components/user_education/common:events",
     "//components/user_education/views",
     "//components/user_manager",
     "//components/vector_icons",
@@ -3759,6 +3760,7 @@
     "wm/splitview/split_view_controller_unittest.cc",
     "wm/splitview/split_view_drag_indicators_unittest.cc",
     "wm/splitview/split_view_highlight_view_unittest.cc",
+    "wm/splitview/split_view_metrics_controller_unittest.cc",
     "wm/system_gesture_event_filter_unittest.cc",
     "wm/system_modal_container_layout_manager_unittest.cc",
     "wm/tablet_mode/accelerometer_test_data_literals.cc",
diff --git a/ash/ambient/ambient_controller.cc b/ash/ambient/ambient_controller.cc
index b8588237..40e39a9 100644
--- a/ash/ambient/ambient_controller.cc
+++ b/ash/ambient/ambient_controller.cc
@@ -1213,6 +1213,8 @@
 }
 
 void AmbientController::OnUiLauncherInitialized(bool success) {
+  CHECK(session_metrics_recorder_);
+  session_metrics_recorder_->SetInitStatus(success);
   if (!success) {
     // Success = false denotes a case where the screensaver is in a permanent
     // error state and such that the UI and any further attempts to launch the
diff --git a/ash/ambient/metrics/ambient_session_metrics_recorder.cc b/ash/ambient/metrics/ambient_session_metrics_recorder.cc
index 032fd19f..c983ef0 100644
--- a/ash/ambient/metrics/ambient_session_metrics_recorder.cc
+++ b/ash/ambient/metrics/ambient_session_metrics_recorder.cc
@@ -41,6 +41,12 @@
   if (!ambient_ui_was_rendering && elapsed >= ambient::kMetricsStartupTimeMax) {
     LOG(ERROR) << "Ambient UI completely failed to start";
     ambient::RecordAmbientModeStartupTime(elapsed, ui_settings_);
+    // If `AmbientUiLauncher::Initialize()` never ran the completion callback
+    // within `kMetricsStartupTimeMax`, that still counts as a failure. It
+    // should be completed (either successfully or unsuccessfully by then).
+    if (!session_init_status_.has_value()) {
+      RecordInitStatus(false);
+    }
   }
 
   base::UmaHistogramCounts100(
@@ -48,7 +54,15 @@
       num_registered_screens_);
 }
 
+void AmbientSessionMetricsRecorder::SetInitStatus(bool init_status) {
+  CHECK(!session_init_status_.has_value());
+  session_init_status_ = init_status;
+  RecordInitStatus(init_status);
+}
+
 void AmbientSessionMetricsRecorder::RegisterScreen() {
+  CHECK(session_init_status_.has_value() && session_init_status_.value())
+      << "Ambient UI should not be rendering on screen if init failed";
   ++num_registered_screens_;
   // The very first screen registered means the ambient session has finished
   // initializing the required assets and is starting to render.
@@ -59,4 +73,10 @@
   }
 }
 
+void AmbientSessionMetricsRecorder::RecordInitStatus(bool init_status) {
+  base::UmaHistogramBoolean(
+      base::StrCat({"Ash.AmbientMode.Init.", ui_settings_.ToString()}),
+      init_status);
+}
+
 }  // namespace ash
diff --git a/ash/ambient/metrics/ambient_session_metrics_recorder.h b/ash/ambient/metrics/ambient_session_metrics_recorder.h
index 6b5fc10..a3ef3fd 100644
--- a/ash/ambient/metrics/ambient_session_metrics_recorder.h
+++ b/ash/ambient/metrics/ambient_session_metrics_recorder.h
@@ -8,6 +8,7 @@
 #include "ash/ambient/ambient_ui_settings.h"
 #include "ash/ash_export.h"
 #include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
 
@@ -15,6 +16,9 @@
 // single ambient session:
 // * Construction     - Ambient session starts by preparing any assets needed
 //                      for rendering.
+// * SetInitStatus    - Ambient session is initialized either successfully or
+//                      unsuccessfully. If successful, it can start rendering
+//                      and RegisterScreen() calls can be made.
 // * RegisterScreen() - Ambient session is rendering. There is one call for each
 //                      screen (display).
 // * Destruction      - Ambient session ends.
@@ -28,14 +32,21 @@
       const AmbientSessionMetricsRecorder&) = delete;
   ~AmbientSessionMetricsRecorder();
 
+  // `init_status` should be the result of `AmbientUiLauncher::Initialize()`.
+  // Must only be called once in `AmbientSessionMetricsRecorder`'s lifetime.
+  void SetInitStatus(bool init_status);
+
   // Should be called once per each screen rendering the UI during an ambient
   // session.
   void RegisterScreen();
 
  private:
+  void RecordInitStatus(bool init_status);
+
   const AmbientUiSettings ui_settings_;
   const base::TimeTicks session_start_time_;
   int num_registered_screens_ = 0;
+  absl::optional<bool> session_init_status_;
 };
 
 }  // namespace ash
diff --git a/ash/ambient/metrics/ambient_session_metrics_recorder_unittest.cc b/ash/ambient/metrics/ambient_session_metrics_recorder_unittest.cc
index 7ad6b7e..efc2d23 100644
--- a/ash/ambient/metrics/ambient_session_metrics_recorder_unittest.cc
+++ b/ash/ambient/metrics/ambient_session_metrics_recorder_unittest.cc
@@ -67,6 +67,7 @@
   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
   {
     AmbientSessionMetricsRecorder recorder(GetParam());
+    recorder.SetInitStatus(true);
     recorder.RegisterScreen();
     task_environment()->FastForwardBy(kExpectedEngagementTime);
   }
@@ -82,6 +83,7 @@
   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
   {
     AmbientSessionMetricsRecorder recorder(GetParam());
+    recorder.SetInitStatus(true);
     recorder.RegisterScreen();
     task_environment()->FastForwardBy(kExpectedEngagementTime);
   }
@@ -99,6 +101,7 @@
   base::HistogramTester histogram_tester;
   AmbientSessionMetricsRecorder recorder(GetParam());
   task_environment()->FastForwardBy(kExpectedStartupTime);
+  recorder.SetInitStatus(true);
   recorder.RegisterScreen();
   // Should be ignored. The time that the first screen starts rendering should
   // be when the startup time is recorded.
@@ -119,12 +122,36 @@
   histogram_tester.ExpectUniqueTimeSample(
       base::StrCat({"Ash.AmbientMode.StartupTime.", GetParam().ToString()}),
       kFailedStartupTime, 1);
+  histogram_tester.ExpectUniqueSample(
+      base::StrCat({"Ash.AmbientMode.Init.", GetParam().ToString()}),
+      /*sample=*/0, /*expected_count=*/1);
+}
+
+TEST_P(AmbientSessionMetricsRecorderTest, InitStatusSuccess) {
+  base::HistogramTester histogram_tester;
+  AmbientSessionMetricsRecorder recorder(GetParam());
+  recorder.SetInitStatus(true);
+  recorder.RegisterScreen();
+  recorder.RegisterScreen();
+  histogram_tester.ExpectUniqueSample(
+      base::StrCat({"Ash.AmbientMode.Init.", GetParam().ToString()}),
+      /*sample=*/1, /*expected_count=*/1);
+}
+
+TEST_P(AmbientSessionMetricsRecorderTest, InitStatusFailed) {
+  base::HistogramTester histogram_tester;
+  AmbientSessionMetricsRecorder recorder(GetParam());
+  recorder.SetInitStatus(false);
+  histogram_tester.ExpectUniqueSample(
+      base::StrCat({"Ash.AmbientMode.Init.", GetParam().ToString()}),
+      /*sample=*/0, /*expected_count=*/1);
 }
 
 TEST_P(AmbientSessionMetricsRecorderTest, RecordsScreenCount) {
   base::HistogramTester histogram_tester;
   {
     AmbientSessionMetricsRecorder recorder(GetParam());
+    recorder.SetInitStatus(true);
     recorder.RegisterScreen();
   }
   histogram_tester.ExpectUniqueSample(
@@ -132,6 +159,7 @@
       /*expected_bucket_count=*/1);
   {
     AmbientSessionMetricsRecorder recorder(GetParam());
+    recorder.SetInitStatus(true);
     recorder.RegisterScreen();
     recorder.RegisterScreen();
   }
diff --git a/ash/events/accessibility_event_rewriter_unittest.cc b/ash/events/accessibility_event_rewriter_unittest.cc
index e518365..02e8244 100644
--- a/ash/events/accessibility_event_rewriter_unittest.cc
+++ b/ash/events/accessibility_event_rewriter_unittest.cc
@@ -21,6 +21,7 @@
 #include "ui/base/ime/ash/fake_ime_keyboard.h"
 #include "ui/events/ash/event_rewriter_ash.h"
 #include "ui/events/ash/keyboard_capability.h"
+#include "ui/events/ash/mojom/extended_fkeys_modifier.mojom-shared.h"
 #include "ui/events/ash/mojom/modifier_key.mojom-shared.h"
 #include "ui/events/ash/mojom/six_pack_shortcut_modifier.mojom-shared.h"
 #include "ui/events/ash/pref_names.h"
@@ -235,6 +236,12 @@
       ui::mojom::SixPackShortcutModifier active_modifier,
       int device_id) override {}
 
+  absl::optional<ui::mojom::ExtendedFkeysModifier> GetExtendedFkeySetting(
+      int device_id,
+      ui::KeyboardCode key_code) override {
+    return absl::nullopt;
+  }
+
   std::map<std::string, ui::mojom::ModifierKey> modifier_remapping_;
 };
 
@@ -659,6 +666,12 @@
       ui::mojom::SixPackShortcutModifier active_modifier,
       int device_id) override {}
 
+  absl::optional<ui::mojom::ExtendedFkeysModifier> GetExtendedFkeySetting(
+      int device_id,
+      ui::KeyboardCode key_code) override {
+    return absl::nullopt;
+  }
+
   std::map<std::string, ui::mojom::ModifierKey> modifier_remapping_;
 
  protected:
diff --git a/ash/events/keyboard_capability_unittest.cc b/ash/events/keyboard_capability_unittest.cc
index b2d2dfd3..007834d4 100644
--- a/ash/events/keyboard_capability_unittest.cc
+++ b/ash/events/keyboard_capability_unittest.cc
@@ -219,6 +219,7 @@
   }
 
   void TearDown() override {
+    fake_keyboard_devices_.clear();
     keyboard_capability_.reset();
     AshTestBase::TearDown();
   }
@@ -234,6 +235,8 @@
 
     keyboard_capability_->SetKeyboardInfoForTesting(fake_keyboard,
                                                     std::move(keyboard_info));
+    fake_keyboard_devices_.push_back(fake_keyboard);
+    ui::DeviceDataManagerTestApi().SetKeyboardDevices(fake_keyboard_devices_);
 
     return fake_keyboard;
   }
@@ -241,6 +244,7 @@
  protected:
   std::unique_ptr<ui::KeyboardCapability> keyboard_capability_;
   std::unique_ptr<FakeDeviceManager> fake_keyboard_manager_;
+  std::vector<ui::KeyboardDevice> fake_keyboard_devices_;
 };
 
 TEST_F(KeyboardCapabilityTest, TestIsSixPackKey) {
diff --git a/ash/game_dashboard/game_dashboard_context.cc b/ash/game_dashboard/game_dashboard_context.cc
index 694d1147..2098b18b4 100644
--- a/ash/game_dashboard/game_dashboard_context.cc
+++ b/ash/game_dashboard/game_dashboard_context.cc
@@ -8,14 +8,17 @@
 #include <string>
 
 #include "ash/game_dashboard/game_dashboard_button.h"
+#include "ash/game_dashboard/game_dashboard_controller.h"
 #include "ash/game_dashboard/game_dashboard_main_menu_view.h"
 #include "ash/game_dashboard/game_dashboard_toolbar_view.h"
 #include "ash/game_dashboard/game_dashboard_widget.h"
+#include "base/check_op.h"
 #include "base/i18n/time_formatting.h"
 #include "chromeos/ui/frame/frame_header.h"
 #include "ui/aura/window.h"
 #include "ui/base/l10n/time_format.h"
 #include "ui/compositor/layer.h"
+#include "ui/events/types/event_type.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/transform.h"
 #include "ui/views/animation/animation_builder.h"
@@ -65,6 +68,81 @@
 
 }  // namespace
 
+// Monitors input events that occur on the `game_dashboard_button_widget_` to
+// determine whether an event should be consumed or passed onto the
+// `game_dashboard_button_widget_`.
+class GameDashboardButtonInputMonitor : public ui::EventHandler {
+ public:
+  explicit GameDashboardButtonInputMonitor(GameDashboardContext* context)
+      : context_(context) {}
+  GameDashboardButtonInputMonitor(const GameDashboardButtonInputMonitor&) =
+      delete;
+  GameDashboardButtonInputMonitor& operator=(
+      const GameDashboardButtonInputMonitor&) = delete;
+  ~GameDashboardButtonInputMonitor() override = default;
+
+  // ui::EventHandler:
+  void OnEvent(ui::Event* event) override {
+    if (ShouldConsumeEvent(event->type())) {
+      event->StopPropagation();
+      event->SetHandled();
+    }
+  }
+
+ private:
+  bool ShouldConsumeEvent(ui::EventType event_type) {
+    // Since the `main_menu_view_` closes itself whenever any touch occurs
+    // outside its bounds, it will duplicate the work of the
+    // `main_menu_button_`'s NotifyClick(). To avoid toggling the
+    // `main_menu_view_` visibility twice, determine whether this event should
+    // be consumed or passed onto the `main_menu_button_`.
+    GameDashboardMainMenuView* main_menu_view = context_->main_menu_view();
+    switch (event_type) {
+      case ui::ET_MOUSE_PRESSED:
+        ignore_next_mouse_released_gesture = main_menu_view;
+        break;
+      case ui::ET_GESTURE_TAP_DOWN:
+        ignore_next_tap_gesture_ = main_menu_view;
+        break;
+      case ui::ET_GESTURE_TAP:
+        if (ignore_next_tap_gesture_) {
+          ignore_next_tap_gesture_ = false;
+          return true;
+        }
+        break;
+      case ui::ET_MOUSE_RELEASED:
+        if (ignore_next_mouse_released_gesture) {
+          ignore_next_mouse_released_gesture = false;
+          return true;
+        }
+        break;
+      case ui::ET_GESTURE_TAP_CANCEL:
+      case ui::ET_GESTURE_END:
+      case ui::ET_GESTURE_SCROLL_END:
+        // Reset params for next `ui::ET_GESTURE_TAP_DOWN` event.
+        ignore_next_tap_gesture_ = false;
+        break;
+      default:
+        break;
+    }
+
+    return false;
+  }
+
+  // Allows this class to access `GameDashboardContext` owned functions/objects.
+  const raw_ptr<GameDashboardContext, ExperimentalAsh> context_;
+
+  // When an initial mouse/touch interaction occurs, the `main_menu_view_`
+  // is destroyed on the `ui::ET_MOUSE_PRESSED`/`ui::ET_GESTURE_TAP_DOWN`
+  // events. However, the `main_menu_button_` won't be notified about the click
+  // until the `ui::ET_MOUSE_RELEASED`/`ui::ET_GESTURE_TAP` event. To prevent
+  // the button from receiving its OnClick() event after the `main_menu_view_`
+  // has already closed itself, utilize these variables to notify that the next
+  // `ui::ET_MOUSE_RELEASED` or `ui::ET_GESTURE_TAP` event should be consumed.
+  bool ignore_next_mouse_released_gesture = false;
+  bool ignore_next_tap_gesture_ = false;
+};
+
 GameDashboardContext::GameDashboardContext(aura::Window* game_window)
     : game_window_(game_window),
       toolbar_snap_location_(ToolbarSnapLocation::kTopRight) {
@@ -102,17 +180,20 @@
     main_menu_widget_ =
         base::WrapUnique(views::BubbleDialogDelegateView::CreateBubble(
             std::move(widget_delegate)));
+    main_menu_widget_->AddObserver(this);
     main_menu_widget_->Show();
     game_dashboard_button_->SetToggled(true);
   } else {
+    DCHECK(main_menu_view_);
+    DCHECK(main_menu_widget_);
     CloseMainMenu();
   }
 }
 
 void GameDashboardContext::CloseMainMenu() {
-  DCHECK(main_menu_view_);
-  DCHECK(main_menu_widget_.get());
   main_menu_view_ = nullptr;
+  DCHECK(main_menu_widget_);
+  main_menu_widget_->RemoveObserver(this);
   main_menu_widget_.reset();
   game_dashboard_button_->SetToggled(false);
 }
@@ -202,6 +283,12 @@
   UpdateGameDashboardButtonWidgetBounds();
 }
 
+void GameDashboardContext::OnWidgetDestroying(views::Widget* widget) {
+  DCHECK(main_menu_view_);
+  DCHECK_EQ(widget, main_menu_view_->GetWidget());
+  main_menu_view_ = nullptr;
+}
+
 void GameDashboardContext::CreateAndAddGameDashboardButtonWidget() {
   auto game_dashboard_button = std::make_unique<GameDashboardButton>(
       base::BindRepeating(&GameDashboardContext::OnGameDashboardButtonPressed,
@@ -211,6 +298,11 @@
   game_dashboard_button_ = game_dashboard_button.get();
   game_dashboard_button_widget_ = CreateTransientChildWidget(
       game_window_, "GameDashboardButton", std::move(game_dashboard_button));
+  game_dashboard_button_input_monitor_ =
+      std::make_unique<GameDashboardButtonInputMonitor>(this);
+  game_dashboard_button_widget_->GetContentsView()->AddPreTargetHandler(
+      game_dashboard_button_input_monitor_.get(),
+      ui::EventTarget::Priority::kSystem);
   DCHECK_EQ(
       game_window_,
       wm::GetTransientParent(game_dashboard_button_widget_->GetNativeWindow()));
diff --git a/ash/game_dashboard/game_dashboard_context.h b/ash/game_dashboard/game_dashboard_context.h
index 4a0ec1b..77f50ad8 100644
--- a/ash/game_dashboard/game_dashboard_context.h
+++ b/ash/game_dashboard/game_dashboard_context.h
@@ -21,13 +21,15 @@
 namespace ash {
 
 class GameDashboardButton;
+class GameDashboardButtonInputMonitor;
 class GameDashboardMainMenuView;
 class GameDashboardToolbarView;
 class GameDashboardWidget;
 
 // This class manages Game Dashboard related UI for a given `aura::Window`, and
 // its instance is managed by the `GameDashboardController`.
-class ASH_EXPORT GameDashboardContext : public views::ViewObserver {
+class ASH_EXPORT GameDashboardContext : public views::ViewObserver,
+                                        public views::WidgetObserver {
  public:
   // Indicator for the 4 quadrants that the toolbar is able to be placed.
   enum class ToolbarSnapLocation {
@@ -44,6 +46,8 @@
 
   aura::Window* game_window() { return game_window_.get(); }
 
+  GameDashboardMainMenuView* main_menu_view() { return main_menu_view_; }
+
   GameDashboardWidget* game_dashboard_button_widget() {
     return game_dashboard_button_widget_.get();
   }
@@ -72,8 +76,6 @@
   // Closes the main menu. Clears `main_menu_widget_` and `main_menu_view_`.
   void CloseMainMenu();
 
-  bool IsMainMenuOpen() const { return main_menu_view_; }
-
   // Toggles the creation/deletion of the toolbar within the game window.
   // Returns the toolbar visibility state.
   bool ToggleToolbar();
@@ -99,6 +101,9 @@
   // views::ViewObserver:
   void OnViewPreferredSizeChanged(views::View* observed_view) override;
 
+  // views::WidgetObserver:
+  void OnWidgetDestroying(views::Widget* widget) override;
+
  private:
   friend class GameDashboardContextTestApi;
 
@@ -144,6 +149,10 @@
   raw_ptr<GameDashboardButton, ExperimentalAsh> game_dashboard_button_ =
       nullptr;
 
+  // Monitors mouse and touch input for `game_dashboard_button_widget_`.
+  std::unique_ptr<GameDashboardButtonInputMonitor>
+      game_dashboard_button_input_monitor_;
+
   // The `GameDashboardMainMenuView` when the user presses the Game Dashboard
   // button.
   // Owned by the views hierarchy.
diff --git a/ash/game_dashboard/game_dashboard_context_test_api.cc b/ash/game_dashboard/game_dashboard_context_test_api.cc
index 50fc8e6..0c3bd90b 100644
--- a/ash/game_dashboard/game_dashboard_context_test_api.cc
+++ b/ash/game_dashboard/game_dashboard_context_test_api.cc
@@ -21,6 +21,7 @@
 #include "ui/events/test/event_generator.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view_utils.h"
+#include "ui/wm/core/window_util.h"
 
 namespace ash {
 
@@ -63,7 +64,7 @@
 }
 
 GameDashboardMainMenuView* GameDashboardContextTestApi::GetMainMenuView() {
-  return context_->main_menu_view_;
+  return context_->main_menu_view();
 }
 
 FeatureTile* GameDashboardContextTestApi::GetMainMenuGameControlsTile() {
@@ -134,6 +135,9 @@
   auto* game_dashboard_button = GetGameDashboardButton();
   ASSERT_TRUE(game_dashboard_button);
   ClickOnView(game_dashboard_button, event_generator_);
+  // Pause to ensure any other open main menu views have had time to auto-close
+  // and notify the `GameDashboardContext` that it's been destroyed.
+  base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(GetMainMenuView());
   ASSERT_TRUE(GetMainMenuWidget());
 }
@@ -144,6 +148,9 @@
   auto* game_dashboard_button = GetGameDashboardButton();
   ASSERT_TRUE(game_dashboard_button);
   ClickOnView(game_dashboard_button, event_generator_);
+  // Pause to ensure the main menu view has had time to auto-close itself and
+  // notify the `GameDashboardContext` that it's been destroyed.
+  base::RunLoop().RunUntilIdle();
   ASSERT_FALSE(GetMainMenuView());
   ASSERT_FALSE(GetMainMenuWidget());
 }
diff --git a/ash/game_dashboard/game_dashboard_context_test_api.h b/ash/game_dashboard/game_dashboard_context_test_api.h
index 060a94ef..1698163 100644
--- a/ash/game_dashboard/game_dashboard_context_test_api.h
+++ b/ash/game_dashboard/game_dashboard_context_test_api.h
@@ -73,12 +73,14 @@
 
   // Opens the main menu.
   // Before opening the main menu, verifies that the main menu is closed.
-  // After opening the main menu, verifies it opened.
+  // After opening the main menu, verifies it opened and waits for the thread to
+  // become idle to ensure that all open `GameDashboardMainMenuView`s close.
   void OpenTheMainMenu();
 
   // Closes the main menu.
   // Before closing the main menu, verifies that the main menu is open.
-  // After closing the main menu, verifies is closed.
+  // After closing the main menu, verifies is closed and waits for the thread to
+  // become idle to ensure that all open `GameDashboardMainMenuView`s close.
   void CloseTheMainMenu();
 
   // Returns the toolbar widget and all its views.
diff --git a/ash/game_dashboard/game_dashboard_context_unittest.cc b/ash/game_dashboard/game_dashboard_context_unittest.cc
index ac0dbdeb..0afc22d 100644
--- a/ash/game_dashboard/game_dashboard_context_unittest.cc
+++ b/ash/game_dashboard/game_dashboard_context_unittest.cc
@@ -285,6 +285,7 @@
     wm::ActivateWindow(recording_window);
 
     // Start recording recording_window.
+    recording_window_test_api->OpenTheMainMenu();
     LeftClickOn(recording_window_test_api->GetMainMenuRecordGameTile());
     ClickOnStartRecordingButtonInCaptureModeBarView();
 
@@ -302,33 +303,27 @@
     VerifyGameDashboardButtonState(other_window_test_api,
                                    /*is_recording=*/false);
 
-    // Retrieve the record game buttons from both windows.
-    auto* recording_window_record_game_tile =
-        recording_window_test_api->GetMainMenuRecordGameTile();
-    ASSERT_TRUE(recording_window_record_game_tile);
-    auto* recording_window_record_game_button =
-        recording_window_test_api->GetToolbarRecordGameButton();
-    ASSERT_TRUE(recording_window_record_game_button);
-    auto* other_window_record_game_tile =
-        other_window_test_api->GetMainMenuRecordGameTile();
-    ASSERT_TRUE(other_window_record_game_tile);
-    auto* other_window_record_game_button =
-        other_window_test_api->GetToolbarRecordGameButton();
-    ASSERT_TRUE(other_window_record_game_button);
+    // Retrieve the record game buttons for the `recording_window` and verify
+    // they're enabled and toggled on.
+    VerifyRecordGameStatus(
+        recording_window_test_api->GetMainMenuRecordGameTile(),
+        recording_window_test_api->GetToolbarRecordGameButton(),
+        /*enabled=*/true, /*toggled=*/true);
 
-    // Verify the recording_window's buttons are enabled and toggled on.
-    EXPECT_TRUE(recording_window_record_game_tile->GetEnabled());
-    EXPECT_TRUE(recording_window_record_game_tile->IsToggled());
-    EXPECT_TRUE(recording_window_record_game_button->GetEnabled());
-    EXPECT_TRUE(recording_window_record_game_button->toggled());
+    // Retrieve the record game buttons for the `other_window`.
+    auto* other_window = other_window_test_api->context()->game_window();
+    wm::ActivateWindow(other_window);
+    other_window_test_api->OpenTheMainMenu();
 
-    // Verify the other window's buttons are disabled and toggled off.
-    EXPECT_FALSE(other_window_record_game_tile->GetEnabled());
-    EXPECT_FALSE(other_window_record_game_tile->IsToggled());
-    EXPECT_FALSE(other_window_record_game_button->GetEnabled());
-    EXPECT_FALSE(other_window_record_game_button->toggled());
+    // Retrieve the record game buttons for the `other_window` and verify
+    // they're disabled and toggled off.
+    VerifyRecordGameStatus(other_window_test_api->GetMainMenuRecordGameTile(),
+                           other_window_test_api->GetToolbarRecordGameButton(),
+                           /*enabled=*/false, /*toggled=*/false);
 
     // Stop the video recording session.
+    wm::ActivateWindow(recording_window);
+    recording_window_test_api->OpenTheMainMenu();
     LeftClickOn(recording_window_test_api->GetMainMenuRecordGameTile());
     EXPECT_FALSE(CaptureModeController::Get()->is_recording_in_progress());
     WaitForCaptureFileToBeSaved();
@@ -336,17 +331,19 @@
     // TODO(b/286889161): Update the record game button pointers after the bug
     // has been addressed. The main menu will no longer remain open, which makes
     // button pointers invalid.
-    // Verify all the record game buttons are enabled and toggled off.
-    EXPECT_TRUE(recording_window_record_game_tile->GetEnabled());
-    EXPECT_TRUE(recording_window_record_game_button->GetEnabled());
-    EXPECT_TRUE(other_window_record_game_tile->GetEnabled());
-    EXPECT_TRUE(other_window_record_game_button->GetEnabled());
+    // Verify all the record game buttons for the `recording_window` are enabled
+    // and toggled off.
+    VerifyRecordGameStatus(
+        recording_window_test_api->GetMainMenuRecordGameTile(),
+        recording_window_test_api->GetToolbarRecordGameButton(),
+        /*enabled=*/true, /*toggled=*/false);
 
-    // Verify all the record game buttons are toggled off.
-    EXPECT_FALSE(recording_window_record_game_tile->IsToggled());
-    EXPECT_FALSE(recording_window_record_game_button->toggled());
-    EXPECT_FALSE(other_window_record_game_tile->IsToggled());
-    EXPECT_FALSE(other_window_record_game_button->toggled());
+    // Verify all the `other_window` buttons are enabled and toggled off.
+    wm::ActivateWindow(other_window);
+    other_window_test_api->OpenTheMainMenu();
+    VerifyRecordGameStatus(other_window_test_api->GetMainMenuRecordGameTile(),
+                           other_window_test_api->GetToolbarRecordGameButton(),
+                           /*enabled=*/true, /*toggled=*/false);
 
     // Verify the recording timer is not running in both windows.
     EXPECT_FALSE(recording_window_timer.IsRunning());
@@ -358,12 +355,29 @@
     VerifyGameDashboardButtonState(other_window_test_api,
                                    /*is_recording=*/false);
 
-    // Close the toolbar and main menu in both windows.
-    for (auto* test_api : {recording_window_test_api, other_window_test_api}) {
-      wm::ActivateWindow(test_api->context()->game_window());
-      test_api->CloseTheToolbar();
-      test_api->CloseTheMainMenu();
-    }
+    // Close the toolbar and main menu in the `other_window`, which is currently
+    // open.
+    other_window_test_api->CloseTheToolbar();
+    other_window_test_api->CloseTheMainMenu();
+
+    // Open the main menu of the recording window to close the toolbar and then
+    // the main menu.
+    wm::ActivateWindow(recording_window);
+    recording_window_test_api->OpenTheMainMenu();
+    recording_window_test_api->CloseTheToolbar();
+    recording_window_test_api->CloseTheMainMenu();
+  }
+
+  void VerifyRecordGameStatus(FeatureTile* game_tile,
+                              IconButton* game_button,
+                              bool enabled,
+                              bool toggled) {
+    ASSERT_TRUE(game_tile);
+    ASSERT_TRUE(game_button);
+    EXPECT_EQ(enabled, game_tile->GetEnabled());
+    EXPECT_EQ(enabled, game_button->GetEnabled());
+    EXPECT_EQ(toggled, game_tile->IsToggled());
+    EXPECT_EQ(toggled, game_button->toggled());
   }
 
   void PressKeyAndVerify(ui::KeyboardCode key,
@@ -406,6 +420,11 @@
         }
         break;
     }
+
+    // Dragging the toolbar causes the main menu to close asynchronously. Run
+    // until idle to ensure that this posted task runs synchronously and
+    // completes before proceeding.
+    base::RunLoop().RunUntilIdle();
   }
 };
 
@@ -733,6 +752,32 @@
   test_api_->CloseTheMainMenu();
 }
 
+// Verifies clicking outside the main menu view will close the main menu
+// widget. Then, clicking on the main menu button will still toggle the main
+// menu widget visibility.
+TEST_P(GameTypeGameDashboardContextTest, CloseMainMenuOutsideButtonWidget) {
+  // Open the main menu widget and verify the main menu open.
+  test_api_->OpenTheMainMenu();
+
+  // Close the main menu dialog by clicking outside the main menu view bounds.
+  ui::test::EventGenerator* event_generator = GetEventGenerator();
+  const gfx::Point& new_location = {kAppBounds.x() + kAppBounds.width(),
+                                    kAppBounds.y() + kAppBounds.height()};
+  event_generator->set_current_screen_location(new_location);
+  event_generator->ClickLeftButton();
+
+  // Clicking outside the main menu causes the main menu to close
+  // asynchronously. Run until idle to ensure that this posted task runs
+  // synchronously and completes before proceeding.
+  base::RunLoop().RunUntilIdle();
+
+  // Open the main menu widget via the main menu button.
+  test_api_->OpenTheMainMenu();
+
+  // Close the main menu widget via the main menu button.
+  test_api_->CloseTheMainMenu();
+}
+
 // Verifies the main menu shows all items allowed.
 TEST_P(GameTypeGameDashboardContextTest,
        MainMenuDialogWidget_AvailableFeatures) {
@@ -1148,6 +1193,7 @@
 
   // Hide then show the toolbar and verify the toolbar was placed back into the
   // bottom left quadrant.
+  test_api_->OpenTheMainMenu();
   test_api_->CloseTheToolbar();
   test_api_->OpenTheToolbar();
   EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
diff --git a/ash/game_dashboard/game_dashboard_controller.cc b/ash/game_dashboard/game_dashboard_controller.cc
index b7cb1c7a..6fdcbbb 100644
--- a/ash/game_dashboard/game_dashboard_controller.cc
+++ b/ash/game_dashboard/game_dashboard_controller.cc
@@ -177,7 +177,7 @@
   // main menu.
   for (auto const& [_, context] : game_window_contexts_) {
     context->game_dashboard_button_widget()->Hide();
-    if (context->IsMainMenuOpen()) {
+    if (context->main_menu_view()) {
       context->CloseMainMenu();
     }
   }
diff --git a/ash/game_dashboard/game_dashboard_main_menu_view.cc b/ash/game_dashboard/game_dashboard_main_menu_view.cc
index 502b8ad..0b3bc24c 100644
--- a/ash/game_dashboard/game_dashboard_main_menu_view.cc
+++ b/ash/game_dashboard/game_dashboard_main_menu_view.cc
@@ -232,7 +232,7 @@
   DCHECK(context_->game_dashboard_button_widget());
 
   set_corner_radius(kBubbleCornerRadius);
-  set_close_on_deactivate(false);
+  set_close_on_deactivate(true);
   set_internal_name("GameDashboardMainMenuView");
   set_margins(gfx::Insets());
   set_parent_window(
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index 9267b56c..d5afcf2 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -116,7 +116,7 @@
   SplitViewController* split_view_controller() {
     return split_view_controller_.get();
   }
-  const SplitViewOverviewSession* split_view_overview_session() const {
+  SplitViewOverviewSession* split_view_overview_session() {
     return split_view_overview_session_.get();
   }
 
diff --git a/ash/system/input_device_settings/input_device_settings_metrics_manager.cc b/ash/system/input_device_settings/input_device_settings_metrics_manager.cc
index a367633..3b46750 100644
--- a/ash/system/input_device_settings/input_device_settings_metrics_manager.cc
+++ b/ash/system/input_device_settings/input_device_settings_metrics_manager.cc
@@ -208,6 +208,23 @@
                        is_initial_value ? ".Initial" : ".Changed"});
 }
 
+void RecordKeyboardNumberOfKeysRemapped(const mojom::Keyboard& keyboard) {
+  base::flat_map<ui::mojom::ModifierKey, ui::mojom::ModifierKey>
+      default_remappings;
+  if (keyboard.meta_key == mojom::MetaKey::kCommand) {
+    default_remappings[ui::mojom::ModifierKey::kControl] =
+        ui::mojom::ModifierKey::kMeta;
+    default_remappings[ui::mojom::ModifierKey::kMeta] =
+        ui::mojom::ModifierKey::kControl;
+  }
+  const int num_keys_remapped = GetNumberOfNonDefaultRemappings(
+      *keyboard.settings, std::move(default_remappings));
+  const std::string keyboard_metrics =
+      base::StrCat({GetKeyboardMetricsPrefix(keyboard),
+                    "Modifiers.NumberOfRemappedKeysOnStart"});
+  base::UmaHistogramCounts100(keyboard_metrics, num_keys_remapped);
+}
+
 }  // namespace
 
 InputDeviceSettingsMetricsManager::InputDeviceSettingsMetricsManager() =
@@ -266,24 +283,6 @@
   }
 }
 
-void InputDeviceSettingsMetricsManager::RecordKeyboardNumberOfKeysRemapped(
-    const mojom::Keyboard& keyboard) {
-  base::flat_map<ui::mojom::ModifierKey, ui::mojom::ModifierKey>
-      default_remappings;
-  if (keyboard.meta_key == mojom::MetaKey::kCommand) {
-    default_remappings[ui::mojom::ModifierKey::kControl] =
-        ui::mojom::ModifierKey::kMeta;
-    default_remappings[ui::mojom::ModifierKey::kMeta] =
-        ui::mojom::ModifierKey::kControl;
-  }
-  const int num_keys_remapped = GetNumberOfNonDefaultRemappings(
-      *keyboard.settings, std::move(default_remappings));
-  const std::string keyboard_metrics =
-      base::StrCat({GetKeyboardMetricsPrefix(keyboard),
-                    "Modifiers.NumberOfRemappedKeysOnStart"});
-  base::UmaHistogramCounts100(keyboard_metrics, num_keys_remapped);
-}
-
 void InputDeviceSettingsMetricsManager::RecordKeyboardChangedMetrics(
     const mojom::Keyboard& keyboard,
     const mojom::KeyboardSettings& old_settings) {
diff --git a/ash/system/input_device_settings/input_device_settings_metrics_manager.h b/ash/system/input_device_settings/input_device_settings_metrics_manager.h
index fb9325c..a5fe8eee 100644
--- a/ash/system/input_device_settings/input_device_settings_metrics_manager.h
+++ b/ash/system/input_device_settings/input_device_settings_metrics_manager.h
@@ -50,7 +50,6 @@
                                             const mojom::Mouse& mouse);
 
  private:
-  void RecordKeyboardNumberOfKeysRemapped(const mojom::Keyboard& keyboard);
   base::flat_map<AccountId, base::flat_set<std::string>> recorded_keyboards_;
   base::flat_map<AccountId, base::flat_set<std::string>> recorded_mice_;
   base::flat_map<AccountId, base::flat_set<std::string>>
diff --git a/ash/user_education/user_education_util.cc b/ash/user_education/user_education_util.cc
index c94bef5..888acfcb 100644
--- a/ash/user_education/user_education_util.cc
+++ b/ash/user_education/user_education_util.cc
@@ -19,6 +19,7 @@
 #include "base/unguessable_token.h"
 #include "components/account_id/account_id.h"
 #include "components/session_manager/session_manager_types.h"
+#include "components/user_education/common/events.h"
 #include "components/user_education/common/help_bubble.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/aura/window.h"
diff --git a/ash/user_education/welcome_tour/welcome_tour_controller.cc b/ash/user_education/welcome_tour/welcome_tour_controller.cc
index dbbcd9d..9ae15b6 100644
--- a/ash/user_education/welcome_tour/welcome_tour_controller.cc
+++ b/ash/user_education/welcome_tour/welcome_tour_controller.cc
@@ -34,6 +34,7 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/timer/elapsed_timer.h"
+#include "components/user_education/common/events.h"
 #include "components/user_education/common/help_bubble.h"
 #include "components/user_education/common/tutorial_description.h"
 #include "components/user_manager/user_type.h"
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 793110d..50f1316 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -5869,7 +5869,7 @@
   EXPECT_EQ(0, observer.daily_refresh_checkpoint_count());
   // User's wallpaper info should exist.
   pref_manager_->SetUserWallpaperInfo(kAccountId1,
-                                      InfoWithType(WallpaperType::kDaily));
+                                      InfoWithType(WallpaperType::kDefault));
   SimulateUserLogin(kAccountId1);
   // Clears signal on login.
   observer.ClearDailyRefreshCheckpointCount();
diff --git a/ash/webui/diagnostics_ui/backend/input/input_data_provider_unittest.cc b/ash/webui/diagnostics_ui/backend/input/input_data_provider_unittest.cc
index 390e68fa..d169351 100644
--- a/ash/webui/diagnostics_ui/backend/input/input_data_provider_unittest.cc
+++ b/ash/webui/diagnostics_ui/backend/input/input_data_provider_unittest.cc
@@ -658,6 +658,12 @@
       ui::mojom::SixPackShortcutModifier active_modifier,
       int device_id) override {}
 
+  absl::optional<ui::mojom::ExtendedFkeysModifier> GetExtendedFkeySetting(
+      int device_id,
+      ui::KeyboardCode key_code) override {
+    return absl::nullopt;
+  }
+
  protected:
   bool suppress_modifier_key_rewrites_ = false;
 };
diff --git a/ash/webui/scanning/resources/BUILD.gn b/ash/webui/scanning/resources/BUILD.gn
index 503857f..565bab2 100644
--- a/ash/webui/scanning/resources/BUILD.gn
+++ b/ash/webui/scanning/resources/BUILD.gn
@@ -57,7 +57,7 @@
     "mojo_interface_provider.ts",
     "scanning_app_types.js",
     "scanning_app_util.ts",
-    "scanning_browser_proxy.js",
+    "scanning_browser_proxy.ts",
     "select_mixin.ts",
   ]
 
@@ -73,6 +73,8 @@
 
   ts_tsconfig_base = "tsconfig.json"
 
+  ts_definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ]
+
   ts_deps = [
     "//ash/webui/common/resources:build_ts",
     "//third_party/polymer/v3_0:library",
diff --git a/ash/webui/scanning/resources/scanning_browser_proxy.js b/ash/webui/scanning/resources/scanning_browser_proxy.js
deleted file mode 100644
index c501a4dd..0000000
--- a/ash/webui/scanning/resources/scanning_browser_proxy.js
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A helper object used by the Scanning App UI in ash/ to
- * provide access to the ScanningHandler which invokes functions that only exist
- * in chrome/.
- */
-
-import {sendWithPromise} from 'chrome://resources/ash/common/cr.m.js';
-
-import {ColorMode, FileType, PageSize, SourceType} from './scanning.mojom-webui.js';
-import {ScanCompleteAction, ScanJobSettingsForMetrics} from './scanning_app_types.js';
-
-/**
- * @typedef {{
- *   baseName: string,
- *   filePath: string,
- * }}
- */
-export let SelectedPath;
-
-/** @interface */
-export class ScanningBrowserProxy {
-  /** Initialize ScanningHandler. */
-  initialize() {}
-
-  /**
-   * Requests the user to choose the directory to save scans.
-   * @return {!Promise<!SelectedPath>}
-   */
-  requestScanToLocation() {}
-
-  /**
-   * Opens the Files app with the file |pathToFile| highlighted.
-   * @param {string} pathToFile
-   * @return {!Promise<boolean>} True if the file is found and Files app opens.
-   */
-  showFileInLocation(pathToFile) {}
-
-  /**
-   * Returns a localized, pluralized string for |name| based on |count|.
-   * @param {string} name
-   * @param {number} count
-   * @return {!Promise<string>}
-   */
-  getPluralString(name, count) {}
-
-  /**
-   * Records the settings for a scan job.
-   * @param {!ScanJobSettingsForMetrics} scanJobSettings
-   */
-  recordScanJobSettings(scanJobSettings) {}
-
-  /**
-   * Returns the MyFiles path for the current user.
-   * @return {!Promise<string>}
-   */
-  getMyFilesPath() {}
-
-  /**
-   * Opens the Media app with the files specified in |filePaths|.
-   * @param {!Array<string>} filePaths
-   */
-  openFilesInMediaApp(filePaths) {}
-
-  /**
-   * Records the action taken after a completed scan job.
-   * @param {!ScanCompleteAction} action
-   */
-  recordScanCompleteAction(action) {}
-
-  /**
-   * Records the number of scan setting changes before a scan is initiated.
-   * @param {number} numChanges
-   */
-  recordNumScanSettingChanges(numChanges) {}
-
-  /**
-   * Saves scan settings to the Prefs service.
-   * @param {string} scanSettings
-   */
-  saveScanSettings(scanSettings) {}
-
-  /**
-   * Returns the saved scan settings from the Prefs service.
-   * @return {!Promise<string>}
-   */
-  getScanSettings() {}
-
-  /**
-   * Validates that |filePath| exists on the local filesystem and returns its
-   * display name. If |filePath| doesn't exist, return an empty SelectedPath.
-   * @param {string} filePath
-   * @return {!Promise<!SelectedPath>}
-   */
-  ensureValidFilePath(filePath) {}
-
-  /**
-   * Records the number of completed scans during a session of the Scan app
-   * being open.
-   * @param {number} numCompletedScans
-   */
-  recordNumCompletedScans(numCompletedScans) {}
-}
-
-/** @implements {ScanningBrowserProxy} */
-export class ScanningBrowserProxyImpl {
-  /** @override */
-  initialize() {
-    chrome.send('initialize');
-  }
-
-  /** @override */
-  requestScanToLocation() {
-    return sendWithPromise('requestScanToLocation');
-  }
-
-  /** @override */
-  showFileInLocation(pathToFile) {
-    return sendWithPromise('showFileInLocation', pathToFile);
-  }
-
-  /** @override */
-  getPluralString(name, count) {
-    return sendWithPromise('getPluralString', name, count);
-  }
-
-  /** @override */
-  recordScanJobSettings(scanJobSettings) {
-    chrome.send('recordScanJobSettings', [scanJobSettings]);
-  }
-
-  /** @override */
-  getMyFilesPath() {
-    return sendWithPromise('getMyFilesPath');
-  }
-
-  /** @override */
-  openFilesInMediaApp(filePaths) {
-    chrome.send('openFilesInMediaApp', [filePaths]);
-  }
-
-  /** @override */
-  recordScanCompleteAction(action) {
-    chrome.send('recordScanCompleteAction', [action]);
-  }
-
-  /** @override */
-  recordNumScanSettingChanges(numChanges) {
-    chrome.send('recordNumScanSettingChanges', [numChanges]);
-  }
-
-  /** @override */
-  saveScanSettings(scanSettings) {
-    chrome.send('saveScanSettings', [scanSettings]);
-  }
-
-  /** @override */
-  getScanSettings() {
-    return sendWithPromise('getScanSettings');
-  }
-
-  /** @override */
-  ensureValidFilePath(filePath) {
-    return sendWithPromise('ensureValidFilePath', filePath);
-  }
-
-  /** @override */
-  recordNumCompletedScans(numCompletedScans) {
-    chrome.send('recordNumCompletedScans', [numCompletedScans]);
-  }
-
-  /** @return {!ScanningBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new ScanningBrowserProxyImpl());
-  }
-
-  /** @param {!ScanningBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
-}
-
-/** @type {?ScanningBrowserProxy} */
-let instance = null;
diff --git a/ash/webui/scanning/resources/scanning_browser_proxy.ts b/ash/webui/scanning/resources/scanning_browser_proxy.ts
new file mode 100644
index 0000000..91adcfd
--- /dev/null
+++ b/ash/webui/scanning/resources/scanning_browser_proxy.ts
@@ -0,0 +1,149 @@
+// Copyright 2020 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A helper object used by the Scanning App UI in ash/ to
+ * provide access to the ScanningHandler which invokes functions that only exist
+ * in chrome/.
+ */
+
+import {sendWithPromise} from 'chrome://resources/ash/common/cr.m.js';
+
+import {ScanCompleteAction, ScanJobSettingsForMetrics} from './scanning_app_types.js';
+
+export interface SelectedPath {
+  baseName: string;
+  filePath: string;
+}
+
+export interface ScanningBrowserProxy {
+  initialize(): void;
+
+  /**
+   * Requests the user to choose the directory to save scans.
+   */
+  requestScanToLocation(): Promise<SelectedPath>;
+
+  /**
+   * Opens the Files app with the file |pathToFile| highlighted. Returns true
+   * if the file is found and Files app opens.
+   */
+  showFileInLocation(pathToFile: string): Promise<boolean>;
+
+  /**
+   * Returns a localized, pluralized string for |name| based on |count|.
+   */
+  getPluralString(name: string, count: number): Promise<string>;
+
+  /**
+   * Records the settings for a scan job.
+   */
+  recordScanJobSettings(scanJobSettings: ScanJobSettingsForMetrics): void;
+
+  /**
+   * Returns the MyFiles path for the current user.
+   */
+  getMyFilesPath(): Promise<string>;
+
+  /**
+   * Opens the Media app with the files specified in |filePaths|.
+   */
+  openFilesInMediaApp(filePaths: string[]): void;
+
+  /**
+   * Records the action taken after a completed scan job.
+   */
+  recordScanCompleteAction(action: ScanCompleteAction): void;
+
+  /**
+   * Records the number of scan setting changes before a scan is initiated.
+   */
+  recordNumScanSettingChanges(numChanges: number): void;
+
+  /**
+   * Saves scan settings to the Prefs service.
+   */
+  saveScanSettings(scanSettings: string): void;
+
+  /**
+   * Returns the saved scan settings from the Prefs service.
+   */
+  getScanSettings(): Promise<string>;
+
+  /**
+   * Validates that |filePath| exists on the local filesystem and returns its
+   * display name. If |filePath| doesn't exist, return an empty SelectedPath.
+   */
+  ensureValidFilePath(filePath: string): Promise<SelectedPath>;
+
+  /**
+   * Records the number of completed scans during a session of the Scan app
+   * being open.
+   */
+  recordNumCompletedScans(numCompletedScans: number): void;
+}
+
+export class ScanningBrowserProxyImpl implements ScanningBrowserProxy {
+  initialize(): void {
+    chrome.send('initialize');
+  }
+
+  requestScanToLocation(): Promise<SelectedPath> {
+    return sendWithPromise('requestScanToLocation');
+  }
+
+  showFileInLocation(pathToFile: string): Promise<boolean> {
+    return sendWithPromise('showFileInLocation', pathToFile);
+  }
+
+  getPluralString(name: string, count: number): Promise<string> {
+    return sendWithPromise('getPluralString', name, count);
+  }
+
+  recordScanJobSettings(scanJobSettings: ScanJobSettingsForMetrics): void {
+    chrome.send('recordScanJobSettings', [scanJobSettings]);
+  }
+
+  getMyFilesPath(): Promise<string> {
+    return sendWithPromise('getMyFilesPath');
+  }
+
+  openFilesInMediaApp(filePaths: string[]): void {
+    chrome.send('openFilesInMediaApp', [filePaths]);
+  }
+
+  recordScanCompleteAction(action: ScanCompleteAction): void {
+    chrome.send('recordScanCompleteAction', [action]);
+  }
+
+  recordNumScanSettingChanges(numChanges: number): void {
+    chrome.send('recordNumScanSettingChanges', [numChanges]);
+  }
+
+  saveScanSettings(scanSettings: string): void {
+    chrome.send('saveScanSettings', [scanSettings]);
+  }
+
+  getScanSettings(): Promise<string> {
+    return sendWithPromise('getScanSettings');
+  }
+
+  ensureValidFilePath(filePath: string): Promise<SelectedPath> {
+    return sendWithPromise('ensureValidFilePath', filePath);
+  }
+
+  recordNumCompletedScans(numCompletedScans: number): void {
+    chrome.send('recordNumCompletedScans', [numCompletedScans]);
+  }
+
+  static getInstance(): ScanningBrowserProxy {
+    return instance || (instance = new ScanningBrowserProxyImpl());
+  }
+
+  static setInstance(obj: ScanningBrowserProxy): void {
+    instance = obj;
+  }
+}
+
+let instance: ScanningBrowserProxy|null = null;
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index 67132b3f..60dc88c 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -28,6 +28,7 @@
 #include "ash/public/cpp/system/toast_data.h"
 #include "ash/public/cpp/test/test_shelf_item_delegate.h"
 #include "ash/public/cpp/window_finder.h"
+#include "ash/root_window_controller.h"
 #include "ash/screen_util.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shelf/hotseat_widget.h"
@@ -4059,6 +4060,8 @@
   auto* split_view_controller =
       SplitViewController::Get(Shell::GetPrimaryRootWindow());
   EXPECT_TRUE(split_view_controller->InSplitViewMode());
+  EXPECT_TRUE(RootWindowController::ForWindow(win0.get())
+                  ->split_view_overview_session());
 
   // Drag |win1| to the other desk.
   DragItemToPoint(overview_session->GetOverviewItemForWindow(win1.get()),
@@ -5408,6 +5411,12 @@
       ui::mojom::SixPackShortcutModifier active_modifier,
       int device_id) override {}
 
+  absl::optional<ui::mojom::ExtendedFkeysModifier> GetExtendedFkeySetting(
+      int device_id,
+      ui::KeyboardCode key_code) override {
+    return absl::nullopt;
+  }
+
   void SendAccelerator(ui::KeyboardCode key_code, int flags) {
     ui::test::EventGenerator* generator = GetEventGenerator();
     generator->PressKey(key_code, flags);
diff --git a/ash/wm/overview/overview_utils.cc b/ash/wm/overview/overview_utils.cc
index 44707b1..3628c37 100644
--- a/ash/wm/overview/overview_utils.cc
+++ b/ash/wm/overview/overview_utils.cc
@@ -9,6 +9,7 @@
 #include "ash/accessibility/accessibility_controller_impl.h"
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/public/cpp/window_properties.h"
+#include "ash/root_window_controller.h"
 #include "ash/scoped_animation_disabler.h"
 #include "ash/screen_util.h"
 #include "ash/shelf/shelf.h"
@@ -24,6 +25,7 @@
 #include "ash/wm/overview/overview_session.h"
 #include "ash/wm/overview/scoped_overview_animation_settings.h"
 #include "ash/wm/splitview/split_view_controller.h"
+#include "ash/wm/splitview/split_view_overview_session.h"
 #include "ash/wm/splitview/split_view_utils.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_state.h"
@@ -210,8 +212,25 @@
   auto* split_view_controller = SplitViewController::Get(target_root);
   SplitViewController::State state = split_view_controller->state();
 
+  // `split_view_overview_session` may have started without updating
+  // `split_view_controller->state()`, i.e. from SnapGroupController. Convert
+  // the split view overview session window to a split view state.
+  // TODO(sophiewen): See if we can remove `state` and just check this.
+  if (auto* split_view_overview_session =
+          RootWindowController::ForWindow(target_root)
+              ->split_view_overview_session()) {
+    auto* window_state =
+        WindowState::Get(split_view_overview_session->window());
+    CHECK(window_state->IsSnapped());
+    chromeos::WindowStateType window_state_type = window_state->GetStateType();
+    state = window_state_type == chromeos::WindowStateType::kPrimarySnapped
+                ? SplitViewController::State::kPrimarySnapped
+                : SplitViewController::State::kSecondarySnapped;
+  }
+
   // If we are in splitview mode already just use the given state, otherwise
-  // convert |window_dragging_state| to a split view state.
+  // convert `window_dragging_state` to a split view state. Note this will
+  // override `state` from `split_view_overview_session` if there is any.
   if (!split_view_controller->InSplitViewMode() && window_dragging_state) {
     switch (*window_dragging_state) {
       case SplitViewDragIndicators::WindowDraggingState::kToSnapPrimary:
@@ -287,8 +306,9 @@
     }
   }
 
-  if (!divider_changed)
+  if (!divider_changed) {
     return bounds;
+  }
 
   DCHECK(opposite_position);
   const bool horizontal = SplitViewController::IsLayoutHorizontal(target_root);
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 26b212fa..b031b0a 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -258,15 +258,15 @@
 void StartSplitViewOverviewSession(aura::Window* window,
                                    absl::optional<OverviewStartAction> action,
                                    absl::optional<OverviewEnterExitType> type) {
+  RootWindowController::ForWindow(window)->StartSplitViewOverviewSession(
+      window);
+
   if (!IsInOverviewSession()) {
     // Overview may already be in session, if a window was dragged to split view
     // from overview in clamshell mode.
     CHECK(action && type);
     Shell::Get()->overview_controller()->StartOverview(*action, *type);
   }
-
-  RootWindowController::ForWindow(window)->StartSplitViewOverviewSession(
-      window);
 }
 
 }  // namespace
@@ -1310,14 +1310,15 @@
     return;
   }
 
+  SnapWindow(target_window, SnapPosition::kPrimary,
+             WindowSnapActionSource::kLongPressOverviewButtonToSnap,
+             /*activate_window=*/true);
+
   // Start overview mode if we aren't already in it.
   StartSplitViewOverviewSession(target_window,
                                 OverviewStartAction::kOverviewButtonLongPress,
                                 OverviewEnterExitType::kImmediateEnter);
 
-  SnapWindow(target_window, SnapPosition::kPrimary,
-             WindowSnapActionSource::kLongPressOverviewButtonToSnap,
-             /*activate_window=*/true);
   base::RecordAction(
       base::UserMetricsAction("Tablet_LongPressOverviewButtonEnterSplitView"));
 }
@@ -1402,7 +1403,6 @@
     SnapGroupController::Get()->RemoveSnapGroupContainingWindow(
         primary_window_);
     split_view_divider_.reset();
-    in_snap_group_creation_session_ = true;
     StartSplitViewOverviewSession(
         snap_position == SnapPosition::kPrimary ? primary_window_
                                                 : secondary_window_,
@@ -1540,7 +1540,9 @@
   // While in clamshell split view mode without being in a snap group
   // creation session, a full overview session should be triggered. In this
   // case, split view should end.
-  if (InClamshellSplitViewMode() && !in_snap_group_creation_session_) {
+  if (InClamshellSplitViewMode() &&
+      !RootWindowController::ForWindow(root_window_)
+           ->split_view_overview_session()) {
     EndSplitView();
     return;
   }
@@ -1632,10 +1634,6 @@
       !IsSnapGroupEnabledInClamshellMode()) {
     EndSplitView();
   }
-
-  // Reset the value as we are guaranteed to be out of snap group creation
-  // session on overview ended.
-  in_snap_group_creation_session_ = false;
 }
 
 void SplitViewController::OnDisplayRemoved(
@@ -2379,7 +2377,6 @@
   // mode when `CanEnterOverview()` returns true, the check will happen in
   // `OverviewController`.
   if (WillStartOverview()) {
-    in_snap_group_creation_session_ = snap_group_enabled_in_clamshell;
     // TODO(b/294580642): Move this to SnapGroupController.
     StartSplitViewOverviewSession(window, OverviewStartAction::kSplitView,
                                   OverviewEnterExitType::kNormal);
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h
index 29baeff..d76430d0 100644
--- a/ash/wm/splitview/split_view_controller.h
+++ b/ash/wm/splitview/split_view_controller.h
@@ -203,9 +203,6 @@
   SnapPosition default_snap_position() const { return default_snap_position_; }
   SplitViewDivider* split_view_divider() { return split_view_divider_.get(); }
   EndReason end_reason() const { return end_reason_; }
-  bool in_snap_group_creation_session() const {
-    return in_snap_group_creation_session_;
-  }
   SplitViewMetricsController* split_view_metrics_controller() {
     return split_view_metrics_controller_.get();
   }
@@ -739,11 +736,6 @@
   // split view and clamshell split view.
   SplitViewType split_view_type_ = SplitViewType::kTabletType;
 
-  // True if we are currently in a snap group creation session which can either
-  // be active on one window snapped or when updating a window. Both use cases
-  // are behind the feature flag `kSnapGroup`.
-  bool in_snap_group_creation_session_ = false;
-
   // The time when splitview starts. Used for metric collection purpose.
   base::Time splitview_start_time_;
 
diff --git a/ash/wm/splitview/split_view_metrics_controller.cc b/ash/wm/splitview/split_view_metrics_controller.cc
index ecaf7fb..43e0b59 100644
--- a/ash/wm/splitview/split_view_metrics_controller.cc
+++ b/ash/wm/splitview/split_view_metrics_controller.cc
@@ -127,10 +127,11 @@
       continue;
     if (!window_state->IsSnapped())
       return false;
-    if (window_state->GetStateType() == top_snap_window_state->GetStateType())
+    if (window_state->GetStateType() == top_snap_window_state->GetStateType()) {
       continue;
-    else
+    } else {
       return true;
+    }
   }
   return false;
 }
@@ -148,6 +149,16 @@
              : SplitViewMetricsController::DeviceOrientation::kPortrait;
 }
 
+chromeos::WindowStateType GetOppositeSnapType(aura::Window* window) {
+  CHECK(window);
+  WindowState* window_state = WindowState::Get(window);
+  CHECK(window_state->IsSnapped());
+  return window_state->GetStateType() ==
+                 chromeos::WindowStateType::kPrimarySnapped
+             ? chromeos::WindowStateType::kSecondarySnapped
+             : chromeos::WindowStateType::kPrimarySnapped;
+}
+
 }  // namespace
 
 // static
@@ -359,6 +370,8 @@
 void SplitViewMetricsController::OnPostWindowStateTypeChange(
     WindowState* window_state,
     chromeos::WindowStateType old_type) {
+  MaybeStartOrEndRecordSnapTwoWindowsDuration(window_state);
+
   // We only care if a window is snapped or unsnapped.
   bool is_snapped = window_state->IsSnapped();
   bool was_snapped = chromeos::IsSnappedWindowStateType(old_type);
@@ -513,6 +526,14 @@
 }
 
 void SplitViewMetricsController::RemoveObservedWindow(aura::Window* window) {
+  if (window == first_snapped_window_) {
+    if (window->is_destroying()) {
+      // If `first_snapped_window_` was destroyed, record the max duration to
+      // indicate a second window was never snapped on the opposite side.
+      RecordSnapTwoWindowsDuration(kSnapTwoWindowsDurationHistogramMaxCount);
+    }
+    first_snapped_window_ = nullptr;
+  }
   if (base::Erase(observed_windows_, window)) {
     WindowState::Get(window)->RemoveObserver(this);
     window->RemoveObserver(this);
@@ -565,11 +586,9 @@
 }
 
 void SplitViewMetricsController::ClearObservedWindows() {
-  for (auto* window : observed_windows_) {
-    WindowState::Get(window)->RemoveObserver(this);
-    window->RemoveObserver(this);
+  while (!observed_windows_.empty()) {
+    RemoveObservedWindow(observed_windows_.back());
   }
-  observed_windows_.clear();
 }
 
 void SplitViewMetricsController::
@@ -579,10 +598,11 @@
   }
 
   bool both_snapped = TopTwoVisibleWindowsBothSnapped(observed_windows_);
-  if (!in_split_view_recording_ && both_snapped)
+  if (!in_split_view_recording_ && both_snapped) {
     StartRecordSplitViewMetrics();
-  else if (in_split_view_recording_ && !both_snapped)
+  } else if (in_split_view_recording_ && !both_snapped) {
     StopRecordSplitViewMetrics();
+  }
 }
 
 bool SplitViewMetricsController::
@@ -612,6 +632,42 @@
       std::vector<aura::Window*>(begin_iter, iter));
 }
 
+void SplitViewMetricsController::RecordSnapTwoWindowsDuration(
+    const base::TimeDelta& elapsed_time) {
+  base::UmaHistogramCustomTimes(
+      kSnapTwoWindowsDurationHistogramName,
+      /*sample=*/elapsed_time, kSnapTwoWindowsDurationHistogramMinCount,
+      kSnapTwoWindowsDurationHistogramMaxCount, /*buckets=*/100);
+  first_snapped_window_ = nullptr;
+  first_snapped_time_ = base::TimeTicks();
+}
+
+void SplitViewMetricsController::MaybeStartOrEndRecordSnapTwoWindowsDuration(
+    WindowState* window_state) {
+  if (window_state->IsSnapped()) {
+    if (first_snapped_window_ && !first_snapped_time_.is_null() &&
+        window_state->window() != first_snapped_window_ &&
+        window_state->GetStateType() ==
+            GetOppositeSnapType(first_snapped_window_)) {
+      // If this is a different window that got snapped on the opposite side,
+      // record the duration since `first_snapped_time_`.
+      RecordSnapTwoWindowsDuration(base::TimeTicks::Now() -
+                                   first_snapped_time_);
+      return;
+    }
+    // Else start recording. If the same window gets snapped again, this will
+    // restart recording.
+    first_snapped_window_ = window_state->window();
+    first_snapped_time_ = base::TimeTicks::Now();
+    return;
+  }
+  // If `first_snapped_window_` is no longer snapped, record the max duration to
+  // indicate a second window was never snapped on the opposite side.
+  if (window_state->window() == first_snapped_window_) {
+    RecordSnapTwoWindowsDuration(kSnapTwoWindowsDurationHistogramMaxCount);
+  }
+}
+
 void SplitViewMetricsController::ResetTimeAndCounter() {
   clamshell_split_view_start_time_ = kInvalidTime;
   tablet_split_view_start_time_ = kInvalidTime;
diff --git a/ash/wm/splitview/split_view_metrics_controller.h b/ash/wm/splitview/split_view_metrics_controller.h
index a8faab0..9a1fa29c 100644
--- a/ash/wm/splitview/split_view_metrics_controller.h
+++ b/ash/wm/splitview/split_view_metrics_controller.h
@@ -28,6 +28,14 @@
 namespace ash {
 class SplitViewController;
 
+// Public so it can be used by unit tests.
+constexpr char kSnapTwoWindowsDurationHistogramName[] =
+    "Ash.Window.SnapTwoWindowsDuration";
+constexpr base::TimeDelta kSnapTwoWindowsDurationHistogramMinCount =
+    base::Seconds(1);
+constexpr base::TimeDelta kSnapTwoWindowsDurationHistogramMaxCount =
+    base::Hours(50);
+
 // SplitViewMetricsController:
 // Manages split view related metrics. Tablet mode split view and clamshell
 // split view with overview next to a snapped window are managed by
@@ -163,6 +171,14 @@
   // return false.
   bool MaybePauseRecordBothSnappedClamshellSplitView();
 
+  // Records and resets the duration between two windows getting snapped.
+  void RecordSnapTwoWindowsDuration(const base::TimeDelta& elapsed_time);
+
+  // Starts recording the time if `window_state` was the first snapped window,
+  // otherwise ends recording if either: 1. the second snapped window is found,
+  // or 2. the first snapped window was unsnapped.
+  void MaybeStartOrEndRecordSnapTwoWindowsDuration(WindowState* window_state);
+
   // Resets the variables related to time and counter metrics.
   void ResetTimeAndCounter();
 
@@ -242,6 +258,12 @@
 
   // Counter of swapping windows in split view.
   int swap_count_ = 0;
+
+  // The first window that gets snapped and the time it's snapped at. Used by
+  // `Ash.Window.SnapTwoWindowsDuration` in
+  // tools/metrics/histograms/metadata/ash/histograms.xml.
+  raw_ptr<aura::Window> first_snapped_window_ = nullptr;
+  base::TimeTicks first_snapped_time_;
 };
 
 }  // namespace ash
diff --git a/ash/wm/splitview/split_view_metrics_controller_unittest.cc b/ash/wm/splitview/split_view_metrics_controller_unittest.cc
new file mode 100644
index 0000000..fa7234d7
--- /dev/null
+++ b/ash/wm/splitview/split_view_metrics_controller_unittest.cc
@@ -0,0 +1,108 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/wm/splitview/split_view_metrics_controller.h"
+
+#include "ash/test/ash_test_base.h"
+#include "ash/wm/desks/desk.h"
+#include "ash/wm/desks/desks_controller.h"
+#include "ash/wm/splitview/split_view_controller.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/time/time.h"
+
+namespace ash {
+
+class SplitViewMetricsControllerTest : public AshTestBase {
+ public:
+  SplitViewMetricsControllerTest()
+      : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+
+  void AdvanceClock(base::TimeDelta delta) {
+    task_environment()->AdvanceClock(delta);
+    task_environment()->RunUntilIdle();
+  }
+};
+
+// Tests that the metrics for recording the duration between one window getting
+// snapped and another window getting snapped on the other side work correctly.
+TEST_F(SplitViewMetricsControllerTest, RecordSnapTwoWindowsDuration) {
+  base::HistogramTester histogram_tester;
+  auto* desks_controller = DesksController::Get();
+  desks_controller->NewDesk(DesksCreationRemovalSource::kKeyboard);
+  std::unique_ptr<aura::Window> window1(CreateAppWindow());
+  std::unique_ptr<aura::Window> window2(CreateAppWindow());
+  WindowState* window_state1 = WindowState::Get(window1.get());
+  WindowState* window_state2 = WindowState::Get(window2.get());
+
+  // Snap `window1` to the left, wait 1 minute, then snap `window1` to the
+  // right. Test it doesn't record since it's the same window.
+  const WindowSnapWMEvent snap_left(WM_EVENT_SNAP_PRIMARY);
+  window_state1->OnWMEvent(&snap_left);
+  const WindowSnapWMEvent snap_right(WM_EVENT_SNAP_SECONDARY);
+  window_state1->OnWMEvent(&snap_right);
+  AdvanceClock(base::Minutes(1));
+  histogram_tester.ExpectTotalCount(kSnapTwoWindowsDurationHistogramName, 0);
+
+  // Snap `window1` to the left, wait 30 seconds, then snap `window2` to the
+  // right. Test that it records in the 0 minute bucket.
+  window_state1->OnWMEvent(&snap_left);
+  AdvanceClock(base::Seconds(30));
+  window_state2->OnWMEvent(&snap_right);
+  histogram_tester.ExpectTimeBucketCount(kSnapTwoWindowsDurationHistogramName,
+                                         base::Seconds(30), 1);
+
+  // Snap `window2` to the left, wait 3 minutes, then snap `window1` to the
+  // right. Test that it records in the 3 minute bucket.
+  window_state2->OnWMEvent(&snap_left);
+  AdvanceClock(base::Minutes(3));
+  window_state1->OnWMEvent(&snap_right);
+  histogram_tester.ExpectTimeBucketCount(kSnapTwoWindowsDurationHistogramName,
+                                         base::Minutes(3), 1);
+
+  // Snap `window1` to the left, wait 3 minutes, open a new `window3` and close
+  // it to simulate real user sessions with multiple windows, then snap
+  // `window2` to the right. Test that it increments the 3 minute bucket.
+  window_state1->OnWMEvent(&snap_left);
+  AdvanceClock(base::Minutes(3));
+  std::unique_ptr<aura::Window> window3(CreateAppWindow());
+  window3.reset();
+  window_state2->OnWMEvent(&snap_right);
+  histogram_tester.ExpectTimeBucketCount(kSnapTwoWindowsDurationHistogramName,
+                                         base::Minutes(3), 2);
+
+  // Snap `window1` to the right, wait 3 minutes, then minimize it. Test that it
+  // records in the max bucket, since no other window was snapped.
+  window_state1->OnWMEvent(&snap_right);
+  AdvanceClock(base::Minutes(3));
+  window_state1->Minimize();
+  histogram_tester.ExpectTimeBucketCount(
+      kSnapTwoWindowsDurationHistogramName,
+      kSnapTwoWindowsDurationHistogramMaxCount, 1);
+
+  // Snap a new `window4` to the left, wait 3 minutes, then close it. Test that
+  // it records in the max bucket, since no other window was snapped.
+  std::unique_ptr<aura::Window> window4(CreateAppWindow());
+  WindowState* window_state4 = WindowState::Get(window4.get());
+  window_state4->OnWMEvent(&snap_left);
+  AdvanceClock(base::Minutes(3));
+  window4.reset();
+  histogram_tester.ExpectTimeBucketCount(
+      kSnapTwoWindowsDurationHistogramName,
+      kSnapTwoWindowsDurationHistogramMaxCount, 2);
+
+  // Snap `window1` to the left, wait 3 minutes, move it to a new desk, move
+  // `window2` to the same desk. Test it doesn't record anything.
+  window_state1->OnWMEvent(&snap_left);
+  AdvanceClock(base::Minutes(3));
+  desks_controller->NewDesk(DesksCreationRemovalSource::kKeyboard);
+  desks_controller->desks()[0]->MoveWindowToDesk(
+      window1.get(), desks_controller->desks()[1].get(),
+      window1->GetRootWindow(), /*unminimize=*/true);
+  desks_controller->desks()[0]->MoveWindowToDesk(
+      window2.get(), desks_controller->desks()[1].get(),
+      window2->GetRootWindow(), /*unminimize=*/true);
+  histogram_tester.ExpectTotalCount(kSnapTwoWindowsDurationHistogramName, 5);
+}
+
+}  // namespace ash
diff --git a/ash/wm/splitview/split_view_overview_session.cc b/ash/wm/splitview/split_view_overview_session.cc
index a3bce8a..bff3616b 100644
--- a/ash/wm/splitview/split_view_overview_session.cc
+++ b/ash/wm/splitview/split_view_overview_session.cc
@@ -45,13 +45,18 @@
 
 }  // namespace
 
-SplitViewOverviewSession::SplitViewOverviewSession(aura::Window* window) {
-  CHECK(window && IsInOverviewSession());
+SplitViewOverviewSession::SplitViewOverviewSession(aura::Window* window)
+    : window_(window) {
+  CHECK(window);
   window_observation_.Observe(window);
-  // TODO(sophiewen): Update overview grid bounds.
+  auto* window_state = WindowState::Get(window);
+  CHECK(window_state && window_state->IsSnapped());
+  window_state->AddObserver(this);
 }
 
-SplitViewOverviewSession::~SplitViewOverviewSession() = default;
+SplitViewOverviewSession::~SplitViewOverviewSession() {
+  WindowState::Get(window_)->RemoveObserver(this);
+}
 
 void SplitViewOverviewSession::OnResizeLoopStarted(aura::Window* window) {
   auto* split_view_controller =
@@ -168,8 +173,20 @@
 
 void SplitViewOverviewSession::OnWindowDestroying(aura::Window* window) {
   CHECK(window_observation_.IsObservingSource(window));
+  CHECK_EQ(window_, window);
   // Destroys `this`.
-  RootWindowController::ForWindow(window)->EndSplitViewOverviewSession();
+  RootWindowController::ForWindow(window_)->EndSplitViewOverviewSession();
+}
+
+void SplitViewOverviewSession::OnPreWindowStateTypeChange(
+    WindowState* window_state,
+    chromeos::WindowStateType old_type) {
+  CHECK_EQ(window_, window_state->window());
+  // Normally split view would have ended and destroy this, but the window can
+  // get unsnapped, e.g. during mid-drag or mid-resize, so bail out here.
+  if (!window_state->IsSnapped()) {
+    RootWindowController::ForWindow(window_)->EndSplitViewOverviewSession();
+  }
 }
 
 }  // namespace ash
diff --git a/ash/wm/splitview/split_view_overview_session.h b/ash/wm/splitview/split_view_overview_session.h
index 4b1bfea..a244070 100644
--- a/ash/wm/splitview/split_view_overview_session.h
+++ b/ash/wm/splitview/split_view_overview_session.h
@@ -7,6 +7,7 @@
 
 #include "ash/wm/overview/overview_metrics.h"
 #include "ash/wm/overview/overview_types.h"
+#include "ash/wm/window_state_observer.h"
 #include "base/scoped_observation.h"
 #include "ui/aura/window_observer.h"
 #include "ui/compositor/presentation_time_recorder.h"
@@ -18,7 +19,7 @@
 // session.
 //
 // While `this` is alive, both split view and overview will be active;
-// however, the converse is not always true. `This` will automatically be
+// however, the converse is not always true. `this` will automatically be
 // destroyed upon split view or overview ending.
 //
 // There may be at most one SplitViewOverviewSession per root window. Consumers
@@ -27,13 +28,16 @@
 //
 // Note that clamshell split view does *not* have a divider, and resizing
 // overview is done via resizing the window directly.
-class SplitViewOverviewSession : public aura::WindowObserver {
+class SplitViewOverviewSession : public aura::WindowObserver,
+                                 public WindowStateObserver {
  public:
   SplitViewOverviewSession(aura::Window* window);
   SplitViewOverviewSession(const SplitViewOverviewSession&) = delete;
   SplitViewOverviewSession& operator=(const SplitViewOverviewSession&) = delete;
   ~SplitViewOverviewSession() override;
 
+  const aura::Window* window() const { return window_; }
+
   // aura::WindowObserver:
   void OnResizeLoopStarted(aura::Window* window) override;
   void OnResizeLoopEnded(aura::Window* window) override;
@@ -43,11 +47,19 @@
                              ui::PropertyChangeReason reason) override;
   void OnWindowDestroying(aura::Window* window) override;
 
+  // WindowStateObserver:
+  void OnPreWindowStateTypeChange(WindowState* window_state,
+                                  chromeos::WindowStateType old_type) override;
+
  private:
   // Records the presentation time of resize operation in clamshell split view
   // mode.
   std::unique_ptr<ui::PresentationTimeRecorder> presentation_time_recorder_;
 
+  // The single snapped window in intermediate split view, with overview on
+  // the opposite side.
+  const raw_ptr<aura::Window> window_;
+
   base::ScopedObservation<aura::Window, aura::WindowObserver>
       window_observation_{this};
 };
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc
index 485194b..8454f9b 100644
--- a/ash/wm/window_util.cc
+++ b/ash/wm/window_util.cc
@@ -12,6 +12,7 @@
 #include "ash/multi_user/multi_user_window_manager_impl.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/root_window_controller.h"
 #include "ash/scoped_animation_disabler.h"
@@ -27,6 +28,7 @@
 #include "ash/wm/snap_group/snap_group.h"
 #include "ash/wm/snap_group/snap_group_controller.h"
 #include "ash/wm/splitview/split_view_controller.h"
+#include "ash/wm/splitview/split_view_overview_session.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_state.h"
@@ -338,17 +340,18 @@
 
   // A window should be excluded from being shown in overview when:
   // 1. In tablet split view mode on one window snapped;
-  // 2. During snap group creation session in clamshell mode, the given `window`
-  // is snapped;
+  // 2. During split view overview session in clamshell mode,
   // 3. If the window is not the mru window in snap group i.e. the corresponding
   // overview item representation for the snap group has been created.
-
   auto should_exclude_in_clamshell = [&]() -> bool {
-    auto* snap_group_controller = SnapGroupController::Get();
-    if (snap_group_controller) {
-      if (snap_group_controller->IsArm1AutomaticallyLockEnabled() &&
-          split_view_controller->in_snap_group_creation_session()) {
-        return window == split_view_controller->GetDefaultSnappedWindow();
+    if (auto* snap_group_controller = SnapGroupController::Get()) {
+      if (auto* split_view_overview_session =
+              RootWindowController::ForWindow(window)
+                  ->split_view_overview_session();
+          snap_group_controller->IsArm1AutomaticallyLockEnabled() &&
+          split_view_overview_session &&
+          split_view_overview_session->window() == window) {
+        return true;
       }
 
       if (SnapGroup* snap_group =
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0f8acb33..e701eff7 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1964,8 +1964,8 @@
       "apple/scoped_mach_port.h",
       "apple/scoped_mach_vm.cc",
       "apple/scoped_mach_vm.h",
-      "apple/scoped_nsautorelease_pool.cc",
       "apple/scoped_nsautorelease_pool.h",
+      "apple/scoped_nsautorelease_pool.mm",
       "apple/scoped_nsobject.h",
       "apple/scoped_objc_class_swizzler.h",
       "apple/scoped_objc_class_swizzler.mm",
@@ -3737,6 +3737,7 @@
       "allocator/partition_allocator/shim/malloc_zone_functions_apple_unittest.cc",
       "apple/call_with_eh_frame_unittest.mm",
       "apple/scoped_mach_vm_unittest.cc",
+      "apple/scoped_nsautorelease_pool_unittest.mm",
       "apple/scoped_objc_class_swizzler_unittest.mm",
       "enterprise_util_mac_unittest.mm",
       "mac/launch_application_unittest.mm",
@@ -4386,8 +4387,17 @@
       "android/java/src/org/chromium/base/compat/ApiHelperForS.java",
       "android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
       "android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
+      "android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
+      "android/java/src/org/chromium/base/jank_tracker/JankEndScenarioTime.java",
       "android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
       "android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
+      "android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
+      "android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
+      "android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
+      "android/java/src/org/chromium/base/jank_tracker/JankTracker.java",
+      "android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java",
+      "android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java",
+      "android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java",
       "android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
       "android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java",
       "android/java/src/org/chromium/base/library_loader/Linker.java",
@@ -4749,7 +4759,10 @@
       "android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java",
       "android/junit/src/org/chromium/base/jank_tracker/FrameMetricsListenerTest.java",
       "android/junit/src/org/chromium/base/jank_tracker/FrameMetricsStoreTest.java",
+      "android/junit/src/org/chromium/base/jank_tracker/JankActivityTrackerTest.java",
       "android/junit/src/org/chromium/base/jank_tracker/JankMetricUMARecorderTest.java",
+      "android/junit/src/org/chromium/base/jank_tracker/JankReportingRunnableTest.java",
+      "android/junit/src/org/chromium/base/jank_tracker/JankReportingSchedulerTest.java",
       "android/junit/src/org/chromium/base/library_loader/LinkerTest.java",
       "android/junit/src/org/chromium/base/memory/MemoryPressureMonitorTest.java",
       "android/junit/src/org/chromium/base/memory/MemoryPurgeManagerTest.java",
diff --git a/base/android/jank_metric_uma_recorder.cc b/base/android/jank_metric_uma_recorder.cc
index a28fab9..2c9c1b5a9 100644
--- a/base/android/jank_metric_uma_recorder.cc
+++ b/base/android/jank_metric_uma_recorder.cc
@@ -21,27 +21,88 @@
     int64_t reporting_interval_start_time,
     int64_t reporting_interval_duration,
     uint64_t janky_frame_count,
-    uint64_t non_janky_frame_count) {
-  if (reporting_interval_start_time < 0) {
+    uint64_t non_janky_frame_count,
+    int scenario) {
+  if (reporting_interval_start_time <= 0) {
     return;
   }
 
   // The following code does nothing if base tracing is disabled.
-  [[maybe_unused]] auto t =
-      perfetto::Track(static_cast<uint64_t>(reporting_interval_start_time));
+  [[maybe_unused]] auto t = perfetto::Track(
+      static_cast<uint64_t>(reporting_interval_start_time + scenario));
   TRACE_EVENT_BEGIN(
-      "android_webview.timeline", "JankMetricsReportingInterval", t,
+      "android_webview.timeline,android.ui.jank",
+      "JankMetricsReportingInterval", t,
       base::TimeTicks::FromUptimeMillis(reporting_interval_start_time),
       "janky_frames", janky_frame_count, "non_janky_frames",
-      non_janky_frame_count);
+      non_janky_frame_count, "scenario", scenario);
   TRACE_EVENT_END(
-      "android_webview.timeline", t,
+      "android_webview.timeline,android.ui.jank", t,
       base::TimeTicks::FromUptimeMillis(
           (reporting_interval_start_time + reporting_interval_duration)));
 }
 
 }  // namespace
 
+const char* GetAndroidFrameTimelineJankHistogramName(JankScenario scenario) {
+#define HISTOGRAM_NAME(x) "Android.FrameTimelineJank.FrameJankStatus." #x
+  switch (scenario) {
+    case JankScenario::PERIODIC_REPORTING:
+      return HISTOGRAM_NAME(Total);
+    case JankScenario::OMNIBOX_FOCUS:
+      return HISTOGRAM_NAME(OmniboxFocus);
+    case JankScenario::NEW_TAB_PAGE:
+      return HISTOGRAM_NAME(NewTabPage);
+    case JankScenario::STARTUP:
+      return HISTOGRAM_NAME(Startup);
+    case JankScenario::TAB_SWITCHER:
+      return HISTOGRAM_NAME(TabSwitcher);
+    case JankScenario::OPEN_LINK_IN_NEW_TAB:
+      return HISTOGRAM_NAME(OpenLinkInNewTab);
+    case JankScenario::START_SURFACE_HOMEPAGE:
+      return HISTOGRAM_NAME(StartSurfaceHomepage);
+    case JankScenario::START_SURFACE_TAB_SWITCHER:
+      return HISTOGRAM_NAME(StartSurfaceTabSwitcher);
+    case JankScenario::FEED_SCROLLING:
+      return HISTOGRAM_NAME(FeedScrolling);
+    case JankScenario::WEBVIEW_SCROLLING:
+      return HISTOGRAM_NAME(WebviewScrolling);
+    default:
+      return HISTOGRAM_NAME(UNKNOWN);
+  }
+#undef HISTOGRAM_NAME
+}
+
+const char* GetAndroidFrameTimelineDurationHistogramName(
+    JankScenario scenario) {
+#define HISTOGRAM_NAME(x) "Android.FrameTimelineJank.Duration." #x
+  switch (scenario) {
+    case JankScenario::PERIODIC_REPORTING:
+      return HISTOGRAM_NAME(Total);
+    case JankScenario::OMNIBOX_FOCUS:
+      return HISTOGRAM_NAME(OmniboxFocus);
+    case JankScenario::NEW_TAB_PAGE:
+      return HISTOGRAM_NAME(NewTabPage);
+    case JankScenario::STARTUP:
+      return HISTOGRAM_NAME(Startup);
+    case JankScenario::TAB_SWITCHER:
+      return HISTOGRAM_NAME(TabSwitcher);
+    case JankScenario::OPEN_LINK_IN_NEW_TAB:
+      return HISTOGRAM_NAME(OpenLinkInNewTab);
+    case JankScenario::START_SURFACE_HOMEPAGE:
+      return HISTOGRAM_NAME(StartSurfaceHomepage);
+    case JankScenario::START_SURFACE_TAB_SWITCHER:
+      return HISTOGRAM_NAME(StartSurfaceTabSwitcher);
+    case JankScenario::FEED_SCROLLING:
+      return HISTOGRAM_NAME(FeedScrolling);
+    case JankScenario::WEBVIEW_SCROLLING:
+      return HISTOGRAM_NAME(WebviewScrolling);
+    default:
+      return HISTOGRAM_NAME(UNKNOWN);
+  }
+#undef HISTOGRAM_NAME
+}
+
 // This function is called from Java with JNI, it's declared in
 // base/base_jni/JankMetricUMARecorder_jni.h which is an autogenerated
 // header. The actual implementation is in RecordJankMetrics for simpler
@@ -50,34 +111,33 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jlongArray>& java_durations_ns,
     const base::android::JavaParamRef<jbooleanArray>& java_jank_status,
-    const base::android::JavaParamRef<jbooleanArray>& java_is_scrolling,
     jlong java_reporting_interval_start_time,
-    jlong java_reporting_interval_duration) {
-  RecordJankMetrics(env, java_durations_ns, java_jank_status, java_is_scrolling,
+    jlong java_reporting_interval_duration,
+    jint java_scenario_enum) {
+  RecordJankMetrics(env, java_durations_ns, java_jank_status,
                     java_reporting_interval_start_time,
-                    java_reporting_interval_duration);
+                    java_reporting_interval_duration, java_scenario_enum);
 }
 
 void RecordJankMetrics(
     JNIEnv* env,
     const base::android::JavaParamRef<jlongArray>& java_durations_ns,
     const base::android::JavaParamRef<jbooleanArray>& java_jank_status,
-    const base::android::JavaParamRef<jbooleanArray>& java_is_scrolling,
     jlong java_reporting_interval_start_time,
-    jlong java_reporting_interval_duration) {
+    jlong java_reporting_interval_duration,
+    jint java_scenario_enum) {
   std::vector<int64_t> durations_ns;
   JavaLongArrayToInt64Vector(env, java_durations_ns, &durations_ns);
 
   std::vector<bool> jank_status;
   JavaBooleanArrayToBoolVector(env, java_jank_status, &jank_status);
 
-  std::vector<bool> scrolling_status;
-  JavaBooleanArrayToBoolVector(env, java_is_scrolling, &scrolling_status);
+  JankScenario scenario = static_cast<JankScenario>(java_scenario_enum);
 
-  std::string frame_duration_histogram_name = "Android.Jank.FrameDuration";
-  std::string janky_frames_histogram_name = "Android.Jank.FrameJankStatus";
-  std::string janky_frames_in_scroll_histogram_name =
-      "Android.FrameTimelineJank.WebScroll.FrameJankStatus";
+  const char* frame_duration_histogram_name =
+      GetAndroidFrameTimelineDurationHistogramName(scenario);
+  const char* janky_frames_per_scenario_histogram_name =
+      GetAndroidFrameTimelineJankHistogramName(scenario);
 
   for (const int64_t frame_duration_ns : durations_ns) {
     base::UmaHistogramTimes(frame_duration_histogram_name,
@@ -86,18 +146,10 @@
 
   uint64_t janky_frame_count = 0;
 
-  DCHECK_EQ(jank_status.size(), scrolling_status.size());
-  for (size_t i = 0; i < jank_status.size(); ++i) {
-    bool is_janky = jank_status[i];
-    bool is_scrolling = scrolling_status[i];
+  for (bool is_janky : jank_status) {
     base::UmaHistogramEnumeration(
-        janky_frames_histogram_name,
+        janky_frames_per_scenario_histogram_name,
         is_janky ? FrameJankStatus::kJanky : FrameJankStatus::kNonJanky);
-    if (is_scrolling) {
-      base::UmaHistogramEnumeration(
-          janky_frames_in_scroll_histogram_name,
-          is_janky ? FrameJankStatus::kJanky : FrameJankStatus::kNonJanky);
-    }
     if (is_janky) {
       ++janky_frame_count;
     }
@@ -105,7 +157,8 @@
 
   RecordJankMetricReportingIntervalTraceEvent(
       java_reporting_interval_start_time, java_reporting_interval_duration,
-      janky_frame_count, jank_status.size() - janky_frame_count);
+      janky_frame_count, jank_status.size() - janky_frame_count,
+      java_scenario_enum);
 }
 
 }  // namespace base::android
diff --git a/base/android/jank_metric_uma_recorder.h b/base/android/jank_metric_uma_recorder.h
index 7dc4f21..18fb1d48 100644
--- a/base/android/jank_metric_uma_recorder.h
+++ b/base/android/jank_metric_uma_recorder.h
@@ -7,6 +7,7 @@
 
 #include "base/android/jni_android.h"
 #include "base/base_export.h"
+#include "base/feature_list.h"
 
 namespace base::android {
 
@@ -18,12 +19,37 @@
   kMaxValue = kNonJanky,
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class JankScenario {
+  PERIODIC_REPORTING = 1,
+  OMNIBOX_FOCUS = 2,
+  NEW_TAB_PAGE = 3,
+  STARTUP = 4,
+  TAB_SWITCHER = 5,
+  OPEN_LINK_IN_NEW_TAB = 6,
+  START_SURFACE_HOMEPAGE = 7,
+  START_SURFACE_TAB_SWITCHER = 8,
+  FEED_SCROLLING = 9,
+  WEBVIEW_SCROLLING = 10,
+  // This value should always be last and is not persisted to logs, exposed only
+  // for testing.
+  MAX_VALUE = WEBVIEW_SCROLLING + 1
+};
+
+// Resolves the above name to a histogram value.
+BASE_EXPORT const char* GetAndroidFrameTimelineJankHistogramName(
+    JankScenario scenario);
+// Resolves the above name to a histogram value.
+BASE_EXPORT const char* GetAndroidFrameTimelineDurationHistogramName(
+    JankScenario scenario);
+
 BASE_EXPORT void RecordJankMetrics(
     JNIEnv* env,
     const base::android::JavaParamRef<jlongArray>& java_durations_ns,
     const base::android::JavaParamRef<jbooleanArray>& java_jank_status,
-    const base::android::JavaParamRef<jbooleanArray>& java_is_scrolling,
     jlong java_reporting_interval_start_time,
-    jlong java_reporting_interval_duration);
+    jlong java_reporting_interval_duration,
+    jint java_scenario_enum);
 }  // namespace base::android
 #endif  // BASE_ANDROID_JANK_METRIC_UMA_RECORDER_H_
diff --git a/base/android/jank_metric_uma_recorder_unittest.cc b/base/android/jank_metric_uma_recorder_unittest.cc
index 2bd6608..38bb1b0e 100644
--- a/base/android/jank_metric_uma_recorder_unittest.cc
+++ b/base/android/jank_metric_uma_recorder_unittest.cc
@@ -18,6 +18,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::ElementsAre;
+using ::testing::IsEmpty;
 
 namespace base::android {
 namespace {
@@ -59,15 +60,9 @@
 };
 const size_t kJankStatusLen = kDurationsLen;
 
-const bool kIsScrolling[] = {
-    false, false, false, true, true, true, false, false,
-};
-const size_t kIsScrollingLen = kDurationsLen;
-
 }  // namespace
 
 TEST(JankMetricUMARecorder, TestUMARecording) {
-  HistogramTester histogram_tester;
 
   JNIEnv* env = AttachCurrentThread();
 
@@ -77,32 +72,55 @@
   jbooleanArray java_jank_status =
       GenerateJavaBooleanArray(env, kJankStatus, kJankStatusLen);
 
-  jbooleanArray java_is_scrolling =
-      GenerateJavaBooleanArray(env, kIsScrolling, kIsScrollingLen);
+  const int kMinScenario = static_cast<int>(JankScenario::PERIODIC_REPORTING);
+  const int kMaxScenario = static_cast<int>(JankScenario::MAX_VALUE);
+  // keep one histogram tester outside to ensure that each histogram is a
+  // different one rather than just the same string over and over.
+  HistogramTester complete_histogram_tester;
+  size_t total_histograms = 0;
+  for (int i = kMinScenario; i < kMaxScenario; ++i) {
+    // HistogramTester takes a snapshot of currently incremented counters so
+    // everything is scoped to just this iteration of the for loop.
+    HistogramTester histogram_tester;
 
-  RecordJankMetrics(
-      env,
-      /* java_durations_ns= */
-      base::android::JavaParamRef<jlongArray>(env, java_durations),
-      /* java_jank_status = */
-      base::android::JavaParamRef<jbooleanArray>(env, java_jank_status),
-      /* java_is_scrolling = */
-      base::android::JavaParamRef<jbooleanArray>(env, java_is_scrolling),
-      /* java_reporting_interval_start_time = */ 0,
-      /* java_reporting_interval_duration = */ 1000);
+    RecordJankMetrics(
+        env,
+        /* java_durations_ns= */
+        base::android::JavaParamRef<jlongArray>(env, java_durations),
+        /* java_jank_status = */
+        base::android::JavaParamRef<jbooleanArray>(env, java_jank_status),
+        /* java_reporting_interval_start_time = */ 0,
+        /* java_reporting_interval_duration = */ 1000,
+        /* java_scenario_enum = */ i);
 
-  EXPECT_THAT(histogram_tester.GetAllSamples("Android.Jank.FrameDuration"),
-              ElementsAre(Bucket(1, 3), Bucket(2, 1), Bucket(10, 1),
-                          Bucket(20, 1), Bucket(29, 1), Bucket(57, 1)));
+    const std::string kDurationName =
+        GetAndroidFrameTimelineDurationHistogramName(
+            static_cast<JankScenario>(i));
+    const std::string kJankyName =
+        GetAndroidFrameTimelineJankHistogramName(static_cast<JankScenario>(i));
 
-  EXPECT_THAT(histogram_tester.GetAllSamples("Android.Jank.FrameJankStatus"),
-              ElementsAre(Bucket(FrameJankStatus::kJanky, 2),
-                          Bucket(FrameJankStatus::kNonJanky, 6)));
+    // Only one Duration and one Jank scenario should be incremented.
+    base::HistogramTester::CountsMap count_map =
+        histogram_tester.GetTotalCountsForPrefix("Android.FrameTimelineJank.");
+    EXPECT_EQ(count_map.size(), 2ul);
+    EXPECT_EQ(count_map[kDurationName], 8) << kDurationName;
+    EXPECT_EQ(count_map[kJankyName], 8) << kJankyName;
+    // And we should be two more then last iteration, but don't do any other
+    // verification because each iteration will do their own.
+    base::HistogramTester::CountsMap total_count_map =
+        complete_histogram_tester.GetTotalCountsForPrefix(
+            "Android.FrameTimelineJank.");
+    EXPECT_EQ(total_count_map.size(), total_histograms + 2);
+    total_histograms += 2;
 
-  EXPECT_THAT(histogram_tester.GetAllSamples(
-                  "Android.FrameTimelineJank.WebScroll.FrameJankStatus"),
-              ElementsAre(Bucket(FrameJankStatus::kJanky, 1),
-                          Bucket(FrameJankStatus::kNonJanky, 2)));
+    EXPECT_THAT(histogram_tester.GetAllSamples(kDurationName),
+                ElementsAre(Bucket(1, 3), Bucket(2, 1), Bucket(10, 1),
+                            Bucket(20, 1), Bucket(29, 1), Bucket(57, 1)))
+        << kDurationName;
+    EXPECT_THAT(histogram_tester.GetAllSamples(kJankyName),
+                ElementsAre(Bucket(FrameJankStatus::kJanky, 2),
+                            Bucket(FrameJankStatus::kNonJanky, 6)))
+        << kJankyName;
+  }
 }
-
 }  // namespace base::android
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java
index 85b95be..51493ac 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java
@@ -5,16 +5,16 @@
 package org.chromium.base.jank_tracker;
 
 import android.os.Build.VERSION_CODES;
-import android.os.SystemClock;
 import android.view.FrameMetrics;
 import android.view.Window;
 import android.view.Window.OnFrameMetricsAvailableListener;
 
 import androidx.annotation.RequiresApi;
 
-import org.chromium.base.ThreadUtils;
 import org.chromium.base.TraceEvent;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * This class receives OnFrameMetricsAvailableListener.onFrameMetricsAvailable() callbacks and
  * records frame durations in a FrameMetricsStore instance.
@@ -22,14 +22,7 @@
 @RequiresApi(api = VERSION_CODES.N)
 public class FrameMetricsListener implements OnFrameMetricsAvailableListener {
     private final FrameMetricsStore mFrameMetricsStore;
-    private boolean mIsRecording;
-
-    // The reporting interval start and duration are passed to the reporting code and used in the
-    // 'JankMetricsReportingInterval' trace event.
-    private long mReportingIntervalStartTime;
-    private long mReportingIntervalDurationMillis;
-
-    private final ThreadUtils.ThreadChecker mThreadChecker = new ThreadUtils.ThreadChecker();
+    private AtomicBoolean mIsRecording = new AtomicBoolean(false);
 
     public FrameMetricsListener(FrameMetricsStore frameMetricsStore) {
         mFrameMetricsStore = frameMetricsStore;
@@ -41,25 +34,14 @@
      * @param isRecording
      */
     public void setIsListenerRecording(boolean isRecording) {
-        mThreadChecker.assertOnValidThread();
-        mIsRecording = isRecording;
-        if (isRecording && mReportingIntervalStartTime == 0) {
-            mReportingIntervalStartTime = SystemClock.uptimeMillis();
-        } else if (!isRecording) {
-            if (mReportingIntervalStartTime != 0) {
-                mReportingIntervalDurationMillis =
-                        SystemClock.uptimeMillis() - mReportingIntervalStartTime;
-            }
-            reportMetrics();
-        }
+        mIsRecording.set(isRecording);
     }
 
     @RequiresApi(api = VERSION_CODES.N)
     @Override
     public void onFrameMetricsAvailable(
             Window window, FrameMetrics frameMetrics, int dropCountSinceLastInvocation) {
-        mThreadChecker.assertOnValidThread();
-        if (!mIsRecording) {
+        if (!mIsRecording.get()) {
             return;
         }
 
@@ -74,15 +56,4 @@
                     frameTotalDurationNs, isJanky, frame_start_vsync_ts);
         }
     }
-
-    private void reportMetrics() {
-        JankMetricUMARecorder.recordJankMetricsToUMA(mFrameMetricsStore.takeMetrics(),
-                mReportingIntervalStartTime, mReportingIntervalDurationMillis);
-        mReportingIntervalStartTime = 0;
-        mReportingIntervalDurationMillis = 0;
-    }
-
-    public void onWebContentsScrollStateUpdate(boolean isScrolling) {
-        mFrameMetricsStore.onWebContentsScrollStateUpdate(isScrolling);
-    }
 }
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java
index 70b0268..45f3ea4d 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java
@@ -4,76 +4,255 @@
 
 package org.chromium.base.jank_tracker;
 
+import org.chromium.base.ThreadUtils.ThreadChecker;
+import org.chromium.base.TraceEvent;
+import org.chromium.build.BuildConfig;
+
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
 
 /**
  * This class stores relevant metrics from FrameMetrics between the calls to UMA reporting methods.
  */
 public class FrameMetricsStore {
+    // FrameMetricsStore can only be accessed on the handler thread (from the
+    // JankReportingScheduler.getOrCreateHandler() method). However construction occurs on a
+    // separate thread so the ThreadChecker is instead constructed later.
+    private ThreadChecker mThreadChecker;
+    // An arbitrary value from which to create a trace event async track. The only risk if this
+    // clashes with another track is trace events will show up on both potentially looking weird in
+    // the tracing UI. No other issue will occur.
+    private static final long TRACE_EVENT_TRACK_ID = 84186319646187624L;
+    // Android FrameMetrics promises in order frame metrics so this is just the latest timestamp.
+    private long mMaxTimestamp = -1;
+    // Array of timestamps stored in nanoseconds, they represent the moment when each frame
+    // began (VSYNC_TIMESTAMP), must always be the same size as mTotalDurationsNs.
+    private final ArrayList<Long> mTimestampsNs = new ArrayList<>();
     // Array of total durations stored in nanoseconds, they represent how long each frame took to
     // draw.
     private final ArrayList<Long> mTotalDurationsNs = new ArrayList<>();
-
     // Array of boolean values denoting whether a given frame is janky or not. Must always be the
     // same size as mTotalDurationsNs.
     private final ArrayList<Boolean> mIsJanky = new ArrayList<>();
-    private final ArrayList<Boolean> mIsScrolling = new ArrayList<>();
-    // Tracks whether we are in a web contents scroll or not.
-    private long mScrollStartTime = Long.MAX_VALUE;
-    private long mScrollEndTime;
+    // Stores the timestamp (nanoseconds) of the most recent frame metric as a scenario started.
+    // Zero if no FrameMetrics have been received.
+    private final HashMap<Integer, Long> mScenarioPreviousFrameTimestampNs = new HashMap<>();
+
+    // Convert an enum value to string to use as an UMA histogram name, changes to strings should be
+    // reflected in android/histograms.xml and base/android/jank_
+    public static String scenarioToString(@JankScenario int scenario) {
+        switch (scenario) {
+            case JankScenario.PERIODIC_REPORTING:
+                return "Total";
+            case JankScenario.OMNIBOX_FOCUS:
+                return "OmniboxFocus";
+            case JankScenario.NEW_TAB_PAGE:
+                return "NewTabPage";
+            case JankScenario.STARTUP:
+                return "Startup";
+            case JankScenario.TAB_SWITCHER:
+                return "TabSwitcher";
+            case JankScenario.OPEN_LINK_IN_NEW_TAB:
+                return "OpenLinkInNewTab";
+            case JankScenario.START_SURFACE_HOMEPAGE:
+                return "StartSurfaceHomepage";
+            case JankScenario.START_SURFACE_TAB_SWITCHER:
+                return "StartSurfaceTabSwitcher";
+            case JankScenario.FEED_SCROLLING:
+                return "FeedScrolling";
+            case JankScenario.WEBVIEW_SCROLLING:
+                return "WebviewScrolling";
+            default:
+                throw new IllegalArgumentException("Invalid scenario value");
+        }
+    }
+
+    /**
+     * initialize is the first entry point that is on the HandlerThread, so set up our thread
+     * checking.
+     */
+    void initialize() {
+        mThreadChecker = new ThreadChecker();
+    }
 
     /**
      * Records the total draw duration and jankiness for a single frame.
      */
     void addFrameMeasurement(long totalDurationNs, boolean isJanky, long frameStartVsyncTs) {
+        mThreadChecker.assertOnValidThread();
         mTotalDurationsNs.add(totalDurationNs);
         mIsJanky.add(isJanky);
-        boolean isScrollFrame =
-                mScrollStartTime < frameStartVsyncTs && frameStartVsyncTs < mScrollEndTime;
-        mIsScrolling.add(isScrollFrame);
+        mTimestampsNs.add(frameStartVsyncTs);
+        mMaxTimestamp = frameStartVsyncTs;
     }
 
-    /**
-     * Returns a copy of accumulated metrics and clears the internal storage.
-     */
-    JankMetrics takeMetrics() {
-        Long[] longDurations;
-        Boolean[] booleanIsJanky;
-        Boolean[] booleanIsScrolling;
+    @SuppressWarnings("NoDynamicStringsInTraceEventCheck")
+    void startTrackingScenario(@JankScenario int scenario) {
+        try (TraceEvent e =
+                        TraceEvent.scoped("startTrackingScenario: " + scenarioToString(scenario))) {
+            mThreadChecker.assertOnValidThread();
+            // Ignore multiple calls to startTrackingScenario without corresponding
+            // stopTrackingScenario calls.
+            if (mScenarioPreviousFrameTimestampNs.containsKey(scenario)) {
+                return;
+            }
+            // Make a unique ID for each scenario for tracing.
+            TraceEvent.startAsync(
+                    "JankCUJ:" + scenarioToString(scenario), TRACE_EVENT_TRACK_ID + scenario);
 
-        longDurations = mTotalDurationsNs.toArray(new Long[mTotalDurationsNs.size()]);
-        mTotalDurationsNs.clear();
+            // Scenarios are tracked based on the latest stored timestamp to allow fast lookups
+            // (find index of [timestamp] vs find first index that's >= [timestamp]). In case there
+            // are no stored timestamps then we hardcode the scenario's starting timestamp to 0L,
+            // this is handled as a special case in stopTrackingScenario by returning all stored
+            // frames.
+            Long startingTimestamp = 0L;
+            if (!mTimestampsNs.isEmpty()) {
+                startingTimestamp = mTimestampsNs.get(mTimestampsNs.size() - 1);
+            }
 
-        booleanIsJanky = mIsJanky.toArray(new Boolean[mIsJanky.size()]);
-        mIsJanky.clear();
-        booleanIsScrolling = mIsScrolling.toArray(new Boolean[mIsScrolling.size()]);
-        mIsScrolling.clear();
+            mScenarioPreviousFrameTimestampNs.put(scenario, startingTimestamp);
+        }
+    }
 
-        long[] durations = new long[longDurations.length];
-        for (int i = 0; i < longDurations.length; i++) {
-            durations[i] = longDurations[i].longValue();
+    boolean hasReceivedMetricsPast(long endScenarioTimeNs) {
+        mThreadChecker.assertOnValidThread();
+        return mMaxTimestamp > endScenarioTimeNs;
+    }
+
+    JankMetrics stopTrackingScenario(@JankScenario int scenario) {
+        return stopTrackingScenario(scenario, -1);
+    }
+
+    // The string added is a static string.
+    @SuppressWarnings("NoDynamicStringsInTraceEventCheck")
+    JankMetrics stopTrackingScenario(@JankScenario int scenario, long endScenarioTimeNs) {
+        try (TraceEvent e =
+                        TraceEvent.scoped("finishTrackingScenario: " + scenarioToString(scenario),
+                                Long.toString(endScenarioTimeNs))) {
+            mThreadChecker.assertOnValidThread();
+            TraceEvent.finishAsync(
+                    "JankCUJ:" + scenarioToString(scenario), TRACE_EVENT_TRACK_ID + scenario);
+            // Get the timestamp of the latest frame before startTrackingScenario was called. This
+            // can be null if tracking never started for scenario, or 0L if tracking started when no
+            // frames were stored.
+            Long previousFrameTimestamp = mScenarioPreviousFrameTimestampNs.remove(scenario);
+
+            // If stopTrackingScenario is called without a corresponding startTrackingScenario then
+            // return an empty FrameMetrics object.
+            if (previousFrameTimestamp == null) {
+                removeUnusedFrames();
+                return new JankMetrics();
+            }
+
+            int startingIndex;
+            // Starting timestamp may be 0 if a scenario starts without any frames stored, in this
+            // case return all frames.
+            if (previousFrameTimestamp == 0) {
+                startingIndex = 0;
+            } else {
+                startingIndex = mTimestampsNs.indexOf(previousFrameTimestamp);
+                // The scenario starts with the frame after the tracking timestamp.
+                startingIndex++;
+
+                // If startingIndex is out of bounds then we haven't recorded any frames since
+                // tracking started, return an empty FrameMetrics object.
+                if (startingIndex >= mTimestampsNs.size()) {
+                    return new JankMetrics();
+                }
+            }
+
+            // Ending index is exclusive, so this is not out of bounds.
+            int endingIndex = mTimestampsNs.size();
+            if (endScenarioTimeNs > 0) {
+                // binarySearch returns
+                // index of the search key (non-negative value) or (-(insertion point) - 1).
+                // The insertion point is defined as the index of the first element greater than the
+                // key, or a.length if all elements in the array are less than the specified key.
+                endingIndex = Collections.binarySearch(mTimestampsNs, endScenarioTimeNs);
+                if (endingIndex < 0) {
+                    endingIndex = -1 * (endingIndex + 1);
+                } else {
+                    endingIndex = Math.min(endingIndex + 1, mTimestampsNs.size());
+                }
+                if (endingIndex <= startingIndex) {
+                    // Something went wrong reset
+                    TraceEvent.instant("FrameMetricsStore invalid endScenarioTimeNs");
+                    endingIndex = mTimestampsNs.size();
+                }
+            }
+
+            JankMetrics jankMetrics =
+                    convertArraysToJankMetrics(mTimestampsNs.subList(startingIndex, endingIndex),
+                            mTotalDurationsNs.subList(startingIndex, endingIndex),
+                            mIsJanky.subList(startingIndex, endingIndex));
+            removeUnusedFrames();
+
+            return jankMetrics;
+        }
+    }
+
+    private void removeUnusedFrames() {
+        if (mScenarioPreviousFrameTimestampNs.isEmpty()) {
+            TraceEvent.instant("removeUnusedFrames", Long.toString(mTimestampsNs.size()));
+            mTimestampsNs.clear();
+            mTotalDurationsNs.clear();
+            mIsJanky.clear();
+            return;
         }
 
-        boolean[] isJanky = new boolean[booleanIsJanky.length];
-        for (int i = 0; i < booleanIsJanky.length; i++) {
-            isJanky[i] = booleanIsJanky[i].booleanValue();
+        long firstUsedTimestamp = findFirstUsedTimestamp();
+        // If the earliest timestamp tracked is 0 then that scenario contains every frame
+        // stored, so we shouldn't delete anything.
+        if (firstUsedTimestamp == 0L) {
+            return;
         }
 
-        boolean[] isScrolling = new boolean[booleanIsScrolling.length];
-        for (int i = 0; i < booleanIsScrolling.length; i++) {
-            isScrolling[i] = booleanIsScrolling[i].booleanValue();
+        int firstUsedIndex = mTimestampsNs.indexOf(firstUsedTimestamp);
+        if (firstUsedIndex == -1) {
+            if (BuildConfig.ENABLE_ASSERTS) {
+                throw new IllegalStateException("Timestamp for tracked scenario not found");
+            }
+            // This shouldn't happen.
+            return;
+        }
+        TraceEvent.instant("removeUnusedFrames", Long.toString(firstUsedIndex));
+
+        mTimestampsNs.subList(0, firstUsedIndex).clear();
+        mTotalDurationsNs.subList(0, firstUsedIndex).clear();
+        mIsJanky.subList(0, firstUsedIndex).clear();
+    }
+
+    private long findFirstUsedTimestamp() {
+        long firstTimestamp = Long.MAX_VALUE;
+        for (long timestamp : mScenarioPreviousFrameTimestampNs.values()) {
+            if (timestamp < firstTimestamp) {
+                firstTimestamp = timestamp;
+            }
         }
 
-        JankMetrics jankMetrics = new JankMetrics(durations, isJanky, isScrolling);
+        return firstTimestamp;
+    }
+
+    private JankMetrics convertArraysToJankMetrics(
+            List<Long> longTimestampsNs, List<Long> longDurations, List<Boolean> booleanIsJanky) {
+        long[] timestamps = new long[longTimestampsNs.size()];
+        for (int i = 0; i < longTimestampsNs.size(); i++) {
+            timestamps[i] = longTimestampsNs.get(i).longValue();
+        }
+
+        long[] durations = new long[longDurations.size()];
+        for (int i = 0; i < longDurations.size(); i++) {
+            durations[i] = longDurations.get(i).longValue();
+        }
+
+        boolean[] isJanky = new boolean[booleanIsJanky.size()];
+        for (int i = 0; i < booleanIsJanky.size(); i++) {
+            isJanky[i] = booleanIsJanky.get(i).booleanValue();
+        }
+
+        JankMetrics jankMetrics = new JankMetrics(timestamps, durations, isJanky);
         return jankMetrics;
     }
-
-    public void onWebContentsScrollStateUpdate(boolean isScrolling) {
-        if (isScrolling) {
-            mScrollStartTime = System.nanoTime();
-            mScrollEndTime = Long.MAX_VALUE;
-        } else {
-            mScrollEndTime = System.nanoTime();
-        }
-    }
 }
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
new file mode 100644
index 0000000..b664fc1
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
@@ -0,0 +1,89 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import android.app.Activity;
+import android.os.Build.VERSION_CODES;
+
+import androidx.annotation.RequiresApi;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.ApplicationStatus.ActivityStateListener;
+import org.chromium.base.ThreadUtils.ThreadChecker;
+import org.chromium.base.lifetime.DestroyChecker;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * This class takes an Activity and attaches a FrameMetricsListener to it, in addition it controls
+ * periodic jank metric reporting and frame metric recording based on the Activity's lifecycle
+ * events.
+ */
+@RequiresApi(api = VERSION_CODES.N)
+class JankActivityTracker extends JankTrackerStateController implements ActivityStateListener {
+    private final ThreadChecker mThreadChecker = new ThreadChecker();
+    private final DestroyChecker mDestroyChecker = new DestroyChecker();
+
+    private WeakReference<Activity> mActivityReference;
+
+    JankActivityTracker(Activity context, FrameMetricsListener listener,
+            JankReportingScheduler reportingScheduler) {
+        super(listener, reportingScheduler);
+        mActivityReference = new WeakReference<>(context);
+    }
+
+    @Override
+    public void initialize() {
+        assertValidState();
+        Activity activity = mActivityReference.get();
+        if (activity != null) {
+            ApplicationStatus.registerStateListenerForActivity(this, activity);
+            @ActivityState
+            int activityState = ApplicationStatus.getStateForActivity(activity);
+            onActivityStateChange(activity, activityState);
+            startMetricCollection(activity.getWindow());
+        }
+    }
+
+    @Override
+    public void destroy() {
+        mThreadChecker.assertOnValidThread();
+        ApplicationStatus.unregisterActivityStateListener(this);
+        stopPeriodicReporting();
+        Activity activity = mActivityReference.get();
+        if (activity != null) {
+            stopMetricCollection(activity.getWindow());
+        }
+        mDestroyChecker.destroy();
+    }
+
+    private void assertValidState() {
+        mThreadChecker.assertOnValidThread();
+        mDestroyChecker.checkNotDestroyed();
+    }
+
+    @Override
+    public void onActivityStateChange(Activity activity, @ActivityState int newState) {
+        assertValidState();
+        switch (newState) {
+            case ActivityState.STARTED: // Intentional fallthrough.
+            case ActivityState.RESUMED:
+                startPeriodicReporting();
+                startMetricCollection(null);
+                break;
+            case ActivityState.PAUSED:
+                // This method can be called at any moment safely, we want to report metrics even
+                // when the activity is paused.
+                startPeriodicReporting();
+                stopMetricCollection(null);
+                break;
+            case ActivityState.STOPPED:
+                stopPeriodicReporting();
+                stopMetricCollection(null);
+                break;
+        }
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankEndScenarioTime.java b/base/android/java/src/org/chromium/base/jank_tracker/JankEndScenarioTime.java
new file mode 100644
index 0000000..d2d1a9e
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankEndScenarioTime.java
@@ -0,0 +1,26 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+/**
+ * A simple Data structure that holds a uptimeNanos that we wish to have data up until, and a delay
+ * to wait for this data from the Android FrameMetrics API.
+ */
+public final class JankEndScenarioTime {
+    public final long endScenarioTimeNs;
+    // 100ms should be long enough to receive frame metric timeline if they haven't been dropped.
+    public final long timeoutDelayMs = 100;
+
+    public static JankEndScenarioTime endAt(long uptimeNanos) {
+        if (uptimeNanos <= 0) {
+            return null;
+        }
+        return new JankEndScenarioTime(uptimeNanos);
+    }
+
+    private JankEndScenarioTime(long uptimeNanos) {
+        endScenarioTimeNs = uptimeNanos;
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java b/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java
index 957ee33..0abb5a6 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java
@@ -12,19 +12,18 @@
  */
 @JNINamespace("base::android")
 public class JankMetricUMARecorder {
-    public static void recordJankMetricsToUMA(
-            JankMetrics metric, long reportingIntervalStartTime, long reportingIntervalDuration) {
+    public static void recordJankMetricsToUMA(JankMetrics metric, long reportingIntervalStartTime,
+            long reportingIntervalDuration, @JankScenario int scenario) {
         if (metric == null) {
             return;
         }
-
         JankMetricUMARecorderJni.get().recordJankMetrics(metric.durationsNs, metric.isJanky,
-                metric.isScrolling, reportingIntervalStartTime, reportingIntervalDuration);
+                reportingIntervalStartTime, reportingIntervalDuration, scenario);
     }
 
     @NativeMethods
     public interface Natives {
-        void recordJankMetrics(long[] durationsNs, boolean[] jankStatus, boolean[] scrollingStatus,
-                long reportingIntervalStartTime, long reportingIntervalDuration);
+        void recordJankMetrics(long[] durationsNs, boolean[] jankStatus,
+                long reportingIntervalStartTime, long reportingIntervalDuration, int scenario);
     }
 }
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java b/base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java
index 943ee5e..36b84e9 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java
@@ -9,13 +9,17 @@
  * to UMA.
  */
 class JankMetrics {
+    public final long[] timestampsNs;
     public final long[] durationsNs;
     public final boolean[] isJanky;
-    public final boolean[] isScrolling;
-
-    public JankMetrics(long[] durationsNs, boolean[] isJanky, boolean[] isScrolling) {
+    public JankMetrics() {
+        timestampsNs = new long[0];
+        durationsNs = new long[0];
+        isJanky = new boolean[0];
+    }
+    public JankMetrics(long[] timestampsNs, long[] durationsNs, boolean[] isJanky) {
+        this.timestampsNs = timestampsNs;
         this.durationsNs = durationsNs;
         this.isJanky = isJanky;
-        this.isScrolling = isScrolling;
     }
 }
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java
new file mode 100644
index 0000000..272b56d
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java
@@ -0,0 +1,98 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import android.os.Handler;
+
+import org.chromium.base.TraceEvent;
+/**
+ * This runnable receives a FrameMetricsStore instance and starts/stops tracking a given scenario.
+ * When a scenario stops it takes its metrics and sends them to native to be recorded in UMA.
+ * This is executed by JankReportingScheduler on its own thread.
+ */
+class JankReportingRunnable implements Runnable {
+    private final FrameMetricsStore mMetricsStore;
+    private final @JankScenario int mScenario;
+    private final boolean mIsStartingTracking;
+    // This must be the same handler that this is running on.
+    private final Handler mHandler;
+    // If metrics should be collected based on the state (scrolling) specify a
+    // JankEndScenarioTime.
+    private final JankEndScenarioTime mJankEndScenarioTime;
+
+    // When a JankEndScenarioTime is specified we don't immediately collect the metrics but instead
+    // post a task (this runnable). However to keep code reuse the same between delay/no-delay we
+    // use the same runnable but don't post it when there is no delay.
+    private class FinalReportingRunnable implements Runnable {
+        @Override
+        public void run() {
+            try (TraceEvent e = TraceEvent.scoped("ReportingCUJScenarioData", mScenario)) {
+                JankMetrics metrics;
+                if (mJankEndScenarioTime == null) {
+                    metrics = mMetricsStore.stopTrackingScenario(mScenario);
+                } else {
+                    // Since this is after the timeout we just unconditionally get the metrics.
+                    metrics = mMetricsStore.stopTrackingScenario(
+                            mScenario, mJankEndScenarioTime.endScenarioTimeNs);
+                }
+
+                if (metrics == null || metrics.timestampsNs.length == 0) {
+                    TraceEvent.instant("no metrics");
+                    return;
+                }
+
+                long startTime = metrics.timestampsNs[0] / 1000000;
+                long lastTime = metrics.timestampsNs[metrics.timestampsNs.length - 1] / 1000000;
+                long lastDuration = metrics.durationsNs[metrics.durationsNs.length - 1] / 1000000;
+                // The time that we have metrics covering is from the first VSYNC_TIMESTAMP
+                // (startTime) to the last frame has finished (lastTime + lastDuration).
+                long endTime = lastTime - startTime + lastDuration;
+
+                // Confirm that the current call context is valid.
+                // Debug builds will assert and fail; release builds will optimize this out.
+                JankMetricUMARecorderJni.get();
+                // TODO(salg@): Cache metrics in case native takes >30s to initialize.
+                JankMetricUMARecorder.recordJankMetricsToUMA(
+                        metrics, startTime, endTime, mScenario);
+            }
+        }
+    }
+
+    JankReportingRunnable(FrameMetricsStore metricsStore, @JankScenario int scenario,
+            boolean isStartingTracking, Handler handler, JankEndScenarioTime endScenarioTime) {
+        mMetricsStore = metricsStore;
+        mScenario = scenario;
+        mIsStartingTracking = isStartingTracking;
+        mHandler = handler;
+        mJankEndScenarioTime = endScenarioTime;
+    }
+
+    @Override
+    public void run() {
+        try (TraceEvent e = TraceEvent.scoped("StartingOrStoppingJankScenario",
+                     "StartingScenario:" + Boolean.toString(mIsStartingTracking)
+                             + ",Scenario:" + Integer.toString(mScenario))) {
+            if (mIsStartingTracking) {
+                if (mMetricsStore == null) {
+                    TraceEvent.instant("StartTrackingScenario metrics store null");
+                    return;
+                }
+                mMetricsStore.startTrackingScenario(mScenario);
+                return;
+            }
+            boolean dataIsReady = mJankEndScenarioTime == null
+                    || (mJankEndScenarioTime != null
+                            && mMetricsStore.hasReceivedMetricsPast(
+                                    mJankEndScenarioTime.endScenarioTimeNs));
+
+            if (dataIsReady) {
+                new FinalReportingRunnable().run();
+            } else {
+                mHandler.postDelayed(
+                        new FinalReportingRunnable(), mJankEndScenarioTime.timeoutDelayMs);
+            }
+        }
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java
new file mode 100644
index 0000000..a781677
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java
@@ -0,0 +1,116 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import androidx.annotation.Nullable;
+
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * This class receives requests to start and stop jank scenario tracking and runs them in a
+ * HandlerThread it creates. In addition it handles the recording of periodic jank metrics.
+ */
+public class JankReportingScheduler {
+    private static final long PERIODIC_METRIC_DELAY_MS = 5_000;
+    private final FrameMetricsStore mFrameMetricsStore;
+    private final HashMap<Integer, JankReportingRunnable> mRunnableStore;
+
+    public JankReportingScheduler(FrameMetricsStore frameMetricsStore) {
+        mFrameMetricsStore = frameMetricsStore;
+        mRunnableStore = new HashMap<Integer, JankReportingRunnable>();
+    }
+
+    private final Runnable mPeriodicMetricReporter = new Runnable() {
+        @Override
+        public void run() {
+            // delay should never be null.
+            finishTrackingScenario(JankScenario.PERIODIC_REPORTING);
+
+            if (mIsPeriodicReporterLooping.get()) {
+                // We delay starting the next periodic reporting until the timeout has finished by
+                // taking the delay and +1 so that it will run in order (it was posted above).
+                startTrackingScenario(JankScenario.PERIODIC_REPORTING);
+                getOrCreateHandler().postDelayed(mPeriodicMetricReporter, PERIODIC_METRIC_DELAY_MS);
+            }
+        }
+    };
+
+    @Nullable
+    protected HandlerThread mHandlerThread;
+    @Nullable
+    private Handler mHandler;
+    private final AtomicBoolean mIsPeriodicReporterLooping = new AtomicBoolean(false);
+
+    public void startTrackingScenario(@JankScenario int scenario) {
+        // We check to see if there was already a stop task queued at some point and attempt to
+        // cancel it. Regardless we send the startTracking runnable because we will ignore this
+        // start if the stop did get canceled and the stopTask already ran we'll start a new
+        // scenario.
+        JankReportingRunnable stopTask = mRunnableStore.get(scenario);
+        if (stopTask != null) {
+            getOrCreateHandler().removeCallbacks(stopTask);
+            mRunnableStore.remove(scenario);
+        }
+        getOrCreateHandler().post(new JankReportingRunnable(
+                mFrameMetricsStore, scenario, /* isStartingTracking= */ true, mHandler, null));
+    }
+
+    public void finishTrackingScenario(@JankScenario int scenario) {
+        finishTrackingScenario(scenario, -1);
+    }
+
+    public void finishTrackingScenario(@JankScenario int scenario, long endScenarioTimeNs) {
+        finishTrackingScenario(scenario, JankEndScenarioTime.endAt(endScenarioTimeNs));
+    }
+
+    public void finishTrackingScenario(
+            @JankScenario int scenario, JankEndScenarioTime endScenarioTime) {
+        // We store the stop task in case the delay is greater than zero and we start this scenario
+        // again.
+        JankReportingRunnable runnable = mRunnableStore.getOrDefault(scenario,
+                new JankReportingRunnable(mFrameMetricsStore, scenario,
+                        /* isStartingTracking= */ false, mHandler, endScenarioTime));
+        getOrCreateHandler().post(runnable);
+    }
+
+    public Handler getOrCreateHandler() {
+        if (mHandler == null) {
+            mHandlerThread = new HandlerThread("Jank-Tracker");
+            mHandlerThread.start();
+            mHandler = new Handler(mHandlerThread.getLooper());
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mFrameMetricsStore.initialize();
+                }
+            });
+        }
+        return mHandler;
+    }
+
+    public void startReportingPeriodicMetrics() {
+        // If mIsPeriodicReporterLooping was already true then there's no need to post another task.
+        if (mIsPeriodicReporterLooping.getAndSet(true)) {
+            return;
+        }
+        startTrackingScenario(JankScenario.PERIODIC_REPORTING);
+        getOrCreateHandler().postDelayed(mPeriodicMetricReporter, PERIODIC_METRIC_DELAY_MS);
+    }
+
+    public void stopReportingPeriodicMetrics() {
+        // Disable mPeriodicMetricReporter looping, and return early if it was already disabled.
+        if (!mIsPeriodicReporterLooping.getAndSet(false)) {
+            return;
+        }
+        // Remove any existing mPeriodicMetricReporter delayed tasks.
+        getOrCreateHandler().removeCallbacks(mPeriodicMetricReporter);
+        // Run mPeriodicMetricReporter one last time immediately.
+        getOrCreateHandler().post(mPeriodicMetricReporter);
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java b/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java
new file mode 100644
index 0000000..ef789ce
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A list of jank scenarios to be tracked, each scenario corresponds to a specific user journey
+ * except by PERIODIC_REPORTING, which runs constantly and is uploaded every 30s.
+ *
+ * IMPORTANT: This must be kept up to date with the histograms.xml histograms
+ * (Android.FrameTimelineJank..*) and the JankScenario C++ enum in
+ * //base/android/jank_metric_uma_recorder.cc.
+ */
+@IntDef({JankScenario.PERIODIC_REPORTING, JankScenario.OMNIBOX_FOCUS, JankScenario.NEW_TAB_PAGE,
+        JankScenario.STARTUP, JankScenario.TAB_SWITCHER, JankScenario.OPEN_LINK_IN_NEW_TAB,
+        JankScenario.START_SURFACE_HOMEPAGE, JankScenario.START_SURFACE_TAB_SWITCHER,
+        JankScenario.FEED_SCROLLING, JankScenario.WEBVIEW_SCROLLING})
+@Retention(RetentionPolicy.SOURCE)
+public @interface JankScenario {
+    int PERIODIC_REPORTING = 1;
+    int OMNIBOX_FOCUS = 2;
+    int NEW_TAB_PAGE = 3;
+    int STARTUP = 4;
+    int TAB_SWITCHER = 5;
+    int OPEN_LINK_IN_NEW_TAB = 6;
+    int START_SURFACE_HOMEPAGE = 7;
+    int START_SURFACE_TAB_SWITCHER = 8;
+    int FEED_SCROLLING = 9;
+    int WEBVIEW_SCROLLING = 10;
+}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java
new file mode 100644
index 0000000..80ea847
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java
@@ -0,0 +1,35 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+/**
+ * Interface for Android UI jank tracking.
+ */
+public interface JankTracker {
+    /**
+     * Starts tracking UI jank for a specific use scenario (e.g. Tab switcher, Omnibox, etc.),
+     * calling this method more than once without calling {@code finishTrackingScenario} won't do
+     * anything.
+     * @param scenario A value from {@link JankScenario} that specifies a use scenario.
+     */
+    void startTrackingScenario(@JankScenario int scenario);
+
+    /**
+     * Finishes tracking UI jank for a use scenario (e.g. Tab switcher, Omnibox, etc.). Histograms
+     * for that scenario (e.g. Android.Jank.FrameDuration.Omnibox) are recorded immediately after
+     * calling this method. Calling this method without calling {@code startTrackingScenario}
+     * beforehand won't do anything.
+     * @param scenario A value from {@link JankScenario} that specifies a use scenario.
+     * @param endScenarioTime A value that determines the maximum frame metric (based on vsync time)
+     *         that should be included.
+     */
+    void finishTrackingScenario(@JankScenario int scenario, long endScenarioTimeNs);
+    void finishTrackingScenario(@JankScenario int scenario);
+
+    /**
+     * To be called when the jank tracker should stop listening to changes.
+     */
+    void destroy();
+}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java
new file mode 100644
index 0000000..59f8518
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java
@@ -0,0 +1,89 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import android.app.Activity;
+import android.os.Build;
+
+/**
+ * Class for recording janky frame metrics for a specific Activity.
+ *
+ * It should be constructed when the activity is created, recording starts and stops automatically
+ * based on activity state. When the activity is being destroyed {@link #destroy()} should be called
+ * to clear the activity state observer. All methods should be called from the UI thread.
+ */
+public class JankTrackerImpl implements JankTracker {
+    // We use the DEADLINE field in the Android FrameMetrics which was added in S.
+    private static final boolean IS_TRACKING_ENABLED =
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
+
+    private JankTrackerStateController mController;
+    private JankReportingScheduler mReportingScheduler;
+
+    /**
+     * Creates a new JankTracker instance tracking UI rendering of an activity. Metric recording
+     * starts when the activity starts, and it's paused when the activity stops.
+     */
+    public JankTrackerImpl(Activity activity) {
+        FrameMetricsStore metricsStore = new FrameMetricsStore();
+        if (!constructInternalPreController(new JankReportingScheduler(metricsStore))) return;
+
+        constructInternalFinal(new JankActivityTracker(
+                activity, new FrameMetricsListener(metricsStore), mReportingScheduler));
+    }
+
+    /**
+     * Creates a new JankTracker which allows the controller to determine when it should start and
+     * stop metric scenarios/collection.
+     */
+    public JankTrackerImpl(JankTrackerStateController controller) {
+        if (!constructInternalPreController(controller.mReportingScheduler)) return;
+        constructInternalFinal(controller);
+    }
+
+    private boolean constructInternalPreController(JankReportingScheduler scheduler) {
+        if (!IS_TRACKING_ENABLED) {
+            mReportingScheduler = null;
+            mController = null;
+            return false;
+        }
+        mReportingScheduler = scheduler;
+        return true;
+    }
+
+    private void constructInternalFinal(JankTrackerStateController controller) {
+        mController = controller;
+        mController.initialize();
+    }
+
+    @Override
+    public void startTrackingScenario(@JankScenario int scenario) {
+        if (!IS_TRACKING_ENABLED) return;
+
+        mReportingScheduler.startTrackingScenario(scenario);
+    }
+
+    @Override
+    public void finishTrackingScenario(@JankScenario int scenario) {
+        finishTrackingScenario(scenario, -1);
+    }
+
+    @Override
+    public void finishTrackingScenario(@JankScenario int scenario, long endScenarioTimeNs) {
+        if (!IS_TRACKING_ENABLED) return;
+
+        mReportingScheduler.finishTrackingScenario(scenario, endScenarioTimeNs);
+    }
+
+    /**
+     * Stops listening for Activity state changes.
+     */
+    @Override
+    public void destroy() {
+        if (!IS_TRACKING_ENABLED) return;
+
+        mController.destroy();
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java
new file mode 100644
index 0000000..9a9ac492
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java
@@ -0,0 +1,51 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import android.view.Window;
+
+/**
+ * A simple holder class to enable easy starting and stopping of metric listening as well as
+ * periodic reporting. This is used by JankTrackerImpl to hold the listener reference and this class
+ * should be hooked up to some sort of listener to when to start/stop listening and periodic
+ * metrics.
+ */
+public class JankTrackerStateController {
+    protected final FrameMetricsListener mFrameMetricsListener;
+    protected final JankReportingScheduler mReportingScheduler;
+
+    public JankTrackerStateController(
+            FrameMetricsListener listener, JankReportingScheduler scheduler) {
+        mFrameMetricsListener = listener;
+        mReportingScheduler = scheduler;
+    }
+
+    public void startPeriodicReporting() {
+        mReportingScheduler.startReportingPeriodicMetrics();
+    }
+
+    public void stopPeriodicReporting() {
+        mReportingScheduler.stopReportingPeriodicMetrics();
+    }
+
+    public void startMetricCollection(Window window) {
+        mFrameMetricsListener.setIsListenerRecording(true);
+        if (window != null) {
+            window.addOnFrameMetricsAvailableListener(
+                    mFrameMetricsListener, mReportingScheduler.getOrCreateHandler());
+        }
+    }
+
+    public void stopMetricCollection(Window window) {
+        mFrameMetricsListener.setIsListenerRecording(false);
+        if (window != null) {
+            window.removeOnFrameMetricsAvailableListener(mFrameMetricsListener);
+        }
+    }
+
+    // Extra methods for subclasses that need to perform extra work on initialization/destruction.
+    public void initialize() {}
+    public void destroy() {}
+}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java
new file mode 100644
index 0000000..a6a2aba2
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java
@@ -0,0 +1,22 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+/**
+ * Placeholder implementation of JankTracker.
+ */
+public class PlaceholderJankTracker implements JankTracker {
+    @Override
+    public void startTrackingScenario(int scenario) {}
+
+    @Override
+    public void finishTrackingScenario(int scenario) {}
+
+    @Override
+    public void finishTrackingScenario(int scenario, long endScenarioTimeNs) {}
+
+    @Override
+    public void destroy() {}
+}
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc
index 2de7862b..6690bd8 100644
--- a/base/android/jni_array.cc
+++ b/base/android/jni_array.cc
@@ -174,7 +174,7 @@
 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects(
     JNIEnv* env,
     base::span<const ScopedJavaLocalRef<jobject>> v,
-    ScopedJavaLocalRef<jclass> type) {
+    const JavaRef<jclass>& type) {
   jobjectArray joa =
       env->NewObjectArray(checked_cast<jsize>(v.size()), type.obj(), nullptr);
   CheckException(env);
@@ -188,7 +188,7 @@
 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects(
     JNIEnv* env,
     base::span<const ScopedJavaGlobalRef<jobject>> v,
-    ScopedJavaLocalRef<jclass> type) {
+    const JavaRef<jclass>& type) {
   jobjectArray joa =
       env->NewObjectArray(checked_cast<jsize>(v.size()), type.obj(), nullptr);
   CheckException(env);
diff --git a/base/android/jni_array.h b/base/android/jni_array.h
index ee3bbb5..0b0f3187 100644
--- a/base/android/jni_array.h
+++ b/base/android/jni_array.h
@@ -101,11 +101,11 @@
 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects(
     JNIEnv* env,
     base::span<const ScopedJavaLocalRef<jobject>> v,
-    ScopedJavaLocalRef<jclass> type);
+    const JavaRef<jclass>& type);
 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects(
     JNIEnv* env,
     base::span<const ScopedJavaGlobalRef<jobject>> v,
-    ScopedJavaLocalRef<jclass> type);
+    const JavaRef<jclass>& type);
 
 // Returns a array of Java byte array converted from |v|.
 BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
diff --git a/base/android/junit/src/org/chromium/base/jank_tracker/FrameMetricsListenerTest.java b/base/android/junit/src/org/chromium/base/jank_tracker/FrameMetricsListenerTest.java
index 5bd24662..fdfcca6 100644
--- a/base/android/junit/src/org/chromium/base/jank_tracker/FrameMetricsListenerTest.java
+++ b/base/android/junit/src/org/chromium/base/jank_tracker/FrameMetricsListenerTest.java
@@ -26,30 +26,37 @@
     @Test
     public void testMetricRecording_OffByDefault() {
         FrameMetricsStore store = new FrameMetricsStore();
+        store.initialize();
+
         FrameMetricsListener metricsListener = new FrameMetricsListener(store);
         FrameMetrics frameMetrics = mock(FrameMetrics.class);
 
         when(frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION)).thenReturn(10_000_000L);
+        store.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
 
         metricsListener.onFrameMetricsAvailable(null, frameMetrics, 0);
 
         // By default metrics shouldn't be logged.
-        Assert.assertEquals(0, store.takeMetrics().durationsNs.length);
+        Assert.assertEquals(
+                0, store.stopTrackingScenario(JankScenario.NEW_TAB_PAGE).durationsNs.length);
         verifyNoMoreInteractions(frameMetrics);
     }
 
     @Test
     public void testMetricRecording_EnableRecording() {
         FrameMetricsStore store = new FrameMetricsStore();
+        store.initialize();
 
         FrameMetricsListener metricsListener = new FrameMetricsListener(store);
         FrameMetrics frameMetrics = mock(FrameMetrics.class);
 
         when(frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION)).thenReturn(10_000_000L);
 
+        store.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
         metricsListener.setIsListenerRecording(true);
         metricsListener.onFrameMetricsAvailable(null, frameMetrics, 0);
 
-        Assert.assertArrayEquals(new long[] {10_000_000L}, store.takeMetrics().durationsNs);
+        Assert.assertArrayEquals(new long[] {10_000_000L},
+                store.stopTrackingScenario(JankScenario.NEW_TAB_PAGE).durationsNs);
     }
 }
diff --git a/base/android/junit/src/org/chromium/base/jank_tracker/FrameMetricsStoreTest.java b/base/android/junit/src/org/chromium/base/jank_tracker/FrameMetricsStoreTest.java
index 770e270..e07ee17 100644
--- a/base/android/junit/src/org/chromium/base/jank_tracker/FrameMetricsStoreTest.java
+++ b/base/android/junit/src/org/chromium/base/jank_tracker/FrameMetricsStoreTest.java
@@ -22,6 +22,9 @@
     @Test
     public void addFrameMeasurementTest() {
         FrameMetricsStore store = new FrameMetricsStore();
+        store.initialize();
+
+        store.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
 
         long frame_start_vsync_ts = 0;
         store.addFrameMeasurement(10_000_000L, false, frame_start_vsync_ts);
@@ -29,21 +32,59 @@
         store.addFrameMeasurement(20_000_000L, true, frame_start_vsync_ts);
         store.addFrameMeasurement(8_000_000L, true, frame_start_vsync_ts);
 
-        JankMetrics metrics = store.takeMetrics();
+        JankMetrics metrics = store.stopTrackingScenario(JankScenario.NEW_TAB_PAGE);
 
         assertArrayEquals(new long[] {10_000_000L, 12_000_000L, 20_000_000L, 8_000_000L},
                 metrics.durationsNs);
         assertArrayEquals(new boolean[] {false, false, true, true}, metrics.isJanky);
 
-        metrics = store.takeMetrics();
+        metrics = store.stopTrackingScenario(JankScenario.NEW_TAB_PAGE);
         assertEquals(0, metrics.durationsNs.length);
     }
 
     @Test
     public void takeMetrics_getMetricsWithoutAnyFrames() {
         FrameMetricsStore store = new FrameMetricsStore();
-        JankMetrics metrics = store.takeMetrics();
+        store.initialize();
+        store.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
+        JankMetrics metrics = store.stopTrackingScenario(JankScenario.NEW_TAB_PAGE);
 
         assertEquals(0, metrics.durationsNs.length);
     }
+
+    @Test
+    public void concurrentScenarios() {
+        // We want to test 2 things.
+        // 1) that concurrent scenarios get the correct frames
+        // 2) that the deletion logic runs correctly. Note however that deletion logic is not
+        // actually public behaviour but we just want this test to explicitly exercise it to
+        // uncover potential bugs.
+        FrameMetricsStore store = new FrameMetricsStore();
+        store.initialize();
+
+        store.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
+
+        long frame_start_vsync_ts = 1_000_000L;
+        store.addFrameMeasurement(10_000_000L, false, frame_start_vsync_ts);
+        store.addFrameMeasurement(12_000_000L, false, frame_start_vsync_ts + 1);
+        store.startTrackingScenario(JankScenario.FEED_SCROLLING);
+        store.addFrameMeasurement(20_000_000L, true, frame_start_vsync_ts + 2);
+        store.addFrameMeasurement(8_000_000L, true, frame_start_vsync_ts + 3);
+
+        // Stop NEW_TAB_PAGE and now the first two frames will be deleted from the
+        // FrameMetricsStore().
+        JankMetrics metrics = store.stopTrackingScenario(JankScenario.NEW_TAB_PAGE);
+
+        assertArrayEquals(new long[] {10_000_000L, 12_000_000L, 20_000_000L, 8_000_000L},
+                metrics.durationsNs);
+        assertArrayEquals(new boolean[] {false, false, true, true}, metrics.isJanky);
+
+        metrics = store.stopTrackingScenario(JankScenario.NEW_TAB_PAGE);
+        assertEquals(0, metrics.durationsNs.length);
+
+        // Only after that will we stop FEED_SCROLLING and we should only see the last two frames.
+        metrics = store.stopTrackingScenario(JankScenario.FEED_SCROLLING);
+        assertArrayEquals(new long[] {20_000_000L, 8_000_000L}, metrics.durationsNs);
+        assertArrayEquals(new boolean[] {true, true}, metrics.isJanky);
+    }
 }
diff --git a/base/android/junit/src/org/chromium/base/jank_tracker/JankActivityTrackerTest.java b/base/android/junit/src/org/chromium/base/jank_tracker/JankActivityTrackerTest.java
new file mode 100644
index 0000000..f6261a5
--- /dev/null
+++ b/base/android/junit/src/org/chromium/base/jank_tracker/JankActivityTrackerTest.java
@@ -0,0 +1,157 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.view.Window;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/**
+ *  Tests for JankActivityTracker.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+public class JankActivityTrackerTest {
+    @Mock
+    private Activity mActivity;
+
+    @Mock
+    private Window mWindow;
+
+    @Mock
+    private FrameMetricsListener mFrameMetricsListener;
+
+    @Mock
+    private JankReportingScheduler mJankReportingScheduler;
+
+    JankActivityTracker createJankActivityTracker(Activity activity) {
+        JankActivityTracker tracker =
+                new JankActivityTracker(activity, mFrameMetricsListener, mJankReportingScheduler);
+
+        return tracker;
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mActivity.getWindow()).thenReturn(mWindow);
+
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.CREATED);
+    }
+
+    @Test
+    public void jankTrackerTest_TestInitialize() {
+        JankActivityTracker jankActivityTracker = createJankActivityTracker(mActivity);
+        jankActivityTracker.initialize();
+
+        // Verify that we are listening to frame metrics.
+        // Initialize also starts listening to activity lifecycle events, but that's harder to
+        // verify.
+        verify(mWindow).addOnFrameMetricsAvailableListener(any(), any());
+    }
+
+    @Test
+    public void jankTrackerTest_TestActivityResume() {
+        JankActivityTracker jankActivityTracker = createJankActivityTracker(mActivity);
+        jankActivityTracker.initialize();
+
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED);
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED);
+
+        // When an activity resumes we start reporting periodic metrics.
+        verify(mJankReportingScheduler, atLeastOnce()).startReportingPeriodicMetrics();
+        verify(mJankReportingScheduler, never()).stopReportingPeriodicMetrics();
+
+        // When an activity resumes we start recording metrics.
+        verify(mFrameMetricsListener, atLeastOnce()).setIsListenerRecording(true);
+    }
+
+    @Test
+    public void jankTrackerTest_TestActivityPause() {
+        JankActivityTracker jankActivityTracker = createJankActivityTracker(mActivity);
+        jankActivityTracker.initialize();
+
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED);
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED);
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED);
+
+        // When an activity pauses the reporting task should still be looping.
+        verify(mJankReportingScheduler, atLeastOnce()).startReportingPeriodicMetrics();
+        verify(mJankReportingScheduler, never()).stopReportingPeriodicMetrics();
+
+        InOrder orderVerifier = Mockito.inOrder(mFrameMetricsListener);
+
+        orderVerifier.verify(mFrameMetricsListener, atLeastOnce()).setIsListenerRecording(true);
+        // When an activity pauses we stop recording metrics.
+        orderVerifier.verify(mFrameMetricsListener).setIsListenerRecording(false);
+    }
+
+    @Test
+    public void jankTrackerTest_TestActivityStop() {
+        JankActivityTracker jankActivityTracker = createJankActivityTracker(mActivity);
+        jankActivityTracker.initialize();
+
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED);
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED);
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED);
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STOPPED);
+
+        // When an activity stops we stop reporting periodic metrics.
+        InOrder schedulerOrderVerifier = Mockito.inOrder(mJankReportingScheduler);
+        schedulerOrderVerifier.verify(mJankReportingScheduler, atLeastOnce())
+                .startReportingPeriodicMetrics();
+        schedulerOrderVerifier.verify(mJankReportingScheduler).stopReportingPeriodicMetrics();
+    }
+
+    @Test
+    public void jankTrackerTest_TestAttachTrackerOnResumedActivity() {
+        // Modify the activity's state before attaching JankActivityTracker.
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STARTED);
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED);
+
+        JankActivityTracker jankActivityTracker = createJankActivityTracker(mActivity);
+        jankActivityTracker.initialize();
+
+        // Verify that JankActivityTracker is running as expected for the Resumed state.
+        // Periodic metric reporting should be enabled.
+        verify(mJankReportingScheduler).startReportingPeriodicMetrics();
+        // Metric recording should be enabled.
+        verify(mFrameMetricsListener, atLeastOnce()).setIsListenerRecording(true);
+    }
+
+    @Test
+    public void jankTrackerTest_TestOutOfOrderStateChange() {
+        JankActivityTracker jankActivityTracker = createJankActivityTracker(mActivity);
+        jankActivityTracker.initialize();
+
+        // Move the activity from STOPPED to RESUMED without calling STARTED.
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.STOPPED);
+        ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.RESUMED);
+
+        // Verify that JankActivityTracker is running as expected for the Resumed state.
+        // Reporting task should be running and looping.
+        verify(mJankReportingScheduler).startReportingPeriodicMetrics();
+        // Metric recording should be enabled.
+        verify(mFrameMetricsListener, atLeastOnce()).setIsListenerRecording(true);
+        verify(mFrameMetricsListener, atLeastOnce()).setIsListenerRecording(false);
+    }
+}
diff --git a/base/android/junit/src/org/chromium/base/jank_tracker/JankMetricUMARecorderTest.java b/base/android/junit/src/org/chromium/base/jank_tracker/JankMetricUMARecorderTest.java
index 6fe3433..b932994 100644
--- a/base/android/junit/src/org/chromium/base/jank_tracker/JankMetricUMARecorderTest.java
+++ b/base/android/junit/src/org/chromium/base/jank_tracker/JankMetricUMARecorderTest.java
@@ -39,24 +39,24 @@
 
     @Test
     public void testRecordMetricsToNative() {
+        long[] timestampsNs = new long[] {5L, 8L, 3L};
         long[] durationsNs = new long[] {5_000_000L, 8_000_000L, 30_000_000L};
         boolean[] jankyFrames = new boolean[] {false, false, true};
-        boolean[] scrollingFrames = new boolean[] {false, false, false};
 
-        JankMetrics metric = new JankMetrics(durationsNs, jankyFrames, scrollingFrames);
+        JankMetrics metric = new JankMetrics(timestampsNs, durationsNs, jankyFrames);
 
-        JankMetricUMARecorder.recordJankMetricsToUMA(metric, 0, 1000);
+        JankMetricUMARecorder.recordJankMetricsToUMA(metric, 0, 1000, 1);
 
         // Ensure that the relevant fields are sent down to native.
-        verify(mNativeMock).recordJankMetrics(durationsNs, jankyFrames, scrollingFrames, 0, 1000);
+        verify(mNativeMock).recordJankMetrics(durationsNs, jankyFrames, 0, 1000, 1);
     }
 
     @Test
     public void testRecordNullMetrics() {
-        JankMetricUMARecorder.recordJankMetricsToUMA(null, 0, 0);
+        JankMetricUMARecorder.recordJankMetricsToUMA(null, 0, 0, 1);
         verify(mNativeMock, never())
                 .recordJankMetrics(ArgumentMatchers.any(), ArgumentMatchers.any(),
-                        ArgumentMatchers.any(), ArgumentMatchers.anyLong(),
-                        ArgumentMatchers.anyLong());
+                        ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong(),
+                        ArgumentMatchers.anyInt());
     }
 }
diff --git a/base/android/junit/src/org/chromium/base/jank_tracker/JankReportingRunnableTest.java b/base/android/junit/src/org/chromium/base/jank_tracker/JankReportingRunnableTest.java
new file mode 100644
index 0000000..468d08b
--- /dev/null
+++ b/base/android/junit/src/org/chromium/base/jank_tracker/JankReportingRunnableTest.java
@@ -0,0 +1,148 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.shadows.ShadowLooper;
+
+import org.chromium.base.TimeUtils;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.JniMocker;
+
+/**
+ *  Tests for JankReportingRunnable.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+public class JankReportingRunnableTest {
+    ShadowLooper mShadowLooper;
+    Handler mHandler;
+    @Rule
+    public JniMocker mocker = new JniMocker();
+
+    @Mock
+    JankMetricUMARecorder.Natives mNativeMock;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mocker.mock(JankMetricUMARecorderJni.TEST_HOOKS, mNativeMock);
+        mShadowLooper = ShadowLooper.shadowMainLooper();
+        mHandler = new Handler(Looper.getMainLooper());
+    }
+
+    @Test
+    public void testStartTracking() {
+        FrameMetricsStore metricsStore = Mockito.spy(new FrameMetricsStore());
+        metricsStore.initialize();
+
+        JankReportingRunnable reportingRunnable = new JankReportingRunnable(metricsStore,
+                JankScenario.TAB_SWITCHER, /* isStartingTracking= */ true, mHandler, null);
+        reportingRunnable.run();
+
+        verify(metricsStore).initialize();
+        verify(metricsStore).startTrackingScenario(JankScenario.TAB_SWITCHER);
+        verifyNoMoreInteractions(metricsStore);
+    }
+
+    @Test
+    public void testStopTracking_withoutDelay() {
+        FrameMetricsStore metricsStore = Mockito.spy(new FrameMetricsStore());
+        metricsStore.initialize();
+
+        JankReportingRunnable startReportingRunnable = new JankReportingRunnable(metricsStore,
+                JankScenario.TAB_SWITCHER, /* isStartingTracking= */ true, mHandler, null);
+        startReportingRunnable.run();
+
+        metricsStore.addFrameMeasurement(1_000_000L, true, 1);
+
+        JankReportingRunnable stopReportingRunnable = new JankReportingRunnable(metricsStore,
+                JankScenario.TAB_SWITCHER, /* isStartingTracking= */ false, mHandler, null);
+        stopReportingRunnable.run();
+
+        verify(metricsStore).initialize();
+        verify(metricsStore).startTrackingScenario(JankScenario.TAB_SWITCHER);
+        verify(metricsStore).stopTrackingScenario(JankScenario.TAB_SWITCHER);
+
+        verify(mNativeMock)
+                .recordJankMetrics(new long[] {1_000_000L}, new boolean[] {true}, 0L, 1L,
+                        JankScenario.TAB_SWITCHER);
+    }
+
+    @Test
+    public void testStopTracking_withDelay() {
+        final long frameTime = 50L * TimeUtils.NANOSECONDS_PER_MILLISECOND;
+        FrameMetricsStore metricsStore = Mockito.spy(new FrameMetricsStore());
+        metricsStore.initialize();
+
+        JankEndScenarioTime endScenarioTime = JankEndScenarioTime.endAt(frameTime);
+        Assert.assertTrue(endScenarioTime != null);
+        Assert.assertEquals(endScenarioTime.endScenarioTimeNs, frameTime);
+
+        JankReportingRunnable startReportingRunnable =
+                new JankReportingRunnable(metricsStore, JankScenario.TAB_SWITCHER,
+                        /* isStartingTracking= */ true, mHandler, endScenarioTime);
+        startReportingRunnable.run();
+
+        metricsStore.addFrameMeasurement(
+                1_000_000L, true, 1 * TimeUtils.NANOSECONDS_PER_MILLISECOND);
+
+        JankReportingRunnable stopReportingRunnable =
+                new JankReportingRunnable(metricsStore, JankScenario.TAB_SWITCHER,
+                        /* isStartingTracking= */ false, mHandler, endScenarioTime);
+        stopReportingRunnable.run();
+
+        // Add two frames, one added before the frame time of 50ms above and one after. The first
+        // should be included and the second ignored.
+        metricsStore.addFrameMeasurement(
+                1_000_001L, false, 5 * TimeUtils.NANOSECONDS_PER_MILLISECOND);
+        metricsStore.addFrameMeasurement(
+                1_000_002L, true, (frameTime + 5) * TimeUtils.NANOSECONDS_PER_MILLISECOND);
+
+        mShadowLooper.runOneTask();
+
+        verify(metricsStore).initialize();
+        verify(metricsStore).startTrackingScenario(JankScenario.TAB_SWITCHER);
+        verify(metricsStore).stopTrackingScenario(JankScenario.TAB_SWITCHER, frameTime);
+
+        verify(mNativeMock)
+                .recordJankMetrics(new long[] {1_000_000L, 1_000_001L}, new boolean[] {true, false},
+                        1L, 5L, JankScenario.TAB_SWITCHER);
+    }
+
+    @Test
+    public void testStopTracking_emptyStoreShouldntRecordAnything() {
+        // Create a store but don't add any measurements.
+        FrameMetricsStore metricsStore = Mockito.spy(new FrameMetricsStore());
+        metricsStore.initialize();
+
+        JankReportingRunnable startReportingRunnable = new JankReportingRunnable(metricsStore,
+                JankScenario.TAB_SWITCHER, /* isStartingTracking= */ true, mHandler, null);
+        startReportingRunnable.run();
+
+        JankReportingRunnable stopReportingRunnable = new JankReportingRunnable(metricsStore,
+                JankScenario.TAB_SWITCHER, /* isStartingTracking= */ false, mHandler, null);
+        stopReportingRunnable.run();
+
+        verify(metricsStore).initialize();
+        verify(metricsStore).startTrackingScenario(JankScenario.TAB_SWITCHER);
+        verify(metricsStore).stopTrackingScenario(JankScenario.TAB_SWITCHER);
+
+        // Native shouldn't be called when there are no measurements.
+        verifyNoMoreInteractions(mNativeMock);
+    }
+}
diff --git a/base/android/junit/src/org/chromium/base/jank_tracker/JankReportingSchedulerTest.java b/base/android/junit/src/org/chromium/base/jank_tracker/JankReportingSchedulerTest.java
new file mode 100644
index 0000000..27a9b9f
--- /dev/null
+++ b/base/android/junit/src/org/chromium/base/jank_tracker/JankReportingSchedulerTest.java
@@ -0,0 +1,158 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.jank_tracker;
+
+import static org.mockito.Mockito.verify;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.LooperMode;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowLooper;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/**
+ *  Tests for JankReportingScheduler.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@LooperMode(LooperMode.Mode.LEGACY)
+public class JankReportingSchedulerTest {
+    ShadowLooper mShadowLooper;
+
+    @Mock
+    private FrameMetricsStore mFrameMetricsStore;
+
+    JankReportingScheduler createJankReportingScheduler() {
+        JankReportingScheduler scheduler = new JankReportingScheduler(mFrameMetricsStore);
+        mShadowLooper = Shadow.extract(scheduler.getOrCreateHandler().getLooper());
+
+        return scheduler;
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void jankScenarioTracking_startTracking() {
+        JankReportingScheduler jankReportingScheduler = createJankReportingScheduler();
+
+        jankReportingScheduler.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
+
+        // When first getting the handler we need to run the initialize on the handler.
+        mShadowLooper.runOneTask();
+        // Starting tracking posts a task to begin recording metrics in FrameMetricsStore.
+        mShadowLooper.runOneTask();
+
+        verify(mFrameMetricsStore).initialize();
+        verify(mFrameMetricsStore).startTrackingScenario(JankScenario.NEW_TAB_PAGE);
+    }
+
+    @Test
+    public void jankScenarioTracking_startAndStopTracking() {
+        JankReportingScheduler jankReportingScheduler = createJankReportingScheduler();
+
+        jankReportingScheduler.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
+        jankReportingScheduler.finishTrackingScenario(JankScenario.NEW_TAB_PAGE);
+
+        // When first getting the handler we need to run the initialize on the handler.
+        mShadowLooper.runOneTask();
+        // Starting tracking posts a task to begin recording metrics in FrameMetricsStore.
+        mShadowLooper.runOneTask();
+        // Stopping tracking posts a task to finish tracking and upload the calculated metrics.
+        mShadowLooper.runOneTask();
+
+        InOrder orderVerifier = Mockito.inOrder(mFrameMetricsStore);
+
+        // After both tasks we should have started and stopped tracking the periodic reporting
+        // scenario.
+        orderVerifier.verify(mFrameMetricsStore).initialize();
+        orderVerifier.verify(mFrameMetricsStore).startTrackingScenario(JankScenario.NEW_TAB_PAGE);
+        orderVerifier.verify(mFrameMetricsStore).stopTrackingScenario(JankScenario.NEW_TAB_PAGE);
+
+        Assert.assertFalse(mShadowLooper.getScheduler().areAnyRunnable());
+    }
+
+    @Test
+    public void jankReportingSchedulerTest_StartPeriodicReporting() {
+        JankReportingScheduler jankReportingScheduler = createJankReportingScheduler();
+
+        jankReportingScheduler.startReportingPeriodicMetrics();
+
+        // When first getting the handler we need to run the initialize on the handler.
+        mShadowLooper.runOneTask();
+        // When periodic reporting is enabled a task is immediately posted to begin tracking.
+        mShadowLooper.runOneTask();
+        // Then a delayed task is posted for the reporting loop.
+        mShadowLooper.runOneTask();
+        // The reporting loop task posts an immediate task to stop tracking and record the data.
+        mShadowLooper.runOneTask();
+
+        InOrder orderVerifier = Mockito.inOrder(mFrameMetricsStore);
+
+        // After both tasks we should have started and stopped tracking the periodic reporting
+        // scenario.
+        orderVerifier.verify(mFrameMetricsStore).initialize();
+        orderVerifier.verify(mFrameMetricsStore)
+                .startTrackingScenario(JankScenario.PERIODIC_REPORTING);
+        orderVerifier.verify(mFrameMetricsStore)
+                .stopTrackingScenario(JankScenario.PERIODIC_REPORTING);
+
+        // There should be another task posted to continue the loop.
+        Assert.assertTrue(mShadowLooper.getScheduler().areAnyRunnable());
+    }
+
+    @Test
+    public void jankReportingSchedulerTest_StopPeriodicReporting() {
+        JankReportingScheduler jankReportingScheduler = createJankReportingScheduler();
+
+        jankReportingScheduler.startReportingPeriodicMetrics();
+
+        // When first getting the handler we need to run the initialize on the handler.
+        mShadowLooper.runOneTask();
+        // Run tracking initialization task.
+        mShadowLooper.runOneTask();
+        // Run the first reporting loop (delayed 30s).
+        mShadowLooper.runOneTask();
+        // Run task to stop tracking 1st loop and record data.
+        mShadowLooper.runOneTask();
+        // Run task to start tracking the 2nd reporting loop.
+        mShadowLooper.runOneTask();
+
+        jankReportingScheduler.stopReportingPeriodicMetrics();
+
+        // Stopping periodic metric recording posts a reporting loop task immediately to stop
+        // tracking and record results.
+        mShadowLooper.runOneTask();
+        // The reporting loop task posts another immediate task to stop tracking and report data.
+        mShadowLooper.runOneTask();
+
+        InOrder orderVerifier = Mockito.inOrder(mFrameMetricsStore);
+
+        // This start/stop pair corresponds to the first reporting period.
+        orderVerifier.verify(mFrameMetricsStore).initialize();
+        orderVerifier.verify(mFrameMetricsStore)
+                .startTrackingScenario(JankScenario.PERIODIC_REPORTING);
+        orderVerifier.verify(mFrameMetricsStore)
+                .stopTrackingScenario(JankScenario.PERIODIC_REPORTING);
+
+        // Stopping reporting forces an immediate report of recorded frames, if any.
+        orderVerifier.verify(mFrameMetricsStore)
+                .startTrackingScenario(JankScenario.PERIODIC_REPORTING);
+        orderVerifier.verify(mFrameMetricsStore)
+                .stopTrackingScenario(JankScenario.PERIODIC_REPORTING);
+
+        // There should not be another task posted to continue the loop.
+        Assert.assertFalse(mShadowLooper.getScheduler().areAnyRunnable());
+    }
+}
diff --git a/base/apple/scoped_nsautorelease_pool.cc b/base/apple/scoped_nsautorelease_pool.cc
deleted file mode 100644
index 5793482..0000000
--- a/base/apple/scoped_nsautorelease_pool.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2010 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/apple/scoped_nsautorelease_pool.h"
-
-// Note that this uses the direct runtime interface to the autorelease pool.
-// https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support
-// This is so this can work when compiled for ARC.
-
-extern "C" {
-void* objc_autoreleasePoolPush(void);
-void objc_autoreleasePoolPop(void* pool);
-}
-
-namespace base::apple {
-
-ScopedNSAutoreleasePool::ScopedNSAutoreleasePool()
-    : autorelease_pool_(objc_autoreleasePoolPush()) {}
-
-ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  objc_autoreleasePoolPop(autorelease_pool_);
-}
-
-// Cycle the internal pool, allowing everything there to get cleaned up and
-// start anew.
-void ScopedNSAutoreleasePool::Recycle() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  objc_autoreleasePoolPop(autorelease_pool_);
-  autorelease_pool_ = objc_autoreleasePoolPush();
-}
-
-}  // namespace base::apple
diff --git a/base/apple/scoped_nsautorelease_pool.h b/base/apple/scoped_nsautorelease_pool.h
index 3d6b0d17..056668b 100644
--- a/base/apple/scoped_nsautorelease_pool.h
+++ b/base/apple/scoped_nsautorelease_pool.h
@@ -6,8 +6,10 @@
 #define BASE_APPLE_SCOPED_NSAUTORELEASE_POOL_H_
 
 #include "base/base_export.h"
+#include "base/dcheck_is_on.h"
 #include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/stack_allocated.h"
+#include "base/thread_annotations.h"
 #include "base/threading/thread_checker.h"
 
 namespace base::apple {
@@ -43,11 +45,21 @@
   void Recycle();
 
  private:
+  // Pushes the autorelease pool and does all required verification.
+  void PushImpl() VALID_CONTEXT_REQUIRED(thread_checker_);
+
+  // Pops the autorelease pool and does all required verification.
+  void PopImpl() VALID_CONTEXT_REQUIRED(thread_checker_);
+
   // This field is not a raw_ptr<> because it is a pointer to an Objective-C
   // object.
   RAW_PTR_EXCLUSION void* autorelease_pool_ GUARDED_BY_CONTEXT(thread_checker_);
 
   THREAD_CHECKER(thread_checker_);
+
+#if DCHECK_IS_ON()
+  unsigned long level_ = 0;
+#endif
 };
 
 }  // namespace base::apple
diff --git a/base/apple/scoped_nsautorelease_pool.mm b/base/apple/scoped_nsautorelease_pool.mm
new file mode 100644
index 0000000..76ed461
--- /dev/null
+++ b/base/apple/scoped_nsautorelease_pool.mm
@@ -0,0 +1,122 @@
+// Copyright 2010 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/apple/scoped_nsautorelease_pool.h"
+
+#include "base/dcheck_is_on.h"
+#include "base/strings/sys_string_conversions.h"
+
+#if DCHECK_IS_ON()
+#import <Foundation/Foundation.h>
+
+#include "base/debug/crash_logging.h"
+#include "base/immediate_crash.h"
+#endif
+
+// Note that this uses the direct runtime interface to the autorelease pool.
+// https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support
+// This is so this can work when compiled for ARC.
+extern "C" {
+void* objc_autoreleasePoolPush(void);
+void objc_autoreleasePoolPop(void* pool);
+}
+
+#if DCHECK_IS_ON()
+namespace {
+// For each NSThread, maintain an array of stack traces (NSArray<NSString>), one
+// for the state of the stack for each invocation of an autorelease pool push.
+// Even though one is allowed to clear out an entire stack of autorelease pools
+// by releasing one near the bottom, because the stack abstraction is mapped to
+// C++ classes, this cannot be allowed.
+NSMutableArray<NSArray<NSString*>*>* GetLevelStackTraces() {
+  NSMutableArray* traces =
+      NSThread.currentThread
+          .threadDictionary[@"CrScopedNSAutoreleasePoolTraces"];
+  if (traces) {
+    return traces;
+  }
+
+  traces = [NSMutableArray array];
+  NSThread.currentThread.threadDictionary[@"CrScopedNSAutoreleasePoolTraces"] =
+      traces;
+  return traces;
+}
+}  // namespace
+#endif
+
+namespace base::apple {
+
+ScopedNSAutoreleasePool::ScopedNSAutoreleasePool() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  PushImpl();
+}
+
+ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  PopImpl();
+}
+
+void ScopedNSAutoreleasePool::Recycle() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  // Cycle the internal pool, allowing everything there to get cleaned up and
+  // start anew.
+  PopImpl();
+  PushImpl();
+}
+
+void ScopedNSAutoreleasePool::PushImpl() {
+#if DCHECK_IS_ON()
+  [GetLevelStackTraces() addObject:NSThread.callStackSymbols];
+  level_ = GetLevelStackTraces().count;
+#endif
+  autorelease_pool_ = objc_autoreleasePoolPush();
+}
+
+void ScopedNSAutoreleasePool::PopImpl() {
+#if DCHECK_IS_ON()
+  auto level_count = GetLevelStackTraces().count;
+  if (level_ != level_count) {
+    NSLog(@"Popping autorelease pool at level %lu while pools exist through "
+          @"level %lu",
+          level_, level_count);
+    if (level_ < level_count) {
+      NSLog(@"WARNING: This abandons ScopedNSAutoreleasePool objects which now "
+            @"have no corresponding implementation.");
+    } else {
+      NSLog(@"ERROR: This is an abandoned ScopedNSAutoreleasePool that cannot "
+            @"release; expect the autorelease machinery to crash.");
+    }
+    NSLog(@"====================");
+    NSString* current_stack =
+        [NSThread.callStackSymbols componentsJoinedByString:@"\n"];
+    NSLog(@"Pop:\n%@", current_stack);
+    [GetLevelStackTraces()
+        enumerateObjectsWithOptions:NSEnumerationReverse
+                         usingBlock:^(NSArray<NSString*>* obj, NSUInteger idx,
+                                      BOOL* stop) {
+                           NSLog(@"====================");
+                           NSLog(@"Autorelease pool level %lu was pushed:\n%@",
+                                 idx + 1, [obj componentsJoinedByString:@"\n"]);
+                         }];
+    // Assume an interactive use of Chromium where crashing immediately is
+    // desirable, and die. When investigating a failing automated test that dies
+    // here, remove this call to ImmediateCrash(), to reveal where the abandoned
+    // ScopedNSAutoreleasePool was expected to be released.
+    SCOPED_CRASH_KEY_NUMBER("ScopedNSAutoreleasePool", "currentlevel", level_);
+    SCOPED_CRASH_KEY_NUMBER("ScopedNSAutoreleasePool", "levelcount",
+                            level_count);
+    SCOPED_CRASH_KEY_STRING1024("ScopedNSAutoreleasePool", "currentstack",
+                                SysNSStringToUTF8(current_stack));
+    SCOPED_CRASH_KEY_STRING1024(
+        "ScopedNSAutoreleasePool", "recentstack",
+        SysNSStringToUTF8(
+            [GetLevelStackTraces().lastObject componentsJoinedByString:@"\n"]));
+    base::ImmediateCrash();
+  }
+  [GetLevelStackTraces() removeLastObject];
+#endif
+  objc_autoreleasePoolPop(autorelease_pool_);
+}
+
+}  // namespace base::apple
diff --git a/base/apple/scoped_nsautorelease_pool_unittest.mm b/base/apple/scoped_nsautorelease_pool_unittest.mm
new file mode 100644
index 0000000..8bd1120
--- /dev/null
+++ b/base/apple/scoped_nsautorelease_pool_unittest.mm
@@ -0,0 +1,26 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "base/apple/scoped_nsautorelease_pool.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace base::apple {
+
+#if DCHECK_IS_ON()
+TEST(ScopedNSAutoreleasePoolTest, DieOutOfOrder) {
+  absl::optional<ScopedNSAutoreleasePool> pool1;
+  absl::optional<ScopedNSAutoreleasePool> pool2;
+
+  // Instantiate the pools in the order 1, then 2.
+  pool1.emplace();
+  pool2.emplace();
+
+  // Destroy in the wrong order; ensure death.
+  ASSERT_DEATH(pool1.reset(), "autorelease");
+}
+#endif
+
+}  // namespace base::apple
diff --git a/base/features.cc b/base/features.cc
index f5c021a8..b7dc8ce0 100644
--- a/base/features.cc
+++ b/base/features.cc
@@ -52,6 +52,10 @@
              "PartialLowEndModeOnMidRangeDevices",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+// Whether to report frame metrics to the Android.FrameTimeline.* histograms.
+BASE_FEATURE(kCollectAndroidFrameTimelineMetrics,
+             "CollectAndroidFrameTimelineMetrics",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 #endif  // BUILDFLAG(IS_ANDROID)
 
 }  // namespace base::features
diff --git a/base/features.h b/base/features.h
index 63037e0..756445ec 100644
--- a/base/features.h
+++ b/base/features.h
@@ -31,6 +31,8 @@
 BASE_EXPORT BASE_DECLARE_FEATURE(kPartialLowEndModeOnMidRangeDevices);
 extern const BASE_EXPORT FeatureParam<bool>
     kPartialLowEndModeExcludeLowEndBackgroundCleanup;
+
+BASE_EXPORT BASE_DECLARE_FEATURE(kCollectAndroidFrameTimelineMetrics);
 #endif
 
 }  // namespace base::features
diff --git a/base/observer_list.h b/base/observer_list.h
index 450ec23..e2f4cd8 100644
--- a/base/observer_list.h
+++ b/base/observer_list.h
@@ -17,6 +17,7 @@
 
 #include "base/check.h"
 #include "base/check_op.h"
+#include "base/containers/cxx20_erase.h"
 #include "base/dcheck_is_on.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/notreached.h"
@@ -342,10 +343,8 @@
     // Compact() is only ever called when the last iterator is destroyed.
     DETACH_FROM_SEQUENCE(iteration_sequence_checker_);
 
-    observers_.erase(
-        std::remove_if(observers_.begin(), observers_.end(),
-                       [](const auto& o) { return o.IsMarkedForRemoval(); }),
-        observers_.end());
+    base::EraseIf(observers_,
+                  [](const auto& o) { return o.IsMarkedForRemoval(); });
   }
 
   std::string GetObserversCreationStackString() const {
diff --git a/base/task/sequenced_task_runner.h b/base/task/sequenced_task_runner.h
index 03529c3..c19f24a 100644
--- a/base/task/sequenced_task_runner.h
+++ b/base/task/sequenced_task_runner.h
@@ -276,7 +276,7 @@
   //   the current thread.
   virtual bool RunsTasksInCurrentSequence() const = 0;
 
-  // Returns the default SequencedThreadTaskRunner for the current task. It
+  // Returns the default SequencedTaskRunner for the current task. It
   // should only be called if HasCurrentDefault() returns true (see the comment
   // there for the requirements).
   //
diff --git a/base/task/single_thread_task_runner.h b/base/task/single_thread_task_runner.h
index e89ca0d..6db207f 100644
--- a/base/task/single_thread_task_runner.h
+++ b/base/task/single_thread_task_runner.h
@@ -115,8 +115,8 @@
     // We expect SingleThreadTaskRunner::CurrentHandleOverride to be only needed
     // under special circumstances. Require them to be enumerated as friends to
     // require //base/OWNERS review. Use
-    // SingleTaskRunner::CurrentHandleOverrideForTesting in unit tests to avoid
-    // the friend requirement.
+    // SingleThreadTaskRunner::CurrentHandleOverrideForTesting in unit tests to
+    // avoid the friend requirement.
 
     friend class blink::scheduler::MainThreadSchedulerImpl;
 
diff --git a/base/task/thread_pool/task.cc b/base/task/thread_pool/task.cc
index 59fa754c..8fe92d47 100644
--- a/base/task/thread_pool/task.cc
+++ b/base/task/thread_pool/task.cc
@@ -6,17 +6,9 @@
 
 #include <utility>
 
-#include "base/atomic_sequence_num.h"
-
 namespace base {
 namespace internal {
 
-namespace {
-
-AtomicSequenceNumber g_sequence_nums_for_tracing;
-
-}  // namespace
-
 Task::Task(const Location& posted_from,
            OnceClosure task,
            TimeTicks queue_time,
@@ -39,15 +31,7 @@
                   queue_time,
                   delayed_run_time,
                   leeway,
-                  delay_policy) {
-  // ThreadPoolImpl doesn't use |sequence_num| but tracing (toplevel.flow)
-  // relies on it being unique. While this subtle dependency is a bit
-  // overreaching, ThreadPoolImpl is the only task system that doesn't use
-  // |sequence_num| and the dependent code rarely changes so this isn't worth a
-  // big change and faking it here isn't too bad for now (posting tasks is full
-  // of atomic ops already).
-  this->sequence_num = g_sequence_nums_for_tracing.GetNext();
-}
+                  delay_policy) {}
 
 // This should be "= default but MSVC has trouble with "noexcept = default" in
 // this case.
diff --git a/base/task/thread_pool/task_tracker.cc b/base/task/thread_pool/task_tracker.cc
index 94db917..a8a5fe6 100644
--- a/base/task/thread_pool/task_tracker.cc
+++ b/base/task/thread_pool/task_tracker.cc
@@ -309,6 +309,7 @@
   DCHECK(task);
   DCHECK(task->task);
 
+  task->sequence_num = sequence_nums_.GetNext();
   if (state_->HasShutdownStarted()) {
     // A non BLOCK_SHUTDOWN task is allowed to be posted iff shutdown hasn't
     // started and the task is not delayed.
diff --git a/base/task/thread_pool/task_tracker.h b/base/task/thread_pool/task_tracker.h
index b4267faf..eaf9791 100644
--- a/base/task/thread_pool/task_tracker.h
+++ b/base/task/thread_pool/task_tracker.h
@@ -12,6 +12,7 @@
 #include <queue>
 #include <string>
 
+#include "base/atomic_sequence_num.h"
 #include "base/atomicops.h"
 #include "base/base_export.h"
 #include "base/containers/circular_deque.h"
@@ -268,6 +269,9 @@
   // completes.
   std::unique_ptr<WaitableEvent> shutdown_event_ GUARDED_BY(shutdown_lock_);
 
+  // Used to generate unique |PendingTask::sequence_num| when posting tasks.
+  AtomicSequenceNumber sequence_nums_;
+
   // Ensures all state (e.g. dangling cleaned up workers) is coalesced before
   // destroying the TaskTracker (e.g. in test environments).
   // Ref. https://crbug.com/827615.
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h
index 292e5ce..2f9a981 100644
--- a/base/trace_event/builtin_categories.h
+++ b/base/trace_event/builtin_categories.h
@@ -32,6 +32,7 @@
   /* The rest of the list is in alphabetical order */                    \
   X("accessibility")                                                     \
   X("AccountFetcherService")                                             \
+  X("android.ui.jank")                                                   \
   X("android_webview")                                                   \
   X("android_webview.timeline")                                          \
   /* Actions on Google Hardware, used in Google-internal code. */        \
@@ -298,6 +299,7 @@
 
 #define INTERNAL_TRACE_LIST_BUILTIN_CATEGORY_GROUPS(X)                        \
   X("android_webview,toplevel")                                               \
+  X("android_webview.timeline,android.ui.jank")                               \
   X("base,toplevel")                                                          \
   X("benchmark,drm")                                                          \
   X("benchmark,latencyInfo,rail")                                             \
diff --git a/base/win/message_window.cc b/base/win/message_window.cc
index 9e9f3cc5..7487627 100644
--- a/base/win/message_window.cc
+++ b/base/win/message_window.cc
@@ -13,9 +13,13 @@
 #include "base/check_op.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/memory/raw_ref.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_util.h"
+#include "base/thread_annotations.h"
+#include "base/threading/thread_checker.h"
+#include "base/threading/thread_local.h"
 #include "base/win/current_module.h"
 #include "base/win/resource_exhaustion.h"
 #include "base/win/wrapped_window_proc.h"
@@ -27,11 +31,17 @@
 
 namespace {
 
+// This class can be accessed from multiple threads,
+// this is handled by each thread having a different instance.
 class MessageWindowMap {
  public:
-  static MessageWindowMap& GetInstance() {
-    static base::NoDestructor<MessageWindowMap> message_window_map;
-    return *message_window_map;
+  static MessageWindowMap& GetInstanceForCurrentThread() {
+    static base::NoDestructor<base::ThreadLocalOwnedPointer<MessageWindowMap>>
+        instance;
+    if (!instance->Get()) {
+      instance->Set(base::WrapUnique(new MessageWindowMap));
+    }
+    return *(instance->Get());
   }
 
   MessageWindowMap(const MessageWindowMap&) = delete;
@@ -39,17 +49,20 @@
 
   // Each key should only be inserted once.
   void Insert(HWND hwnd, base::win::MessageWindow& message_window) {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     CHECK(map_.emplace(hwnd, message_window).second);
   }
 
   // Erase should only be called on an existing key.
   void Erase(HWND hwnd) {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     // Check that exactly one element is erased from the map.
     CHECK_EQ(map_.erase(hwnd), 1u);
   }
 
   // Will return nullptr if `hwnd` is not in the map.
   base::win::MessageWindow* Get(HWND hwnd) const {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     if (auto search = map_.find(hwnd); search != map_.end()) {
       return &(search->second.get());
     }
@@ -57,9 +70,10 @@
   }
 
  private:
-  friend class base::NoDestructor<MessageWindowMap>;
   MessageWindowMap() = default;
-  std::map<HWND, const raw_ref<base::win::MessageWindow>> map_;
+  THREAD_CHECKER(thread_checker_);
+  std::map<HWND, const raw_ref<base::win::MessageWindow>> map_
+      GUARDED_BY_CONTEXT(thread_checker_);
 };
 
 }  // namespace
@@ -173,7 +187,9 @@
                                            UINT message,
                                            WPARAM wparam,
                                            LPARAM lparam) {
-  auto& message_window_map = MessageWindowMap::GetInstance();
+  // This can be called from different threads for different windows,
+  // each thread has its own MessageWindowMap instance.
+  auto& message_window_map = MessageWindowMap::GetInstanceForCurrentThread();
   MessageWindow* self = message_window_map.Get(hwnd);
 
   switch (message) {
diff --git a/build/android/gyp/bytecode_processor.py b/build/android/gyp/bytecode_processor.py
index 421b54e..e6c41c3 100755
--- a/build/android/gyp/bytecode_processor.py
+++ b/build/android/gyp/bytecode_processor.py
@@ -21,8 +21,8 @@
 import action_helpers  # build_utils adds //build to sys.path.
 
 _SRC_PATH = pathlib.Path(build_utils.DIR_SOURCE_ROOT).resolve()
-sys.path.append(str(_SRC_PATH / 'tools/android/modularization/gn'))
-from dep_operations import NO_VALID_GN_STR
+sys.path.append(str(_SRC_PATH / 'build/gn_ast'))
+from gn_editor import NO_VALID_GN_STR
 
 
 def _ShouldIgnoreDep(dep_name: str):
diff --git a/build/android/gyp/bytecode_processor.pydeps b/build/android/gyp/bytecode_processor.pydeps
index 78db0c45..a729800 100644
--- a/build/android/gyp/bytecode_processor.pydeps
+++ b/build/android/gyp/bytecode_processor.pydeps
@@ -9,13 +9,10 @@
 ../../../third_party/catapult/devil/devil/android/sdk/version_codes.py
 ../../../third_party/catapult/devil/devil/constants/__init__.py
 ../../../third_party/catapult/devil/devil/constants/exit_codes.py
-../../../tools/android/modularization/gn/dep_operations.py
-../../../tools/android/modularization/gn/json_gn_editor.py
-../../../tools/android/modularization/gn/utils.py
-../../../tools/android/python_utils/__init__.py
-../../../tools/android/python_utils/git_metadata_utils.py
-../../../tools/android/python_utils/subprocess_utils.py
 ../../action_helpers.py
+../../gn_ast/gn_editor.py
+../../gn_ast/json_gn_editor.py
+../../gn_ast/utils.py
 ../../gn_helpers.py
 ../list_java_targets.py
 ../pylib/__init__.py
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py
index 95109c3..23c598e 100755
--- a/build/android/gyp/lint.py
+++ b/build/android/gyp/lint.py
@@ -355,18 +355,14 @@
                                 stderr_filter=stderr_filter,
                                 fail_on_output=warnings_as_errors,
                                 fail_func=fail_func))
+  except build_utils.CalledProcessError as e:
+    # Do not output the python stacktrace because it is lengthy and is not
+    # relevant to the actual lint error.
+    sys.stderr.write(e.output)
   finally:
     # When not treating warnings as errors, display the extra footer.
     is_debug = os.environ.get('LINT_DEBUG', '0') != '0'
 
-    if failed:
-      print('- For more help with lint in Chrome:', _LINT_MD_URL)
-      if is_debug:
-        print('- DEBUG MODE: Here is the project.xml: {}'.format(
-            _SrcRelative(project_xml_path)))
-      else:
-        print('- Run with LINT_DEBUG=1 to enable lint configuration debugging')
-
     end = time.time() - start
     logging.info('Lint command took %ss', end)
     if not is_debug:
@@ -375,6 +371,15 @@
       shutil.rmtree(srcjar_root_dir, ignore_errors=True)
       os.unlink(project_xml_path)
 
+    if failed:
+      print('- For more help with lint in Chrome:', _LINT_MD_URL)
+      if is_debug:
+        print('- DEBUG MODE: Here is the project.xml: {}'.format(
+            _SrcRelative(project_xml_path)))
+      else:
+        print('- Run with LINT_DEBUG=1 to enable lint configuration debugging')
+      sys.exit(1)
+
   logging.info('Lint completed')
 
 
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index 752aa21..938c7041 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -224,6 +224,7 @@
   logging.info('CheckOutput: %s', ' '.join(args))
   child = subprocess.Popen(args,
       stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env)
+
   stdout, stderr = child.communicate()
 
   # For Python3 only:
diff --git a/build/android/gyp/util/dep_utils.py b/build/android/gyp/util/dep_utils.py
index c849df6..cbf8937 100644
--- a/build/android/gyp/util/dep_utils.py
+++ b/build/android/gyp/util/dep_utils.py
@@ -255,8 +255,8 @@
 
   build_file_path = GnTargetToBuildFilePath(gn_target)
   return [
-      'tools/android/modularization/gn/dep_operations.py', 'add', '--quiet',
-      '--file', build_file_path, '--target', gn_target, '--deps'
+      'build/gn_editor', 'add', '--quiet', '--file', build_file_path,
+      '--target', gn_target, '--deps'
   ] + missing_deps
 
 
diff --git a/build/android/gyp/util/server_utils.py b/build/android/gyp/util/server_utils.py
index b634cf9..6d5ed79 100644
--- a/build/android/gyp/util/server_utils.py
+++ b/build/android/gyp/util/server_utils.py
@@ -5,6 +5,7 @@
 import contextlib
 import json
 import os
+import pathlib
 import socket
 
 # Use a unix abstract domain socket:
@@ -44,4 +45,9 @@
               '$ build/android/fast_local_dev_server.py\n\n') from None
         return False
       raise e
+
+  # Siso needs the stamp file to be created in order for the build step to
+  # complete. If the task fails when the build server runs it, the build server
+  # will delete the stamp file so that it will be run again next build.
+  pathlib.Path(stamp_file).touch()
   return True
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py
index 39b90d0..582e690 100644
--- a/build/android/pylib/local/device/local_device_environment.py
+++ b/build/android/pylib/local/device/local_device_environment.py
@@ -86,26 +86,6 @@
   return decorator
 
 
-# TODO(b/293175593): Use PlaceNomediaFile after
-# https://crrev.com/c/4877296 lands
-def place_nomedia_on_device(dev, device_root, as_root=False):
-  """Places .nomedia file in test data root.
-
-  This helps to prevent system from scanning media files inside test data.
-
-  Args:
-    dev: Device to place .nomedia file.
-    device_root: Base path on device to place .nomedia file.
-  """
-
-  dev.RunShellCommand(['mkdir', '-p', device_root],
-                      check_return=True,
-                      as_root=as_root)
-  dev.WriteFile('%s/.nomedia' % device_root,
-                'https://crbug.com/796640',
-                as_root=as_root)
-
-
 # TODO(1262303): After Telemetry is supported by python3 we can re-add
 # super without arguments in this script.
 # pylint: disable=super-with-arguments
diff --git a/build/android/pylib/local/device/local_device_gtest_run.py b/build/android/pylib/local/device/local_device_gtest_run.py
index 86fe489..0b49651 100644
--- a/build/android/pylib/local/device/local_device_gtest_run.py
+++ b/build/android/pylib/local/device/local_device_gtest_run.py
@@ -430,8 +430,7 @@
         host_device_tuples_substituted = [
             (h, local_device_test_run.SubstituteDeviceRoot(d, device_root))
             for h, d in host_device_tuples]
-        local_device_environment.place_nomedia_on_device(
-            dev, device_root, as_root=self._env.force_main_user)
+        dev.PlaceNomediaFile(device_root)
         dev.PushChangedFiles(
             host_device_tuples_substituted,
             delete_device_stale=True,
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 2ba7ab2f..e146156 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -461,8 +461,7 @@
         logging.info('Pushing data dependencies.')
         for h, d in host_device_tuples_substituted:
           logging.debug('  %r -> %r', h, d)
-        local_device_environment.place_nomedia_on_device(
-            dev, test_data_root_dir)
+        dev.PlaceNomediaFile(test_data_root_dir)
         dev.PushChangedFiles(host_device_tuples_substituted,
                              delete_device_stale=True,
                              as_root=self._env.force_main_user)
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index f0f370e..965a16f 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -95,12 +95,6 @@
   assert(android_static_analysis == "on" || android_static_analysis == "off" ||
          android_static_analysis == "build_server")
 
-  # Build server modifies stamp files independently of builds.
-  # Siso is not well-suited for this use case.
-  assert(
-      !(android_static_analysis == "build_server" && use_siso),
-      "Siso doesn't support android_static_analysis=\"build_server\". Please set android_static_analysis=\"on\"")
-
   # This configuration has not bot coverage and has broken multiple times.
   # Warn against it.
   assert(!(enable_chrome_android_internal && skip_secondary_abi_for_cq))
diff --git a/tools/android/modularization/gn/dep_operations.py b/build/gn_ast/gn_editor.py
similarity index 95%
rename from tools/android/modularization/gn/dep_operations.py
rename to build/gn_ast/gn_editor.py
index 797a4d0..3b63ba8 100755
--- a/tools/android/modularization/gn/dep_operations.py
+++ b/build/gn_ast/gn_editor.py
@@ -18,15 +18,19 @@
 import json_gn_editor
 import utils
 
-_TOOLS_ANDROID_PATH = pathlib.Path(__file__).resolve().parents[2]
-if str(_TOOLS_ANDROID_PATH) not in sys.path:
-    sys.path.append(str(_TOOLS_ANDROID_PATH))
-from python_utils import git_metadata_utils, subprocess_utils
+_SRC_PATH = pathlib.Path(__file__).resolve().parents[2]
 
-_SRC_PATH = git_metadata_utils.get_chromium_src_path()
-sys.path.append(str(_SRC_PATH / 'build' / 'android'))
+_BUILD_ANDROID_PATH = _SRC_PATH / 'build/android'
+if str(_BUILD_ANDROID_PATH) not in sys.path:
+    sys.path.append(str(_BUILD_ANDROID_PATH))
 from pylib import constants
 
+_BUILD_ANDROID_GYP_PATH = _SRC_PATH / 'build/android/gyp'
+if str(_BUILD_ANDROID_GYP_PATH) not in sys.path:
+    sys.path.append(str(_BUILD_ANDROID_GYP_PATH))
+
+from util import build_utils
+
 _GIT_IGNORE_STR = '(git ignored file) '
 
 NO_VALID_GN_STR = 'No valid GN files found after filtering.'
@@ -177,13 +181,13 @@
         # TODO: Ensure that the build server is not running.
 
     logging.info(f'Running "gn gen" in output directory: {out_dir}')
-    subprocess_utils.run_command(['gn', 'gen', '-C', out_dir, '--ide=json'])
+    build_utils.CheckOutput(['gn', 'gen', '-C', out_dir, '--ide=json'])
 
     if args.all_java_deps:
         assert not args.dep, '--all-java-target does not support passing deps.'
         assert args.file, '--all-java-target requires passing --file.'
         logging.info(f'Finding java deps under {out_dir}.')
-        all_java_deps = subprocess_utils.run_command([
+        all_java_deps = build_utils.CheckOutput([
             str(_SRC_PATH / 'build' / 'android' / 'list_java_targets.py'),
             '--gn-labels', '-C', out_dir
         ]).split('\n')
@@ -264,7 +268,7 @@
 
 def main():
     parser = argparse.ArgumentParser(
-        description='Add or remove deps programatically.')
+        prog='gn_editor', description='Add or remove deps programatically.')
 
     common_args_parser = argparse.ArgumentParser(add_help=False)
     common_args_parser.add_argument(
@@ -287,7 +291,7 @@
         help='Skip files before this build file path (debugging).')
 
     subparsers = parser.add_subparsers(
-        help='Use subcommand -h to see full usage.')
+        required=True, help='Use subcommand -h to see full usage.')
 
     add_parser = subparsers.add_parser(
         'add',
@@ -375,7 +379,7 @@
     logging.basicConfig(
         level=level, format='%(levelname).1s %(relativeCreated)7d %(message)s')
 
-    root = git_metadata_utils.get_chromium_src_path()
+    root = _SRC_PATH
     if args.file:
         build_filepaths = [os.path.relpath(args.file, root)]
     else:
diff --git a/tools/android/modularization/gn/json_gn_editor.py b/build/gn_ast/json_gn_editor.py
similarity index 96%
rename from tools/android/modularization/gn/json_gn_editor.py
rename to build/gn_ast/json_gn_editor.py
index ce67e86..abafb63 100644
--- a/tools/android/modularization/gn/json_gn_editor.py
+++ b/build/gn_ast/json_gn_editor.py
@@ -20,12 +20,13 @@
 
 from typing import Dict, Iterator, List, Optional, Tuple
 
-_TOOLS_ANDROID_PATH = pathlib.Path(__file__).resolve().parents[2]
-if str(_TOOLS_ANDROID_PATH) not in sys.path:
-    sys.path.insert(0, str(_TOOLS_ANDROID_PATH))
-from python_utils import git_metadata_utils, subprocess_utils
+_SRC_PATH = pathlib.Path(__file__).resolve().parents[2]
 
-_SRC_PATH = git_metadata_utils.get_chromium_src_path()
+_BUILD_ANDROID_GYP_PATH = _SRC_PATH / 'build/android/gyp'
+if str(_BUILD_ANDROID_GYP_PATH) not in sys.path:
+    sys.path.append(str(_BUILD_ANDROID_GYP_PATH))
+
+from util import build_utils
 
 # Refer to parse_tree.cc for GN AST implementation details:
 # https://gn.googlesource.com/gn/+/refs/heads/main/src/gn/parse_tree.cc
@@ -52,10 +53,10 @@
             f.write(contents)
 
 
-def _build_targets_output(out_dir: str,
-                          targets: List[str],
-                          should_print: Optional[bool] = None
-                          ) -> Optional[str]:
+def _build_targets_output(
+        out_dir: str,
+        targets: List[str],
+        should_print: Optional[bool] = None) -> Optional[str]:
     env = os.environ.copy()
     if should_print is None:
         should_print = logging.getLogger().isEnabledFor(logging.DEBUG)
@@ -102,7 +103,7 @@
 
 
 def _generate_project_json_content(out_dir: str) -> str:
-    subprocess_utils.run_command(['gn', 'gen', '--ide=json', out_dir])
+    build_utils.CheckOutput(['gn', 'gen', '--ide=json', out_dir])
     with open(os.path.join(out_dir, 'project.json')) as f:
         return f.read()
 
@@ -118,7 +119,6 @@
 
 class BuildFile:
     """Represents the contents of a BUILD.gn file."""
-
     def __init__(self,
                  build_gn_path: str,
                  root_gn_path: pathlib.Path,
@@ -131,7 +131,7 @@
         self._skip_write_content = dryrun
 
     def __enter__(self):
-        output = subprocess_utils.run_command(
+        output = build_utils.CheckOutput(
             ['gn', 'format', '--dump-tree=json', self._full_path])
         self._content = json.loads(output)
         self._original_content = json.dumps(self._content)
@@ -141,7 +141,6 @@
         if not self._skip_write_content:
             self.write_content_to_file()
 
-
     # See: https://gist.github.com/sgraham/bd9ffee312f307d5f417019a9c0f0777
     def _find_all(self, match_fn):
         results = []
@@ -226,7 +225,6 @@
         return name
 
     def _find_all_list_assignments(self):
-
         def match_list_assignments(node):
             r"""Matches and returns the list being assigned.
 
@@ -558,6 +556,8 @@
     def write_content_to_file(self) -> None:
         current_content = json.dumps(self._content)
         if current_content != self._original_content:
-            subprocess_utils.run_command(
+            subprocess.run(
                 ['gn', 'format', '--read-tree=json', self._full_path],
-                cmd_input=current_content)
+                text=True,
+                check=True,
+                input=current_content)
diff --git a/tools/android/modularization/gn/json_gn_editor_test.py b/build/gn_ast/json_gn_editor_test.py
similarity index 100%
rename from tools/android/modularization/gn/json_gn_editor_test.py
rename to build/gn_ast/json_gn_editor_test.py
diff --git a/tools/android/modularization/gn/utils.py b/build/gn_ast/utils.py
similarity index 75%
rename from tools/android/modularization/gn/utils.py
rename to build/gn_ast/utils.py
index aa4049e3..05fe41b 100644
--- a/tools/android/modularization/gn/utils.py
+++ b/build/gn_ast/utils.py
@@ -6,12 +6,7 @@
 import logging
 import os
 import pathlib
-import sys
-
-_TOOLS_ANDROID_PATH = pathlib.Path(__file__).resolve().parents[2]
-if str(_TOOLS_ANDROID_PATH) not in sys.path:
-    sys.path.append(str(_TOOLS_ANDROID_PATH))
-from python_utils import subprocess_utils
+import subprocess
 
 # These paths should be relative to repository root.
 _BAD_FILES = [
@@ -35,6 +30,6 @@
 def is_git_ignored(root: pathlib.Path, filepath: str) -> bool:
     # The command git check-ignore exits with 0 if the path is ignored, 1 if it
     # is not ignored.
-    exit_code = subprocess_utils.run_command(
-        ['git', 'check-ignore', '-q', filepath], cwd=root, exitcode_only=True)
+    exit_code = subprocess.run(['git', 'check-ignore', '-q', filepath],
+                               cwd=root).returncode
     return exit_code == 0
diff --git a/build/gn_editor b/build/gn_editor
new file mode 100755
index 0000000..ecf86e8
--- /dev/null
+++ b/build/gn_editor
@@ -0,0 +1,8 @@
+#!/bin/bash
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+base_dir=$(dirname "$0")
+
+exec python3 "$base_dir/gn_ast/gn_editor.py" "$@"
diff --git a/cc/layers/painted_scrollbar_layer_impl.cc b/cc/layers/painted_scrollbar_layer_impl.cc
index 4b9dff3..c7c105a5 100644
--- a/cc/layers/painted_scrollbar_layer_impl.cc
+++ b/cc/layers/painted_scrollbar_layer_impl.cc
@@ -81,7 +81,7 @@
 }
 
 float PaintedScrollbarLayerImpl::OverlayScrollbarOpacity() const {
-  return painted_opacity_;
+  return IsFluentOverlayScrollbarEnabled() ? Opacity() : painted_opacity_;
 }
 
 bool PaintedScrollbarLayerImpl::WillDraw(
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 55ad782..fe92eab 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1381,7 +1381,6 @@
       "javatests/src/org/chromium/chrome/browser/share/ShareUrlTest.java",
       "javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java",
       "javatests/src/org/chromium/chrome/browser/tab/WebContentsStateBridgeTest.java",
-      "javatests/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorageTest.java",
       "javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java",
       "javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java",
       "javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java",
@@ -1499,12 +1498,6 @@
     data = [ "//chrome/test/data/android/" ]
   }
 
-  flatbuffer_java_library(
-      "critical_persisted_tab_data_flatbuffer_test_v1_java") {
-    root_dir = "javatests/src/org/chromium/chrome/browser/tab/state/"
-    sources = [ "$root_dir/critical_persisted_tab_data_test_v1.fbs" ]
-  }
-
   android_library("chrome_test_java") {
     testonly = true
     resources_package = "org.chromium.chrome.test"
@@ -1520,7 +1513,6 @@
       ":browser_java_test_support",
       ":chrome_app_java_resources",
       ":chrome_test_util_java",
-      ":critical_persisted_tab_data_flatbuffer_test_v1_java",
       ":delegate_public_impl_java",
       "$google_play_services_package:google_play_services_base_java",
       "$google_play_services_package:google_play_services_basement_java",
@@ -1641,7 +1633,6 @@
       "//chrome/browser/supervised_user:test_support_java",
       "//chrome/browser/sync/android:java",
       "//chrome/browser/sync/test/android:test_support_java",
-      "//chrome/browser/tab:critical_persisted_tab_data_flatbuffer_java",
       "//chrome/browser/tab:critical_persisted_tab_data_proto_java",
       "//chrome/browser/tab:java",
       "//chrome/browser/tab_group:java",
diff --git a/chrome/android/DEPS b/chrome/android/DEPS
index e602190..21a3802 100644
--- a/chrome/android/DEPS
+++ b/chrome/android/DEPS
@@ -48,6 +48,7 @@
   "+components/permissions/android/nfc",
   "+components/policy",
   "+components/prefs/android",
+  "+components/privacy_sandbox/android",
   "+components/query_tiles",
   "+components/safe_browsing/android/java",
   "+components/security_interstitials/content/android",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index c532599b..7ff56ec0 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -375,6 +375,7 @@
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java",
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java",
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStacker.java",
+  "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripTabHoverCardView.java",
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java",
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDropTarget.java",
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabLoadTracker.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 2d75658..456acaf 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -116,6 +116,7 @@
   "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTabTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStackerUnitTest.java",
+  "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripTabHoverCardViewUnitTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSourceTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDropTargetTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabUsageTrackerTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 4b00000..81cc4f8 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -484,7 +484,6 @@
   "javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java",
   "javatests/src/org/chromium/chrome/browser/tab/TabViewManagerTest.java",
   "javatests/src/org/chromium/chrome/browser/tab/UndoIntegrationTest.java",
-  "javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java",
   "javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedDataStorageTest.java",
   "javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageFactoryTest.java",
   "javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java",
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
index 963cd951..e2292ac 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
@@ -13,6 +13,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.recyclerview.widget.RecyclerView;
 
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.app.feed.FeedActionDelegateImpl;
@@ -50,6 +51,7 @@
     public static final String FEED_CONTENT_FIRST_LOADED_TIME_MS_UMA = "FeedContentFirstLoadedTime";
 
     private final Activity mActivity;
+    private final JankTracker mJankTracker;
     private final FeedSurfaceCoordinator mFeedSurfaceCoordinator;
     private final ExploreSurfaceNavigationDelegate mExploreSurfaceNavigationDelegate;
     private final boolean mIsPlaceholderShownInitially;
@@ -69,13 +71,14 @@
             long embeddingSurfaceConstructedTimeNs, FeedSwipeRefreshLayout swipeRefreshLayout,
             ViewGroup parentView, Supplier<Tab> parentTabSupplier, SnackbarManager snackbarManager,
             Supplier<ShareDelegate> shareDelegateSupplier, WindowAndroid windowAndroid,
-            TabModelSelector tabModelSelector) {
+            JankTracker jankTracker, TabModelSelector tabModelSelector) {
         mActivity = activity;
+        mJankTracker = jankTracker;
         mExploreSurfaceNavigationDelegate = new ExploreSurfaceNavigationDelegate(parentTabSupplier);
         mIsPlaceholderShownInitially = isPlaceholderShown;
 
         mFeedSurfaceCoordinator = new FeedSurfaceCoordinator(mActivity, snackbarManager,
-                windowAndroid, /*snapScrollHelper=*/null, /*ntpHeader=*/null,
+                windowAndroid, mJankTracker, /*snapScrollHelper=*/null, /*ntpHeader=*/null,
                 mActivity.getResources().getDimensionPixelSize(R.dimen.toolbar_height_no_shadow),
                 isInNightMode, /*delegate=*/new ExploreFeedSurfaceDelegate(), profile,
                 isPlaceholderShown, bottomSheetController, shareDelegateSupplier,
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinatorFactory.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinatorFactory.java
index 8d7f3b89..608ed24 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinatorFactory.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinatorFactory.java
@@ -10,6 +10,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.feed.FeedSwipeRefreshLayout;
 import org.chromium.chrome.browser.feed.ScrollableContainerDelegate;
@@ -33,6 +34,7 @@
     private final SnackbarManager mSnackbarManager;
     private final Supplier<ShareDelegate> mShareDelegateSupplier;
     private final WindowAndroid mWindowAndroid;
+    private final JankTracker mJankTracker;
     private final TabModelSelector mTabModelSelector;
     private final BottomSheetController mBottomSheetController;
     private final ScrollableContainerDelegate mScrollableContainerDelegate;
@@ -54,6 +56,7 @@
      * @param snackbarManager Manages the snackbar.
      * @param shareDelegateSupplier Supplies the {@link ShareDelegate}.
      * @param windowAndroid The current {@link WindowAndroid}.
+     * @param jankTracker tracks jank.
      * @param tabModelSelector The current {@link TabModelSelector}.
      * @param toolbarSupplier Supplies the {@link Toolbar}.
      * @param embeddingSurfaceConstructedTimeNs Timestamp taken when the caller was constructed.
@@ -66,8 +69,9 @@
             @NonNull ScrollableContainerDelegate scrollableContainerDelegate,
             @NonNull SnackbarManager snackbarManager,
             @NonNull Supplier<ShareDelegate> shareDelegateSupplier,
-            @NonNull WindowAndroid windowAndroid, @NonNull TabModelSelector tabModelSelector,
-            @NonNull Supplier<Toolbar> toolbarSupplier, long embeddingSurfaceConstructedTimeNs,
+            @NonNull WindowAndroid windowAndroid, @NonNull JankTracker jankTracker,
+            @NonNull TabModelSelector tabModelSelector, @NonNull Supplier<Toolbar> toolbarSupplier,
+            long embeddingSurfaceConstructedTimeNs,
             @Nullable FeedSwipeRefreshLayout swipeRefreshLayout) {
         mActivity = activity;
         mParentView = parentView;
@@ -75,6 +79,7 @@
         mSnackbarManager = snackbarManager;
         mShareDelegateSupplier = shareDelegateSupplier;
         mWindowAndroid = windowAndroid;
+        mJankTracker = jankTracker;
         mTabModelSelector = tabModelSelector;
         mBottomSheetController = bottomSheetController;
         mScrollableContainerDelegate = scrollableContainerDelegate;
@@ -99,6 +104,6 @@
                 mBottomSheetController, mScrollableContainerDelegate, launchOrigin,
                 mToolbarSupplier, mEmbeddingSurfaceConstructedTimeNs, mSwipeRefreshLayout,
                 mParentView, mParentTabSupplier, mSnackbarManager, mShareDelegateSupplier,
-                mWindowAndroid, mTabModelSelector);
+                mWindowAndroid, mJankTracker, mTabModelSelector);
     }
 }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
index d9273a0..de3e81e 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -24,6 +24,7 @@
 import org.chromium.base.Log;
 import org.chromium.base.MathUtils;
 import org.chromium.base.ObserverList;
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
@@ -105,6 +106,7 @@
     private final BottomSheetController mBottomSheetController;
     private final Supplier<Tab> mParentTabSupplier;
     private final WindowAndroid mWindowAndroid;
+    private final JankTracker mJankTracker;
     private ViewGroup mContainerView;
     private final Supplier<DynamicResourceLoader> mDynamicResourceLoaderSupplier;
     private final TabModelSelector mTabModelSelector;
@@ -249,7 +251,8 @@
      * @param startSurfaceOneshotSupplier Supplies the start surface.
      * @param parentTabSupplier Supplies the current parent {@link Tab}.
      * @param hadWarmStart Whether the application had a warm start.
-     * @param windowAndroid The current {@link WindowAndroid}.
+     * @param windowAndroid The current {@link WindowAndroid}.a
+     * @param jankTracker asd
      * @param containerView The container {@link ViewGroup} for this ui, also the root view for
      *         StartSurface.
      * @param dynamicResourceLoaderSupplier Supplies the current {@link DynamicResourceLoader}.
@@ -277,7 +280,8 @@
             @NonNull BottomSheetController sheetController,
             @NonNull OneshotSupplierImpl<StartSurface> startSurfaceOneshotSupplier,
             @NonNull Supplier<Tab> parentTabSupplier, boolean hadWarmStart,
-            @NonNull WindowAndroid windowAndroid, @NonNull ViewGroup containerView,
+            @NonNull WindowAndroid windowAndroid, @NonNull JankTracker jankTracker,
+            @NonNull ViewGroup containerView,
             @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
             @NonNull TabModelSelector tabModelSelector,
             @NonNull BrowserControlsManager browserControlsManager,
@@ -302,6 +306,7 @@
         mBottomSheetController = sheetController;
         mParentTabSupplier = parentTabSupplier;
         mWindowAndroid = windowAndroid;
+        mJankTracker = jankTracker;
         mContainerView = containerView;
         mDynamicResourceLoaderSupplier = dynamicResourceLoaderSupplier;
         mTabModelSelector = tabModelSelector;
@@ -512,8 +517,8 @@
             mExploreSurfaceCoordinatorFactory = new ExploreSurfaceCoordinatorFactory(mActivity,
                     parentView, mPropertyModel, mBottomSheetController, mParentTabSupplier,
                     new ScrollableContainerDelegateImpl(), mSnackbarManager, mShareDelegateSupplier,
-                    mWindowAndroid, mTabModelSelector, mToolbarSupplier, mConstructedTimeNs,
-                    mSwipeRefreshLayout);
+                    mWindowAndroid, mJankTracker, mTabModelSelector, mToolbarSupplier,
+                    mConstructedTimeNs, mSwipeRefreshLayout);
         }
         mStartSurfaceMediator.initWithNative(
                 mIsStartSurfaceEnabled ? mOmniboxStubSupplier.get() : null,
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
index c2c2d4c..39bca6e1 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
@@ -11,6 +11,7 @@
 
 import androidx.annotation.NonNull;
 
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.OneshotSupplierImpl;
@@ -118,7 +119,8 @@
             @NonNull BottomSheetController sheetController,
             @NonNull OneshotSupplierImpl<StartSurface> startSurfaceOneshotSupplier,
             @NonNull Supplier<Tab> parentTabSupplier, boolean hadWarmStart,
-            @NonNull WindowAndroid windowAndroid, @NonNull ViewGroup containerView,
+            @NonNull WindowAndroid windowAndroid, @NonNull JankTracker jankTracker,
+            @NonNull ViewGroup containerView,
             @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
             @NonNull TabModelSelector tabModelSelector,
             @NonNull BrowserControlsManager browserControlsManager,
@@ -138,7 +140,7 @@
             @NonNull ObservableSupplier<Profile> profileSupplier) {
         return new StartSurfaceCoordinator(activity, scrimCoordinator, sheetController,
                 startSurfaceOneshotSupplier, parentTabSupplier, hadWarmStart, windowAndroid,
-                containerView, dynamicResourceLoaderSupplier, tabModelSelector,
+                jankTracker, containerView, dynamicResourceLoaderSupplier, tabModelSelector,
                 browserControlsManager, snackbarManager, shareDelegateSupplier, omniboxStubSupplier,
                 tabContentManager, modalDialogManager, chromeActivityNativeDelegate,
                 activityLifecycleDispatcher, tabCreatorManager, menuOrKeyboardActionController,
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java
index 56910f6e..00a1224 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java
@@ -30,6 +30,7 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import org.chromium.base.jank_tracker.PlaceholderJankTracker;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Restriction;
@@ -82,6 +83,7 @@
                             mActivityTestRule.getActivity().getSnackbarManager(),
                             mActivityTestRule.getActivity().getShareDelegateSupplier(),
                             mActivityTestRule.getActivity().getWindowAndroid(),
+                            new PlaceholderJankTracker(),
                             mActivityTestRule.getActivity().getTabModelSelector(),
                             () -> { return null; }, 0L, null);
             mExploreSurfaceCoordinator = mExploreSurfaceCoordinatorFactory.create(
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTestRule.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTestRule.java
index 98cb688..04726d7 100644
--- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTestRule.java
+++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTestRule.java
@@ -26,6 +26,7 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.FeatureList;
 import org.chromium.base.FeatureListJni;
+import org.chromium.base.jank_tracker.PlaceholderJankTracker;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneshotSupplierImpl;
@@ -251,9 +252,9 @@
 
         mCoordinator = new StartSurfaceCoordinator(mActivity, scrimCoordinator,
                 Mockito.mock(BottomSheetController.class), new OneshotSupplierImpl<>(),
-                new ObservableSupplierImpl<>(), false, windowAndroid, mContainerView,
-                new ObservableSupplierImpl<>(), mTabModelSelector, browserControlsManager,
-                snackbarManager, new ObservableSupplierImpl<>(),
+                new ObservableSupplierImpl<>(), false, windowAndroid, new PlaceholderJankTracker(),
+                mContainerView, new ObservableSupplierImpl<>(), mTabModelSelector,
+                browserControlsManager, snackbarManager, new ObservableSupplierImpl<>(),
                 ()
                         -> omniboxStub,
                 tabContentManager, new FakeModalDialogManager(ModalDialogType.APP),
diff --git a/chrome/android/features/tab_ui/java/res/layout/tab_hover_card_holder.xml b/chrome/android/features/tab_ui/java/res/layout/tab_hover_card_holder.xml
index b9e4c7c..cae4721 100644
--- a/chrome/android/features/tab_ui/java/res/layout/tab_hover_card_holder.xml
+++ b/chrome/android/features/tab_ui/java/res/layout/tab_hover_card_holder.xml
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<LinearLayout
+<org.chromium.chrome.browser.compositor.overlays.strip.StripTabHoverCardView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/tab_hover_card_holder"
@@ -35,4 +35,4 @@
       android:maxLines="1"
       android:textDirection="locale"
       android:textAppearance="@style/TextAppearance.TextSmall.Secondary"/>
-</LinearLayout>
+</org.chromium.chrome.browser.compositor.overlays.strip.StripTabHoverCardView>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java
index 9796df4..1886dfd 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tabmodel.TabModelFilter;
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -242,8 +241,7 @@
      * @return The timestamp
      */
     public static long getTimestampMillis(int id) {
-        return getSharedPreferences().getLong(
-                getTimestampMillisKey(id), CriticalPersistedTabData.INVALID_TIMESTAMP);
+        return getSharedPreferences().getLong(getTimestampMillisKey(id), Tab.INVALID_TIMESTAMP);
     }
 
     private static void cacheTimestampMillis(int id, long timestampMillis) {
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java
index d2894eb6..69a040b 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabImpl;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tabmodel.TabList;
 import org.chromium.chrome.browser.tabmodel.TabModelFilter;
 import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider;
@@ -65,9 +64,6 @@
     @Mock
     TabModelFilterProvider mTabModelFilterProvider;
 
-    @Mock
-    CriticalPersistedTabData mCriticalPersistedTabData;
-
     private TabImpl mTab1;
     private TabImpl mTab2;
     private TabImpl mTab3;
@@ -77,10 +73,10 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        mTab1 = TabUiUnitTestUtils.prepareTab(TAB1_ID, mCriticalPersistedTabData);
-        mTab2 = TabUiUnitTestUtils.prepareTab(TAB2_ID, mCriticalPersistedTabData);
-        mTab3 = TabUiUnitTestUtils.prepareTab(TAB3_ID, mCriticalPersistedTabData);
-        mTab1Copy = TabUiUnitTestUtils.prepareTab(TAB1_ID, mCriticalPersistedTabData);
+        mTab1 = TabUiUnitTestUtils.prepareTab(TAB1_ID);
+        mTab2 = TabUiUnitTestUtils.prepareTab(TAB2_ID);
+        mTab3 = TabUiUnitTestUtils.prepareTab(TAB3_ID);
+        mTab1Copy = TabUiUnitTestUtils.prepareTab(TAB1_ID);
 
         doReturn(mTabModelFilterProvider).when(mTabModelSelector).getTabModelFilterProvider();
     }
@@ -301,7 +297,7 @@
         doReturn(timestamp).when(mTab1).getTimestampMillis();
 
         PseudoTab tab = PseudoTab.fromTabId(TAB1_ID);
-        Assert.assertEquals(CriticalPersistedTabData.INVALID_TIMESTAMP, tab.getTimestampMillis());
+        Assert.assertEquals(Tab.INVALID_TIMESTAMP, tab.getTimestampMillis());
 
         PseudoTab realTab = PseudoTab.fromTab(mTab1);
         Assert.assertNotEquals(tab, realTab);
@@ -458,7 +454,6 @@
         // Timestamp was not set. Without the isInitialized() check,
         // pseudoTab.getTimestampMillis() would crash here with
         // UnsupportedOperationException
-        Assert.assertEquals(
-                CriticalPersistedTabData.INVALID_TIMESTAMP, pseudoTab.getTimestampMillis());
+        Assert.assertEquals(Tab.INVALID_TIMESTAMP, pseudoTab.getTimestampMillis());
     }
 }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiUnitTestUtils.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiUnitTestUtils.java
index f4a0d4b..b454e846 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiUnitTestUtils.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiUnitTestUtils.java
@@ -6,12 +6,10 @@
 
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 import org.chromium.base.UserDataHost;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabImpl;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tab.state.PersistedTabData;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.url.GURL;
@@ -62,20 +60,6 @@
         return tab;
     }
 
-    public static TabImpl prepareTab(int tabId, CriticalPersistedTabData criticalPersistedTabData) {
-        TabImpl tab = prepareTab();
-        doReturn(tabId).when(tab).getId();
-        prepareCriticalPersistedTabData(tab, criticalPersistedTabData);
-        return tab;
-    }
-
-    private static void prepareCriticalPersistedTabData(
-            TabImpl tab, CriticalPersistedTabData criticalPersistedTabData) {
-        UserDataHost userDataHost = new UserDataHost();
-        userDataHost.setUserData(CriticalPersistedTabData.class, criticalPersistedTabData);
-        when(tab.getUserDataHost()).thenReturn(userDataHost);
-    }
-
     public static TabImpl prepareTab(int tabId, int rootId) {
         TabImpl tab = prepareTab(tabId);
         doReturn(rootId).when(tab).getRootId();
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
index 55b79dd..ed5682e 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -29,7 +29,10 @@
 import org.chromium.base.CommandLine;
 import org.chromium.base.ObserverList;
 import org.chromium.base.ResettersForTesting;
+import org.chromium.base.TimeUtils;
 import org.chromium.base.TraceEvent;
+import org.chromium.base.jank_tracker.JankScenario;
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
@@ -48,6 +51,7 @@
 import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.share.ShareDelegate;
+import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.top.Toolbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
@@ -65,6 +69,11 @@
 import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.feature_engagement.Tracker;
+import org.chromium.components.signin.Tribool;
+import org.chromium.components.signin.base.AccountInfo;
+import org.chromium.components.signin.base.CoreAccountInfo;
+import org.chromium.components.signin.identitymanager.ConsentLevel;
+import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.third_party.android.swiperefresh.SwipeRefreshLayout;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.ui.base.ViewUtils;
@@ -88,6 +97,7 @@
     private static final long DELAY_FEED_HEADER_IPH_MS = 50;
 
     protected final Activity mActivity;
+    private final JankTracker mJankTracker;
     private final SnackbarManager mSnackbarManager;
     @Nullable
     private final View mNtpHeader;
@@ -291,6 +301,8 @@
                     endScroll();
                     if (newState == RecyclerView.SCROLL_STATE_SETTLING) {
                         startFling();
+                    } else {
+                        finishJankTracking();
                     }
                     break;
                 }
@@ -298,6 +310,8 @@
                     endFling();
                     if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                         startScroll();
+                    } else {
+                        finishJankTracking();
                     }
                     break;
                 }
@@ -312,6 +326,11 @@
         @Override
         public void onScrolled(RecyclerView view, int dx, int dy) {}
 
+        private void finishJankTracking() {
+            mJankTracker.finishTrackingScenario(JankScenario.FEED_SCROLLING,
+                    TimeUtils.uptimeMillis() * TimeUtils.NANOSECONDS_PER_MILLISECOND);
+        }
+
         private void startScroll() {
             // TODO(nuskos): These next two are just a "hack" to get a nice track name
             // in the UI (it uses the first event it hits). Eventually with the Perfetto
@@ -319,6 +338,7 @@
             TraceEvent.startAsync("Feed.ScrollState", hashCode());
             TraceEvent.finishAsync("Feed.ScrollState", hashCode());
             TraceEvent.startAsync("Feed.TouchScrollStarted", hashCode());
+            mJankTracker.startTrackingScenario(JankScenario.FEED_SCROLLING);
         }
         private void endScroll() {
             TraceEvent.finishAsync("Feed.TouchScrollEnded", hashCode());
@@ -352,6 +372,7 @@
      * @param activity The containing {@link Activity}.
      * @param snackbarManager The {@link SnackbarManager} displaying Snackbar UI.
      * @param windowAndroid The window of the page.
+     * @param jankTracker tracks the jank during feed scrolling.
      * @param snapScrollHelper The {@link SnapScrollHelper} for the New Tab Page.
      * @param ntpHeader The extra header on top of the feeds for the New Tab Page.
      * @param toolbarHeight The height of the toolbar which overlaps Feed content at the top of the
@@ -376,9 +397,10 @@
      * @param tabModelSelector TabModelSelector used to get TabModels we can observe.
      */
     public FeedSurfaceCoordinator(Activity activity, SnackbarManager snackbarManager,
-            WindowAndroid windowAndroid, @Nullable SnapScrollHelper snapScrollHelper,
-            @Nullable View ntpHeader, @Px int toolbarHeight, boolean showDarkBackground,
-            FeedSurfaceDelegate delegate, Profile profile, boolean isPlaceholderShownInitially,
+            WindowAndroid windowAndroid, @Nullable JankTracker jankTracker,
+            @Nullable SnapScrollHelper snapScrollHelper, @Nullable View ntpHeader,
+            @Px int toolbarHeight, boolean showDarkBackground, FeedSurfaceDelegate delegate,
+            Profile profile, boolean isPlaceholderShownInitially,
             BottomSheetController bottomSheetController,
             Supplier<ShareDelegate> shareDelegateSupplier,
             @Nullable ScrollableContainerDelegate externalScrollableContainerDelegate,
@@ -398,6 +420,7 @@
         mBottomSheetController = bottomSheetController;
         mProfile = profile;
         mWindowAndroid = windowAndroid;
+        mJankTracker = jankTracker;
         mShareSupplier = shareDelegateSupplier;
         mScrollableContainerDelegate = externalScrollableContainerDelegate;
         mPrivacyPreferencesManager = privacyPreferencesManager;
@@ -757,6 +780,29 @@
         mMediator.setTabId(getTabIdFromLaunchOrigin(launchOrigin));
     }
 
+    /*
+     * Returns true if the primary signed-in account is subject to parental controls.
+     */
+    public boolean isPrimaryAccountSupervised() {
+        if (mProfile == null) {
+            return false;
+        }
+        final IdentityManager identityManager =
+                IdentityServicesProvider.get().getIdentityManager(mProfile);
+        final @Nullable CoreAccountInfo primaryAccount =
+                identityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN);
+
+        if (primaryAccount == null) {
+            return false;
+        }
+
+        final @Nullable AccountInfo primaryAccountInfo =
+                identityManager.findExtendedAccountInfoByEmailAddress(primaryAccount.getEmail());
+        return primaryAccountInfo != null
+                && primaryAccountInfo.getAccountCapabilities().isSubjectToParentalControls()
+                == Tribool.TRUE;
+    }
+
     /**
      * Gets the appropriate {@link StreamTabId} for the given {@link NewTabPageLaunchOrigin}.
      *
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
index 72f3ccf..0f6cd8b 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
@@ -485,8 +485,11 @@
 
         boolean suggestionsVisible = isSuggestionsVisible();
 
+        @StreamKind
+        int streamKind = mCoordinator.isPrimaryAccountSupervised() ? StreamKind.SUPERVISED_USER
+                                                                   : StreamKind.FOR_YOU;
         addHeaderAndStream(getInterestFeedHeaderText(suggestionsVisible),
-                mCoordinator.createFeedStream(StreamKind.FOR_YOU, new StreamsMediatorImpl()));
+                mCoordinator.createFeedStream(streamKind, new StreamsMediatorImpl()));
         setHeaderIndicatorState(suggestionsVisible);
 
         // Build menu after section enabled key is set.
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index f3d6d63..d07a3a5 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -174,6 +174,7 @@
     <dimen name="ntp_search_box_bottom_margin">1dp</dimen>
     <dimen name="ntp_search_box_start_margin">44dp</dimen>
     <dimen name="ntp_search_box_transition_length">16dp</dimen>
+    <dimen name="ntp_search_box_transition_length_polish_offset">4dp</dimen>
     <dimen name="ntp_search_box_lateral_margin_tablet_polish">100dp</dimen>
     <dimen name="snippets_article_header_height">40dp</dimen>
     <dimen name="snippets_article_header_menu_size">48dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index d1e10e4..8b94bbc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -45,6 +45,9 @@
 import org.chromium.base.MemoryPressureListener;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.TraceEvent;
+import org.chromium.base.jank_tracker.JankTracker;
+import org.chromium.base.jank_tracker.JankTrackerImpl;
+import org.chromium.base.jank_tracker.PlaceholderJankTracker;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
@@ -335,6 +338,9 @@
     // Use #shouldIgnoreIntent instead.
     private Boolean mShouldIgnoreIntent;
 
+    // Listens to FrameMetrics and records janks.
+    private JankTracker mJankTracker;
+
     // Supplier for a dependency to inform about the type of intent used to launch Chrome.
     private OneshotSupplierImpl<ToolbarIntentMetadata> mIntentMetadataOneshotSupplier =
             new OneshotSupplierImpl<>();
@@ -704,7 +710,7 @@
             CompositorViewHolder compositorViewHolder, ViewGroup tabSwitcherContainer) {
         StartSurfaceDelegate.createStartSurface(this, mRootUiCoordinator.getScrimCoordinator(),
                 mRootUiCoordinator.getBottomSheetController(), mStartSurfaceSupplier,
-                mStartSurfaceParentTabSupplier, hadWarmStart(), getWindowAndroid(),
+                mStartSurfaceParentTabSupplier, hadWarmStart(), getWindowAndroid(), mJankTracker,
                 tabSwitcherContainer, compositorViewHolder::getDynamicResourceLoader,
                 getTabModelSelector(), getBrowserControlsManager(), getSnackbarManager(),
                 getShareDelegateSupplier(), getToolbarManager()::getOmniboxStub,
@@ -1705,6 +1711,14 @@
     public void performPreInflationStartup() {
         super.performPreInflationStartup();
 
+        // Android FrameMetrics allow tracking of java views and their deadline misses (frame
+        // drops/janks).
+        if (ChromeFeatureList.sCollectAndroidFrameTimelineMetrics.isEnabled()) {
+            mJankTracker = new JankTrackerImpl(this);
+        } else {
+            mJankTracker = new PlaceholderJankTracker();
+        }
+
         // Decide whether to record startup UMA histograms. This is done  early in the main
         // Activity.onCreate() to avoid recording navigation delays when they require user input to
         // proceed. For example, FRE (First Run Experience) happens before the activity is created,
@@ -2012,8 +2026,9 @@
                     /* TabCreatorManager */ this, getTabModelSelectorSupplier(),
                     getCompositorViewHolderSupplier(), getModalDialogManagerSupplier(),
                     this::getSnackbarManager, getBrowserControlsManager(), getActivityTabProvider(),
-                    getLifecycleDispatcher(), getWindowAndroid(), getToolbarManager()::getToolbar,
-                    mHomeSurfaceTracker, getTabContentManagerSupplier());
+                    getLifecycleDispatcher(), getWindowAndroid(), mJankTracker,
+                    getToolbarManager()::getToolbar, mHomeSurfaceTracker,
+                    getTabContentManagerSupplier());
         }
         return mTabDelegateFactory;
     }
@@ -2796,6 +2811,11 @@
             mCallbackController = null;
         }
 
+        if (mJankTracker != null) {
+            mJankTracker.destroy();
+            mJankTracker = null;
+        }
+
         if (mTabModelSelectorTabObserver != null) {
             mTabModelSelectorTabObserver.destroy();
             mTabModelSelectorTabObserver = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java
index 9560470..f5c4bdb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java
@@ -8,6 +8,7 @@
 
 import androidx.annotation.Nullable;
 
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.app.tab_activity_glue.ActivityTabWebContentsDelegateAndroid;
@@ -69,6 +70,7 @@
     private final Supplier<Tab> mCurrentTabSupplier;
     private final ActivityLifecycleDispatcher mLifecycleDispatcher;
     private final WindowAndroid mWindowAndroid;
+    private final JankTracker mJankTracker;
     private final Supplier<Toolbar> mToolbarSupplier;
     private final HomeSurfaceTracker mHomeSurfaceTracker;
 
@@ -88,7 +90,8 @@
             Supplier<SnackbarManager> snackbarManagerSupplier,
             BrowserControlsManager browserControlsManager, Supplier<Tab> currentTabSupplier,
             ActivityLifecycleDispatcher lifecycleDispatcher, WindowAndroid windowAndroid,
-            Supplier<Toolbar> toolbarSupplier, @Nullable HomeSurfaceTracker homeSurfaceTracker,
+            JankTracker jankTracker, Supplier<Toolbar> toolbarSupplier,
+            @Nullable HomeSurfaceTracker homeSurfaceTracker,
             ObservableSupplier<TabContentManager> tabContentManagerSupplier) {
         mActivity = activity;
         mAppBrowserControlsVisibilityDelegate = appBrowserControlsVisibilityDelegate;
@@ -109,6 +112,7 @@
         mCurrentTabSupplier = currentTabSupplier;
         mLifecycleDispatcher = lifecycleDispatcher;
         mWindowAndroid = windowAndroid;
+        mJankTracker = jankTracker;
         mToolbarSupplier = toolbarSupplier;
         mHomeSurfaceTracker = homeSurfaceTracker;
         mTabContentManagerSupplier = tabContentManagerSupplier;
@@ -151,7 +155,7 @@
             mNativePageFactory = new NativePageFactory(mActivity, mBottomSheetController,
                     mBrowserControlsManager, mCurrentTabSupplier, mSnackbarManagerSupplier,
                     mLifecycleDispatcher, mTabModelSelectorSupplier.get(), mShareDelegateSupplier,
-                    mWindowAndroid, mToolbarSupplier, mHomeSurfaceTracker,
+                    mWindowAndroid, mJankTracker, mToolbarSupplier, mHomeSurfaceTracker,
                     mTabContentManagerSupplier);
         }
         return mNativePageFactory.createNativePage(url, candidatePage, tab);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java
index 0f2eed4..1a248067 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/settings/ChromeAccessibilitySettingsDelegate.java
@@ -43,6 +43,27 @@
         }
     }
 
+    private static class TextSizeContrastAccessibilityDelegate
+            implements IntegerPreferenceDelegate {
+        private final BrowserContextHandle mBrowserContextHandle;
+
+        public TextSizeContrastAccessibilityDelegate(BrowserContextHandle mBrowserContextHandle) {
+            this.mBrowserContextHandle = mBrowserContextHandle;
+        }
+
+        @Override
+        public int getValue() {
+            return UserPrefs.get(mBrowserContextHandle)
+                    .getInteger(Pref.ACCESSIBILITY_TEXT_SIZE_CONTRAST_FACTOR);
+        }
+
+        @Override
+        public void setValue(int value) {
+            UserPrefs.get(mBrowserContextHandle)
+                    .setInteger(Pref.ACCESSIBILITY_TEXT_SIZE_CONTRAST_FACTOR, value);
+        }
+    }
+
     private final Profile mProfile;
 
     /**
@@ -64,6 +85,11 @@
     }
 
     @Override
+    public IntegerPreferenceDelegate getTextSizeContrastAccessibilityDelegate() {
+        return new TextSizeContrastAccessibilityDelegate(getBrowserContextHandle());
+    }
+
+    @Override
     public void addExtraPreferences(PreferenceFragmentCompat fragment) {
         if (ImageDescriptionsController.getInstance().shouldShowImageDescriptionsMenuItem()) {
             fragment.addPreferencesFromResource(R.xml.image_descriptions_settings_preference);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
index e4e4254..12cb45ab 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -34,7 +34,6 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.recent_tabs.RestoreTabsFeatureHelper;
-import org.chromium.chrome.browser.tab.state.FilePersistedTabDataStorage;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementFieldTrial;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
 import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration;
@@ -87,7 +86,6 @@
                 BrandingController.USE_TEMPORARY_STORAGE,
                 BrandingController.ANIMATE_TOOLBAR_ICON_TRANSITION, ChimeFeatures.ALWAYS_REGISTER,
                 FeedPlaceholderLayout.ENABLE_INSTANT_START_ANIMATION,
-                FilePersistedTabDataStorage.DELAY_SAVES_UNTIL_DEFERRED_STARTUP_PARAM,
                 OptimizationGuidePushNotificationManager.MAX_CACHE_SIZE,
                 OmniboxFeatures.ENABLE_MODERNIZE_VISUAL_UPDATE_ON_TABLET,
                 OmniboxFeatures.MODERNIZE_VISUAL_UPDATE_ACTIVE_COLOR_ON_OMNIBOX,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java
index e45de08..9c52b33 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java
@@ -14,7 +14,6 @@
 import org.chromium.chrome.browser.auxiliary_search.AuxiliarySearchGroupProto.AuxiliarySearchTabGroup;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tabmodel.TabList;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.url.GURL;
@@ -105,7 +104,7 @@
 
         var tabBuilder = AuxiliarySearchEntry.newBuilder().setTitle(title).setUrl(url.getSpec());
         final long lastAccessTime = tab.getTimestampMillis();
-        if (lastAccessTime != CriticalPersistedTabData.INVALID_TIMESTAMP) {
+        if (lastAccessTime != Tab.INVALID_TIMESTAMP) {
             tabBuilder.setLastAccessTimestamp(lastAccessTime);
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
index f17b9bd..b943aca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -19,7 +19,6 @@
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
-import android.util.DisplayMetrics;
 import android.util.FloatProperty;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
@@ -28,13 +27,10 @@
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ArrayAdapter;
 import android.widget.ListPopupWindow;
-import android.widget.TextView;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 import androidx.annotation.VisibleForTesting;
-import androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams;
-import androidx.core.view.ViewCompat;
 
 import org.chromium.base.MathUtils;
 import org.chromium.base.metrics.RecordHistogram;
@@ -67,7 +63,6 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabUiThemeUtil;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.styles.SemanticColorUtils;
-import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.interpolators.Interpolators;
 import org.chromium.ui.util.ColorUtils;
@@ -289,7 +284,7 @@
     private StripLayoutTab mLastHoveredTab;
     private TabDropTarget mTabDropTarget;
 
-    private View mTabHoverCardView;
+    private StripTabHoverCardView mTabHoverCardView;
 
     /**
      * Creates an instance of the {@link StripLayoutHelper}.
@@ -457,6 +452,10 @@
     public void destroy() {
         mStripTabEventHandler.removeCallbacksAndMessages(null);
         mTabDropTarget = null;
+        if (mTabHoverCardView != null) {
+            mTabHoverCardView.destroy();
+            mTabHoverCardView = null;
+        }
     }
 
     /**
@@ -1506,11 +1505,11 @@
     }
 
     @VisibleForTesting
-    void setTabHoverCardView(View tabHoverCardView) {
+    void setTabHoverCardView(StripTabHoverCardView tabHoverCardView) {
         mTabHoverCardView = tabHoverCardView;
     }
 
-    View getTabHoverCardViewForTesting() {
+    StripTabHoverCardView getTabHoverCardViewForTesting() {
         return mTabHoverCardView;
     }
 
@@ -1527,7 +1526,7 @@
         assert mTabHoverCardView != null : "Hover card view should not be null.";
         // Remove the highlight from the last hovered tab.
         updateHoveredFolioTabState(mLastHoveredTab, false);
-        mTabHoverCardView.setVisibility(View.GONE);
+        mTabHoverCardView.hide();
         mLastHoveredTab = null;
     }
 
@@ -1541,116 +1540,9 @@
         updateHoveredFolioTabState(mLastHoveredTab, true);
 
         // Show the tab hover card.
-        // TODO(crbug.com/1485258): Create a TabHoverCardView class to manage view logic.
         int hoveredTabIndex = findIndexForTab(mLastHoveredTab.getId());
-        Tab tab = mModel.getTabAt(hoveredTabIndex);
-        if (tab == null) return;
-        var titleView = (TextView) mTabHoverCardView.findViewById(R.id.title);
-        var urlView = (TextView) mTabHoverCardView.findViewById(R.id.url);
-        titleView.setText(tab.getTitle());
-        String url = tab.getUrl().getHost();
-        // If the URL is a Chrome scheme, display the GURL spec instead of the host. For e.g., use
-        // chrome://newtab instead of just newtab on the hover card.
-        if (UrlUtilities.isInternalScheme(tab.getUrl())) {
-            url = tab.getUrl().getSpec();
-            // GURL#getSpec() returns a string with a trailing "/", remove this.
-            url = url.replaceFirst("/$", "");
-        }
-        urlView.setText(url);
-
-        float[] position = getHoverCardPosition(hoveredTab, hoveredTabIndex == mModel.index());
-        mTabHoverCardView.setX(position[0]);
-        mTabHoverCardView.setY(position[1]);
-
-        mTabHoverCardView.setVisibility(View.VISIBLE);
-    }
-
-    /**
-     * Update the hover card background and text colors based on the theme and incognito mode.
-     */
-    public void updateHoverCardColors() {
-        if (!isPeripheralsSupportForTabStripEnabled()) return;
-        if (mTabHoverCardView == null) return;
-
-        var titleView = (TextView) mTabHoverCardView.findViewById(R.id.title);
-        var urlView = (TextView) mTabHoverCardView.findViewById(R.id.url);
-        titleView.setTextColor(
-                TabUiThemeProvider.getStripTabHoverCardTextColorPrimary(mContext, mIncognito));
-        urlView.setTextColor(
-                TabUiThemeProvider.getStripTabHoverCardTextColorSecondary(mContext, mIncognito));
-
-        ViewCompat.setBackgroundTintList(mTabHoverCardView,
-                TabUiThemeProvider.getStripTabHoverCardBackgroundTintList(mContext, mIncognito));
-    }
-
-    /**
-     * Get the x and y coordinates of the position of the hover card, in px.
-     *
-     * @param hoveredTab The {@link StripLayoutTab} that is hovered on.
-     * @param isSelectedTab Whether the tab is the selected tab, {@code true} if the hovered tab is
-     *         also the selected tab, {@code false} otherwise.
-     * @return A float array specifying the x (array[0]) and y (array[1]) coordinates of the
-     *         position of the hover card, in px.
-     */
-    @VisibleForTesting
-    float[] getHoverCardPosition(StripLayoutTab hoveredTab, boolean isSelectedTab) {
-        boolean isFolioEnabled = TabManagementFieldTrial.isTabStripFolioEnabled();
-        boolean isDetachedEnabled = TabManagementFieldTrial.isTabStripDetachedEnabled();
-
-        // 1. Determine the window width.
-        DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
-        float displayDensity = displayMetrics.density;
-        float windowWidthPx = displayMetrics.widthPixels;
-        float windowWidthDp = windowWidthPx / displayDensity;
-
-        // 2. Determine the hover card width, making adjustments relative to the window width if
-        // applicable.
-        float hoverCardWidthPx = mContext.getResources().getDimension(R.dimen.tab_hover_card_width);
-        // Hover card width should be a maximum of 90% of the window width.
-        hoverCardWidthPx = Math.min(hoverCardWidthPx, HOVER_CARD_MAX_WIDTH_PERCENT * windowWidthPx);
-        float hoverCardWidthDp = hoverCardWidthPx / displayDensity;
-        // Update the card LayoutParams if an adjustment on the original width is required.
-        if (hoverCardWidthPx
-                != mContext.getResources().getDimension(R.dimen.tab_hover_card_width)) {
-            var layoutParams = mTabHoverCardView.getLayoutParams();
-            mTabHoverCardView.setLayoutParams(
-                    new LayoutParams(Math.round(hoverCardWidthPx), layoutParams.height));
-        }
-
-        // 3. Determine the horizontal position of the hover card.
-        float hoverCardXDp = LocalizationUtils.isLayoutRtl()
-                ? (hoveredTab.getDrawX() - (hoverCardWidthDp - hoveredTab.getWidth()))
-                : hoveredTab.getDrawX();
-        // Adjust the TSR detached and inactive folio tab hover card to align with the tab container
-        // edge.
-        if (isDetachedEnabled || (isFolioEnabled && !isSelectedTab)) {
-            hoverCardXDp +=
-                    MathUtils.flipSignIf(mContext.getResources().getDimension(
-                                                 R.dimen.tsr_no_feet_tab_hover_card_x_offset)
-                                    / displayDensity,
-                            LocalizationUtils.isLayoutRtl());
-        }
-
-        float windowHorizontalMarginDp = mContext.getResources().getDimension(
-                                                 R.dimen.tab_hover_card_window_horizontal_margin)
-                / displayDensity;
-        // Align the hover card at a minimum horizontal margin of 8dp from the window left edge.
-        if (hoverCardXDp < windowHorizontalMarginDp) {
-            hoverCardXDp = windowHorizontalMarginDp;
-        }
-        // Align the hover card at a minimum horizontal margin of 8dp from the window right edge.
-        if (hoverCardXDp + hoverCardWidthDp > windowWidthDp - windowHorizontalMarginDp) {
-            hoverCardXDp = windowWidthDp - hoverCardWidthDp - windowHorizontalMarginDp;
-        }
-
-        // 4. Determine the vertical position of the hover card.
-        float hoverCardYDp = mHeight;
-        // Adjust the TSR detached tab hover card to be at a fixed distance from the tab container.
-        if (isDetachedEnabled) {
-            hoverCardYDp += FOLIO_DETACHED_BOTTOM_MARGIN_DP;
-        }
-
-        return new float[] {hoverCardXDp * displayDensity, hoverCardYDp * displayDensity};
+        mTabHoverCardView.show(mModel.getTabAt(hoveredTabIndex), mLastHoveredTab,
+                hoveredTabIndex == mModel.index(), mHeight);
     }
 
     private void updateHoveredFolioTabState(StripLayoutTab tab, boolean hovered) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
index fe7a6ac..55db864 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -21,6 +21,8 @@
 
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.base.task.PostTask;
+import org.chromium.base.task.TaskTraits;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.LayerTitleCache;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerHost;
@@ -116,6 +118,8 @@
     static final float FADE_MEDIUM_TSR_WIDTH_DP = 72;
     static final float FADE_LONG_TSR_WIDTH_DP = 136;
 
+    private static final int HOVER_EXIT_ON_DOWN_DELAY_MS = 150;
+
     // Caching Variables
     private final RectF mStripFilterArea = new RectF();
 
@@ -173,8 +177,12 @@
     private class TabStripEventHandler implements MotionEventHandler {
         @Override
         public void onDown(float x, float y, boolean fromMouse, int buttons) {
-            // Clear any persisting tab strip hover state on a down event on the strip.
-            getActiveStripLayoutHelper().onHoverExit();
+            // Clear any persisting tab strip hover state on a down event on the strip. Clearance is
+            // posted at a delay, as a best effort for the clearance to take effect after any
+            // animations triggered by the down event have ended.
+            // TODO (crbug.com/1483487): Monitor correctness of delay duration.
+            PostTask.postDelayedTask(
+                    TaskTraits.UI_DEFAULT, this::onHoverExit, HOVER_EXIT_ON_DOWN_DELAY_MS);
             if (mModelSelectorButton.onDown(x, y)) return;
             getActiveStripLayoutHelper().onDown(time(), x, y, fromMouse, buttons);
         }
@@ -400,9 +408,10 @@
                 mModelSelectorButton, multiInstanceManager, toolbarContainerView);
 
         tabHoverCardViewStub.setOnInflateListener((viewStub, view) -> {
-            mNormalHelper.setTabHoverCardView(view);
-            mIncognitoHelper.setTabHoverCardView(view);
-            getActiveStripLayoutHelper().updateHoverCardColors();
+            var hoverCardView = (StripTabHoverCardView) view;
+            hoverCardView.initialize(mTabModelSelector);
+            mNormalHelper.setTabHoverCardView(hoverCardView);
+            mIncognitoHelper.setTabHoverCardView(hoverCardView);
         });
 
         if (tabModelStartupInfoSupplier != null) {
@@ -899,11 +908,6 @@
         mNormalHelper.tabModelSelected(!mIsIncognito);
 
         updateModelSwitcherButton();
-        // Update the tab hover card background and text colors for the active tab model when it is
-        // selected (provided that the hover card view that is shared across the tab models is
-        // already inflated), since the colors will be the same for a given tab model, but different
-        // across tab models.
-        getActiveStripLayoutHelper().updateHoverCardColors();
 
         mUpdateHost.requestUpdate();
     }
@@ -952,6 +956,10 @@
         }
     }
 
+    void simulateOnDownForTesting(float x, float y, boolean fromMouse, int buttons) {
+        mTabStripEventHandler.onDown(x, y, fromMouse, buttons);
+    }
+
     void setTabStripTreeProviderForTesting(TabStripSceneLayer tabStripTreeProvider) {
         mTabStripTreeProvider = tabStripTreeProvider;
     }
@@ -959,8 +967,4 @@
     ViewStub getTabHoverCardViewStubForTesting() {
         return mTabHoverCardViewStub;
     }
-
-    TabModelSelectorObserver getTabModelSelectorObserverForTesting() {
-        return mTabModelSelectorObserver;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripTabHoverCardView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripTabHoverCardView.java
new file mode 100644
index 0000000..102463a
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripTabHoverCardView.java
@@ -0,0 +1,217 @@
+// Copyright 2023 The Chromium Authors
+// 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.compositor.overlays.strip;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.view.ViewCompat;
+
+import org.chromium.base.MathUtils;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
+import org.chromium.chrome.browser.tasks.tab_management.TabManagementFieldTrial;
+import org.chromium.chrome.browser.tasks.tab_management.TabUiThemeProvider;
+import org.chromium.components.embedder_support.util.UrlUtilities;
+import org.chromium.ui.base.LocalizationUtils;
+
+public class StripTabHoverCardView extends LinearLayout {
+    // The max width of the tab hover card in terms of the enclosing window width percent.
+    static final float HOVER_CARD_MAX_WIDTH_PERCENT = 0.9f;
+
+    private TextView mTitleView;
+    private TextView mUrlView;
+    private TabModelSelector mTabModelSelector;
+    private TabModelSelectorObserver mTabModelSelectorObserver;
+
+    public StripTabHoverCardView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public StripTabHoverCardView(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTitleView = findViewById(R.id.title);
+        mUrlView = findViewById(R.id.url);
+    }
+
+    /**
+     * Show the strip tab hover card.
+     * @param hoveredTab The {@link Tab} instance of the hovered tab.
+     * @param hoveredStripLayoutTab The {@link StripLayoutTab} instance of the hovered tab.
+     * @param isSelectedTab Whether the hovered tab is selected, {@code true} if the hovered tab is
+     *         also the selected tab, {@code false} otherwise.
+     * @param height The height of the tab strip stack.
+     */
+    public void show(Tab hoveredTab, StripLayoutTab hoveredStripLayoutTab, boolean isSelectedTab,
+            float height) {
+        if (hoveredTab == null) return;
+        mTitleView.setText(hoveredTab.getTitle());
+        String url = hoveredTab.getUrl().getHost();
+        // If the URL is a Chrome scheme, display the GURL spec instead of the host. For e.g., use
+        // chrome://newtab instead of just newtab on the hover card.
+        if (UrlUtilities.isInternalScheme(hoveredTab.getUrl())) {
+            url = hoveredTab.getUrl().getSpec();
+            // GURL#getSpec() returns a string with a trailing "/", remove this.
+            url = url.replaceFirst("/$", "");
+        }
+        mUrlView.setText(url);
+
+        float[] position = getHoverCardPosition(hoveredStripLayoutTab, isSelectedTab, height);
+        setX(position[0]);
+        setY(position[1]);
+
+        setVisibility(VISIBLE);
+    }
+
+    /**
+     * Hide the strip tab hover card.
+     */
+    public void hide() {
+        setVisibility(GONE);
+    }
+
+    /**
+     * Perform tasks after the view is inflated: update the hover card colors, and add a {@link
+     * TabModelSelectorObserver} to update the view when a tab model is selected.
+     * @param tabModelSelector The {@link TabModelSelector} to observe.
+     */
+    public void initialize(TabModelSelector tabModelSelector) {
+        mTabModelSelector = tabModelSelector;
+        mTabModelSelectorObserver = new TabModelSelectorObserver() {
+            @Override
+            public void onTabModelSelected(TabModel newModel, TabModel oldModel) {
+                updateHoverCardColors(newModel.isIncognito());
+            }
+        };
+        mTabModelSelector.addObserver(mTabModelSelectorObserver);
+        updateHoverCardColors(mTabModelSelector.isIncognitoSelected());
+    }
+
+    /**
+     * Update the hover card background and text colors based on the theme and incognito mode.
+     * @param incognito Whether the incognito mode is selected, {@code true} for incognito, {@link
+     *         false} otherwise.
+     */
+    public void updateHoverCardColors(boolean incognito) {
+        if (!ChromeFeatureList.isEnabled(
+                    ChromeFeatureList.ADVANCED_PERIPHERALS_SUPPORT_TAB_STRIP)) {
+            return;
+        }
+
+        mTitleView.setTextColor(
+                TabUiThemeProvider.getStripTabHoverCardTextColorPrimary(getContext(), incognito));
+        mUrlView.setTextColor(
+                TabUiThemeProvider.getStripTabHoverCardTextColorSecondary(getContext(), incognito));
+
+        ViewCompat.setBackgroundTintList(this,
+                TabUiThemeProvider.getStripTabHoverCardBackgroundTintList(getContext(), incognito));
+    }
+
+    public void destroy() {
+        if (mTabModelSelector != null) {
+            mTabModelSelector.removeObserver(mTabModelSelectorObserver);
+            mTabModelSelector = null;
+        }
+    }
+
+    /**
+     * Get the x and y coordinates of the position of the hover card, in px.
+     *
+     * @param hoveredTab The {@link StripLayoutTab} that is hovered on.
+     * @param isSelectedTab Whether the tab is the selected tab, {@code true} if the hovered tab is
+     *         also the selected tab, {@code false} otherwise.
+     * @param height The height of the strip stack, to determine the y position of the card.
+     * @return A float array specifying the x (array[0]) and y (array[1]) coordinates of the
+     *         position of the hover card, in px.
+     */
+    float[] getHoverCardPosition(StripLayoutTab hoveredTab, boolean isSelectedTab, float height) {
+        boolean isFolioEnabled = TabManagementFieldTrial.isTabStripFolioEnabled();
+        boolean isDetachedEnabled = TabManagementFieldTrial.isTabStripDetachedEnabled();
+
+        // 1. Determine the window width.
+        DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
+        float displayDensity = displayMetrics.density;
+        float windowWidthPx = displayMetrics.widthPixels;
+        float windowWidthDp = windowWidthPx / displayDensity;
+
+        // 2. Determine the hover card width, making adjustments relative to the window width if
+        // applicable.
+        float hoverCardWidthPx = getContext().getResources().getDimension(
+                org.chromium.chrome.R.dimen.tab_hover_card_width);
+        // Hover card width should be a maximum of 90% of the window width.
+        hoverCardWidthPx = Math.min(hoverCardWidthPx, HOVER_CARD_MAX_WIDTH_PERCENT * windowWidthPx);
+        float hoverCardWidthDp = hoverCardWidthPx / displayDensity;
+        // Update the card LayoutParams if an adjustment on the original width is required.
+        if (hoverCardWidthPx
+                != getContext().getResources().getDimension(
+                        org.chromium.chrome.R.dimen.tab_hover_card_width)) {
+            var layoutParams = getLayoutParams();
+            setLayoutParams(new CoordinatorLayout.LayoutParams(
+                    Math.round(hoverCardWidthPx), layoutParams.height));
+        }
+
+        // 3. Determine the horizontal position of the hover card.
+        float hoverCardXDp = LocalizationUtils.isLayoutRtl()
+                ? (hoveredTab.getDrawX() - (hoverCardWidthDp - hoveredTab.getWidth()))
+                : hoveredTab.getDrawX();
+        // Adjust the TSR detached and inactive folio tab hover card to align with the tab container
+        // edge.
+        if (isDetachedEnabled || (isFolioEnabled && !isSelectedTab)) {
+            hoverCardXDp += MathUtils.flipSignIf(
+                    getContext().getResources().getDimension(
+                            org.chromium.chrome.R.dimen.tsr_no_feet_tab_hover_card_x_offset)
+                            / displayDensity,
+                    LocalizationUtils.isLayoutRtl());
+        }
+
+        float windowHorizontalMarginDp =
+                getContext().getResources().getDimension(
+                        org.chromium.chrome.R.dimen.tab_hover_card_window_horizontal_margin)
+                / displayDensity;
+        // Align the hover card at a minimum horizontal margin of 8dp from the window left edge.
+        if (hoverCardXDp < windowHorizontalMarginDp) {
+            hoverCardXDp = windowHorizontalMarginDp;
+        }
+        // Align the hover card at a minimum horizontal margin of 8dp from the window right edge.
+        if (hoverCardXDp + hoverCardWidthDp > windowWidthDp - windowHorizontalMarginDp) {
+            hoverCardXDp = windowWidthDp - hoverCardWidthDp - windowHorizontalMarginDp;
+        }
+
+        // 4. Determine the vertical position of the hover card.
+        float hoverCardYDp = height;
+        // Adjust the TSR detached tab hover card to be at a fixed distance from the tab container.
+        if (isDetachedEnabled) {
+            hoverCardYDp += StripLayoutHelper.FOLIO_DETACHED_BOTTOM_MARGIN_DP;
+        }
+
+        return new float[] {hoverCardXDp * displayDensity, hoverCardYDp * displayDensity};
+    }
+
+    void setTitleViewForTesting(TextView titleView) {
+        mTitleView = titleView;
+    }
+
+    void setUrlViewForTesting(TextView urlView) {
+        mUrlView = urlView;
+    }
+
+    TabModelSelectorObserver getTabModelSelectorObserverForTesting() {
+        return mTabModelSelectorObserver;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
index 0149bc40..d1098a1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
@@ -12,6 +12,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.DestroyableObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
@@ -61,6 +62,7 @@
     private final TabModelSelector mTabModelSelector;
     private final Supplier<ShareDelegate> mShareDelegateSupplier;
     private final WindowAndroid mWindowAndroid;
+    private final JankTracker mJankTracker;
     private final Supplier<Toolbar> mToolbarSupplier;
     private final HomeSurfaceTracker mHomeSurfaceTracker;
     private final ObservableSupplier<TabContentManager> mTabContentManagerSupplier;
@@ -76,7 +78,8 @@
             @NonNull ActivityLifecycleDispatcher lifecycleDispatcher,
             @NonNull TabModelSelector tabModelSelector,
             @NonNull Supplier<ShareDelegate> shareDelegateSupplier,
-            @NonNull WindowAndroid windowAndroid, @NonNull Supplier<Toolbar> toolbarSupplier,
+            @NonNull WindowAndroid windowAndroid, @NonNull JankTracker jankTracker,
+            @NonNull Supplier<Toolbar> toolbarSupplier,
             @Nullable HomeSurfaceTracker homeSurfaceTracker,
             @Nullable ObservableSupplier<TabContentManager> tabContentManagerSupplier) {
         mActivity = activity;
@@ -88,6 +91,7 @@
         mTabModelSelector = tabModelSelector;
         mShareDelegateSupplier = shareDelegateSupplier;
         mWindowAndroid = windowAndroid;
+        mJankTracker = jankTracker;
         mToolbarSupplier = toolbarSupplier;
         mHomeSurfaceTracker = homeSurfaceTracker;
         mTabContentManagerSupplier = tabContentManagerSupplier;
@@ -98,8 +102,8 @@
             mNativePageBuilder = new NativePageBuilder(mActivity, this::getNewTabPageUma,
                     mBottomSheetController, mBrowserControlsManager, mCurrentTabSupplier,
                     mSnackbarManagerSupplier, mLifecycleDispatcher, mTabModelSelector,
-                    mShareDelegateSupplier, mWindowAndroid, mToolbarSupplier, mHomeSurfaceTracker,
-                    mTabContentManagerSupplier);
+                    mShareDelegateSupplier, mWindowAndroid, mJankTracker, mToolbarSupplier,
+                    mHomeSurfaceTracker, mTabContentManagerSupplier);
         }
         return mNativePageBuilder;
     }
@@ -124,6 +128,7 @@
         private final TabModelSelector mTabModelSelector;
         private final Supplier<ShareDelegate> mShareDelegateSupplier;
         private final WindowAndroid mWindowAndroid;
+        private final JankTracker mJankTracker;
         private final Supplier<Toolbar> mToolbarSupplier;
         private final HomeSurfaceTracker mHomeSurfaceTracker;
         private final ObservableSupplier<TabContentManager> mTabContentManagerSupplier;
@@ -134,7 +139,8 @@
                 Supplier<SnackbarManager> snackbarManagerSupplier,
                 ActivityLifecycleDispatcher lifecycleDispatcher, TabModelSelector tabModelSelector,
                 Supplier<ShareDelegate> shareDelegateSupplier, WindowAndroid windowAndroid,
-                Supplier<Toolbar> toolbarSupplier, HomeSurfaceTracker homeSurfaceTracker,
+                JankTracker jankTracker, Supplier<Toolbar> toolbarSupplier,
+                HomeSurfaceTracker homeSurfaceTracker,
                 ObservableSupplier<TabContentManager> tabContentManagerSupplier) {
             mActivity = activity;
             mUma = uma;
@@ -146,6 +152,7 @@
             mTabModelSelector = tabModelSelector;
             mShareDelegateSupplier = shareDelegateSupplier;
             mWindowAndroid = windowAndroid;
+            mJankTracker = jankTracker;
             mToolbarSupplier = toolbarSupplier;
             mHomeSurfaceTracker = homeSurfaceTracker;
             mTabContentManagerSupplier = tabContentManagerSupplier;
@@ -160,7 +167,7 @@
                     mSnackbarManagerSupplier.get(), mLifecycleDispatcher, mTabModelSelector,
                     DeviceFormFactor.isWindowOnTablet(mWindowAndroid), mUma.get(),
                     ColorUtils.inNightMode(mActivity), nativePageHost, tab, url,
-                    mBottomSheetController, mShareDelegateSupplier, mWindowAndroid,
+                    mBottomSheetController, mShareDelegateSupplier, mWindowAndroid, mJankTracker,
                     mToolbarSupplier, new SettingsLauncherImpl(), mHomeSurfaceTracker,
                     mTabContentManagerSupplier);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
index be7b9c7..1d93fcd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -29,6 +29,8 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.TimeUtils;
 import org.chromium.base.TraceEvent;
+import org.chromium.base.jank_tracker.JankScenario;
+import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
@@ -129,6 +131,7 @@
     private final ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
 
     private final String mTitle;
+    private final JankTracker mJankTracker;
     private Context mContext;
     private int mBackgroundColor;
     protected final NewTabPageManagerImpl mNewTabPageManager;
@@ -346,6 +349,7 @@
      * @param bottomSheetController The controller for bottom sheets, used by the feed.
      * @param shareDelegateSupplier Supplies the Delegate used to open SharingHub.
      * @param windowAndroid The containing window of this page.
+     * @param jankTracker {@link JankTracker} object to measure jankiness while NTP is visible.
      * @param toolbarSupplier Supplies the {@link Toolbar}.
      * @param settingsLauncher {@link SettingsLauncher} object to launch settings fragments.
      */
@@ -356,8 +360,8 @@
             NativePageHost nativePageHost, Tab tab, String url,
             BottomSheetController bottomSheetController,
             Supplier<ShareDelegate> shareDelegateSupplier, WindowAndroid windowAndroid,
-            Supplier<Toolbar> toolbarSupplier, SettingsLauncher settingsLauncher,
-            HomeSurfaceTracker homeSurfaceTracker,
+            JankTracker jankTracker, Supplier<Toolbar> toolbarSupplier,
+            SettingsLauncher settingsLauncher, HomeSurfaceTracker homeSurfaceTracker,
             ObservableSupplier<TabContentManager> tabContentManagerSupplier) {
         mConstructedTimeNs = System.nanoTime();
         TraceEvent.begin(TAG);
@@ -367,6 +371,7 @@
         mActivityLifecycleDispatcher = lifecycleDispatcher;
         mTab = tab;
         mNewTabPageUma = uma;
+        mJankTracker = jankTracker;
         mToolbarSupplier = toolbarSupplier;
         mMostVisitedTileClickObservers = new ObserverList<>();
         mBrowserControlsStateProvider = browserControlsStateProvider;
@@ -422,6 +427,19 @@
             }
 
             @Override
+            public void onInteractabilityChanged(Tab tab, boolean isInteractable) {
+                // We start/stop tracking based on InteractabilityChanged in addition to
+                // Shown/Hidden because those events don't trigger for switching to tab switcher, we
+                // don't rely solely on this event because it doeesn't trigger when the user
+                // navigates to a website.
+                if (isInteractable) {
+                    mJankTracker.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
+                } else {
+                    mJankTracker.finishTrackingScenario(JankScenario.NEW_TAB_PAGE);
+                }
+            }
+
+            @Override
             public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) {
                 mNewTabPageLayout.onLoadUrl(UrlUtilities.isNTPUrl(tab.getUrl()));
             }
@@ -536,7 +554,7 @@
         };
 
         FeedSurfaceCoordinator feedSurfaceCoordinator = new FeedSurfaceCoordinator(activity,
-                snackbarManager, windowAndroid,
+                snackbarManager, windowAndroid, mJankTracker,
                 new SnapScrollHelperImpl(mNewTabPageManager, mNewTabPageLayout), mNewTabPageLayout,
                 mBrowserControlsStateProvider.getTopControlsHeight(), isInNightMode, this, profile,
                 /* isPlaceholderShownInitially= */ false, mBottomSheetController,
@@ -805,6 +823,7 @@
     private void recordNTPShown() {
         mLastShownTimeNs = System.nanoTime();
         RecordUserAction.record("MobileNTPShown");
+        mJankTracker.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
         SuggestionsMetrics.recordSurfaceVisible();
 
         FeatureNotificationUtils.registerIPHCallback(FeatureType.VOICE_SEARCH,
@@ -813,6 +832,7 @@
 
     /** Records UMA for the NTP being hidden and the time spent on it. */
     private void recordNTPHidden() {
+        mJankTracker.finishTrackingScenario(JankScenario.NEW_TAB_PAGE);
         RecordHistogram.recordMediumTimesHistogram("NewTabPage.TimeSpent",
                 (System.nanoTime() - mLastShownTimeNs) / TimeUtils.NANOSECONDS_PER_MILLISECOND);
         SuggestionsMetrics.recordSurfaceHidden();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
index 7fe029e..50e878c3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -153,6 +153,9 @@
     private Boolean mIsMvtAllFilledPortrait;
     private final int mTileViewIntervalPaddingTabletForPolish;
     private final int mTileViewEdgePaddingTabletForPolish;
+    // This offset is added to the transition length when the surface polish flag is enabled in
+    // order to make sure the animation is completed.
+    private float mTransitionLengthOffset;
 
     /**
      * Constructor for inflating from XML.
@@ -236,6 +239,11 @@
             mSearchBoxBoundsVerticalInset = getResources().getDimensionPixelSize(
                     R.dimen.ntp_search_box_bounds_vertical_inset_modern);
         }
+        mTransitionLengthOffset = mIsSurfacePolishEnabled
+                        && !DeviceFormFactor.isNonMultiDisplayContextOnTablet(activity)
+                ? getResources().getDimensionPixelSize(
+                        R.dimen.ntp_search_box_transition_length_polish_offset)
+                : 0;
 
         if (mIsNtpAsHomeSurfaceEnabled && !mIsSurfacePolishEnabled) {
             // We add extra side margins to the fake search box when multiple column Feeds are
@@ -476,15 +484,17 @@
         final int scrollY = mScrollDelegate.getVerticalScrollOffset();
         // Use int pixel size instead of float dimension to avoid precision error on the percentage.
         final float transitionLength =
-                getResources().getDimensionPixelSize(R.dimen.ntp_search_box_transition_length);
+                getResources().getDimensionPixelSize(R.dimen.ntp_search_box_transition_length)
+                + mTransitionLengthOffset;
         // Tab strip height is zero on phones, nonzero on tablets.
         int tabStripHeight = getResources().getDimensionPixelSize(R.dimen.tab_strip_height);
 
         // |scrollY - searchBoxTop + tabStripHeight| gives the distance the search bar is from the
         // top of the tab.
-        return MathUtils.clamp(
-                (scrollY - searchBoxTop + tabStripHeight + transitionLength) / transitionLength, 0f,
-                1f);
+        return MathUtils.clamp((scrollY - (searchBoxTop + mTransitionLengthOffset) + tabStripHeight
+                                       + transitionLength)
+                        / transitionLength,
+                0f, 1f);
     }
 
     private void insertSiteSectionView() {
@@ -843,7 +853,8 @@
      */
     private boolean isSearchBoxOffscreen() {
         return !mScrollDelegate.isChildVisibleAtPosition(0)
-                || mScrollDelegate.getVerticalScrollOffset() > getSearchBoxView().getTop();
+                || mScrollDelegate.getVerticalScrollOffset()
+                > getSearchBoxView().getTop() + mTransitionLengthOffset;
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java
index 0d9c21ad..d902c63 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java
@@ -14,6 +14,7 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.feed.SnapScrollHelper;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 
 /**
  * This class handles snap scroll for the search box on a {@link NewTabPage}.
@@ -27,6 +28,7 @@
     private final Runnable mUpdateSearchBoxOnScrollRunnable;
     private final int mToolbarHeight;
     private final int mSearchBoxTransitionLength;
+    private final int mSearchBoxTransitionLengthOffset;
 
     private View mView;
     private boolean mPendingSnapScroll;
@@ -48,6 +50,9 @@
                 + res.getDimensionPixelSize(R.dimen.toolbar_progress_bar_height);
         mSearchBoxTransitionLength =
                 res.getDimensionPixelSize(R.dimen.ntp_search_box_transition_length);
+        mSearchBoxTransitionLengthOffset = ChromeFeatureList.sSurfacePolish.isEnabled()
+                ? res.getDimensionPixelSize(R.dimen.ntp_search_box_transition_length_polish_offset)
+                : 0;
     }
 
     /** @param view The view on which this class needs to handle snap scroll. */
@@ -120,7 +125,8 @@
             View fakeBox = mNewTabPageLayout.getSearchBoxView();
             int fakeBoxUpperBound = fakeBox.getTop() + fakeBox.getPaddingTop();
             scrollPosition = calculateSnapPositionForRegion(scrollPosition,
-                    fakeBoxUpperBound - mSearchBoxTransitionLength, fakeBoxUpperBound);
+                    fakeBoxUpperBound - mSearchBoxTransitionLength,
+                    fakeBoxUpperBound + mSearchBoxTransitionLengthOffset);
         }
 
         return scrollPosition;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
index aae0554..2bc58ae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
@@ -63,6 +63,7 @@
 import org.chromium.chrome.browser.password_manager.settings.PasswordSettings;
 import org.chromium.chrome.browser.privacy_guide.PrivacyGuideFragment;
 import org.chromium.chrome.browser.privacy_sandbox.AdMeasurementFragment;
+import org.chromium.chrome.browser.privacy_sandbox.ChromeTrackingProtectionDelegate;
 import org.chromium.chrome.browser.privacy_sandbox.PrivacySandboxSettingsBaseFragment;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileManagerUtils;
@@ -93,6 +94,7 @@
 import org.chromium.components.browser_ui.widget.displaystyle.ViewResizer;
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
+import org.chromium.components.privacy_sandbox.TrackingProtectionSettings;
 import org.chromium.ui.KeyboardVisibilityDelegate;
 import org.chromium.ui.UiUtils;
 import org.chromium.ui.base.ActivityWindowAndroid;
@@ -604,6 +606,10 @@
         if (fragment instanceof AutofillOptionsFragment) {
             AutofillOptionsCoordinator.createFor((AutofillOptionsFragment) fragment);
         }
+        if (fragment instanceof TrackingProtectionSettings) {
+            ((TrackingProtectionSettings) fragment)
+                    .setTrackingProtectionDelegate(new ChromeTrackingProtectionDelegate(mProfile));
+        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
index 338d5a3..aedab87 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -29,7 +29,6 @@
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityUtils;
@@ -50,7 +49,6 @@
 import org.chromium.chrome.browser.rlz.RevenueStats;
 import org.chromium.chrome.browser.tab.TabUtils.LoadIfNeededCaller;
 import org.chromium.chrome.browser.tab.TabUtils.UseDesktopUserAgentCaller;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.ui.native_page.FrozenNativePage;
 import org.chromium.chrome.browser.ui.native_page.NativePage;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
@@ -81,8 +79,6 @@
  * This class is not intended to be extended.
  */
 public class TabImpl implements Tab {
-    private static final long INVALID_TIMESTAMP = -1;
-
     /** Used for logging. */
     private static final String TAG = "Tab";
 
@@ -204,8 +200,6 @@
     private final UserDataHost mUserDataHost = new UserDataHost();
 
     private boolean mIsDestroyed;
-    private ObservableSupplierImpl<Boolean> mIsTabSaveEnabledSupplier =
-            new ObservableSupplierImpl<>();
 
     private final TabThemeColorHelper mThemeColorHelper;
     private int mThemeColor;
@@ -255,7 +249,6 @@
      */
     @SuppressLint("HandlerLeak")
     TabImpl(int id, boolean incognito, @Nullable @TabLaunchType Integer launchType) {
-        mIsTabSaveEnabledSupplier.set(false);
         mId = TabIdManager.getInstance().generateValidId(id);
         mIncognito = incognito;
         mRootId = mId;
@@ -396,7 +389,6 @@
 
     @CalledByNative
     @Override
-    // TODO(crbug.com/1113249) move getUrl() to CriticalPersistedTabData
     public GURL getUrl() {
         if (!isInitialized()) {
             return GURL.emptyGURL();
@@ -855,15 +847,6 @@
         return null;
     }
 
-    @Override
-    public void setIsTabSaveEnabled(boolean isTabSaveEnabled) {
-        mIsTabSaveEnabledSupplier.set(isTabSaveEnabled);
-    }
-
-    public ObservableSupplierImpl<Boolean> getIsTabSaveEnabledSupplierForTesting() {
-        return mIsTabSaveEnabledSupplier;
-    }
-
     protected void updateWebContentObscured(boolean obscureWebContent) {
         // Update whether or not the current native tab and/or web contents are
         // currently visible (from an accessibility perspective), or whether
@@ -979,7 +962,6 @@
             if (mTimestampMillis == INVALID_TIMESTAMP) {
                 setTimestampMillis(System.currentTimeMillis());
             }
-            registerTabSaving();
             String appId = null;
             Boolean hasThemeColor = null;
             int themeColor = 0;
@@ -997,12 +979,6 @@
         }
     }
 
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    public void registerTabSaving() {
-        CriticalPersistedTabData.from(this).registerIsTabSaveEnabledSupplier(
-                mIsTabSaveEnabledSupplier);
-    }
-
     @Nullable
     @TabCreationState
     Integer getCreationState() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplier.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplier.java
index b0d3eae..3402a685 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplier.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.tabmodel;
 
-import androidx.annotation.Nullable;
-
 import org.chromium.base.Callback;
 import org.chromium.base.lifetime.Destroyable;
 import org.chromium.base.supplier.ObservableSupplier;
@@ -97,14 +95,15 @@
         super.set(profile);
     }
 
-    @Nullable
     @Override
     public Profile get() {
         Profile profile = super.get();
-        // TODO(crbug.com/1353138): Convert to an IllegalStateException if no bug reports are filed.
-        assert profile
-                != null : ("Attempting to read a null profile from the supplier. Use "
-                                  + "hasValue() instead and add an observer.");
+        if (profile == null) {
+            // Prevent unintentional access to a null profile early during app initialization. If a
+            // client wants to read this when it could be null, use hasValue() and add an observer
+            // to be notified when the profile becomes available.
+            throw new IllegalStateException("Attempting to read a null profile from the supplier");
+        }
         return profile;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
index 6ed7aab..f410b41 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -593,8 +593,8 @@
         // enforce the detection of unbuffered input/output operations, which results in
         // https://crbug.com/1276907. After evaluating the performance impact, here we disabled the
         // detection of unbuffered input/output operations.
-        // TabState is on a deprecation path and the intention is to replace with
-        // CriticalPersistedTabData. So this workaround should be temporary.
+        // This will no longer be necessary when the TabState schema is replaced with
+        // a FlatBuffer approach - go/tabstate-flatbuffer-decision.
         try (StrictModeContext ignored = StrictModeContext.allowUnbufferedIo()) {
             int restoredTabId = SharedPreferencesManager.getInstance().readInt(
                     ChromePreferenceKeys.TABMODEL_ACTIVE_TAB_ID, Tab.INVALID_TAB_ID);
@@ -1282,8 +1282,6 @@
             if (mDestroyed || isCancelled()) return;
             if (mStateSaved) {
                 if (!mTab.isDestroyed()) TabStateAttributes.from(mTab).clearTabStateDirtiness();
-                // TODO(b/298056319) Remove CriticalPersitsedTabData relevant code in TabImpl.
-                mTab.setIsTabSaveEnabled(false);
             }
             mSaveTabTask = null;
             saveNextTab();
@@ -1438,8 +1436,7 @@
     }
 
     /**
-     * Manages loading of {@link TabState} and {@link CriticalPersistedTabData} (TabState
-     * replacement) stored tab metadata. Also used to track if a load is in progress and the tab
+     * Manages loading of {@link TabState}. Also used to track if a load is in progress and the tab
      * details of that load.
      * TODO(b/298058408) deprecate TabLoader
      */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
index 0ec629e..438186a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
@@ -899,8 +899,8 @@
                                 MotionEvent.ACTION_HOVER_ENTER, xEnter, yEnter));
 
         // Verify that the card view is inflated as expected.
-        View hoverCardView = stripLayoutHelperManager.getActiveStripLayoutHelper()
-                                     .getTabHoverCardViewForTesting();
+        var hoverCardView = stripLayoutHelperManager.getActiveStripLayoutHelper()
+                                    .getTabHoverCardViewForTesting();
         Assert.assertNotNull("Hover card view should be set in normal StripLayoutHelper instance.",
                 stripLayoutHelperManager.getStripLayoutHelper(false)
                         .getTabHoverCardViewForTesting());
@@ -978,8 +978,8 @@
                                 MotionEvent.ACTION_HOVER_ENTER, standardXEnter, standardYEnter));
 
         // Verify that the card view background color is correctly set.
-        View hoverCardView = stripLayoutHelperManager.getActiveStripLayoutHelper()
-                                     .getTabHoverCardViewForTesting();
+        var hoverCardView = stripLayoutHelperManager.getActiveStripLayoutHelper()
+                                    .getTabHoverCardViewForTesting();
         Assert.assertNotNull("Hover card view should be set in normal StripLayoutHelper instance.",
                 stripLayoutHelperManager.getStripLayoutHelper(false)
                         .getTabHoverCardViewForTesting());
@@ -1044,8 +1044,8 @@
                                 MotionEvent.ACTION_HOVER_ENTER, xEnter, yEnter));
 
         // Verify that the card is visible.
-        View hoverCardView = stripLayoutHelperManager.getActiveStripLayoutHelper()
-                                     .getTabHoverCardViewForTesting();
+        var hoverCardView = stripLayoutHelperManager.getActiveStripLayoutHelper()
+                                    .getTabHoverCardViewForTesting();
         Assert.assertEquals(
                 "Hover card should be visible.", View.VISIBLE, hoverCardView.getVisibility());
 
@@ -1060,6 +1060,53 @@
     }
 
     /**
+     * Tests that the tab hover state is cleared when a down event is received on the tab strip.
+     */
+    @Test
+    @LargeTest
+    @Feature({"TabStrip"})
+    @EnableFeatures({ChromeFeatureList.ADVANCED_PERIPHERALS_SUPPORT_TAB_STRIP,
+            ChromeFeatureList.TAB_STRIP_REDESIGN})
+    @Restriction(UiRestriction.RESTRICTION_TYPE_TABLET)
+    public void
+    testTabHoverStateClearedOnDownEvent() throws Exception {
+        TabManagementFieldTrial.TAB_STRIP_REDESIGN_ENABLE_FOLIO.setForTesting(true);
+        // Open a new tab.
+        ChromeTabUtils.newTabFromMenu(
+                InstrumentationRegistry.getInstrumentation(), sActivityTestRule.getActivity());
+
+        TabModel model = sActivityTestRule.getActivity().getTabModelSelector().getModel(false);
+        StripLayoutTab tab = TabStripUtils.findStripLayoutTab(
+                sActivityTestRule.getActivity(), false, model.getTabAt(1).getId());
+        assertTabVisibility(true, tab);
+
+        // Simulate a hover into the tab's close button.
+        StripLayoutHelperManager stripLayoutHelperManager =
+                TabStripUtils.getStripLayoutHelperManager(sActivityTestRule.getActivity());
+        float xEnter = tab.getCloseButton().getX();
+        float yEnter = tab.getCloseButton().getY();
+        TestThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> stripLayoutHelperManager.simulateHoverEventForTesting(
+                                MotionEvent.ACTION_HOVER_ENTER, xEnter, yEnter));
+
+        // Verify that the card is visible.
+        View hoverCardView = stripLayoutHelperManager.getActiveStripLayoutHelper()
+                                     .getTabHoverCardViewForTesting();
+        Assert.assertEquals(
+                "Hover card should be visible.", View.VISIBLE, hoverCardView.getVisibility());
+
+        // Simulate a down event on the tab's close button.
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> stripLayoutHelperManager.simulateOnDownForTesting(xEnter, yEnter, true, 0));
+
+        CriteriaHelper.pollInstrumentationThread(() -> {
+            Criteria.checkThat("Hover card should be hidden.", hoverCardView.getVisibility(),
+                    Matchers.is(View.GONE));
+        });
+    }
+
+    /**
      * Take a model index and figure out which index it will be in the TabStrip's view hierarchy.
      * @param tabCount The number of tabs.
      * @param selectedIndex The index of the selected tab.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
index 7a64439..b940e5ec 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
@@ -21,6 +21,7 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RequiresRestart;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
@@ -167,6 +168,7 @@
     @Test
     @SmallTest
     @Feature({"Location"})
+    @DisabledTest(message = "http://crbug/1479552")
     public void testGeolocationHeaderPrimingEnabledPermissionAllow() {
         setPermission(ContentSettingValues.ALLOW);
         checkHeaderPriming(true /* shouldPrimeHeader */);
@@ -175,6 +177,7 @@
     @Test
     @SmallTest
     @Feature({"Location"})
+    @DisabledTest(message = "http://crbug/1479552")
     public void testGeolocationHeaderPrimingDisabledPermissionBlock() {
         setPermission(ContentSettingValues.BLOCK);
         checkHeaderPriming(false /* shouldPrimeHeader */);
@@ -183,6 +186,7 @@
     @Test
     @SmallTest
     @Feature({"Location"})
+    @DisabledTest(message = "http://crbug/1479552")
     public void testGeolocationHeaderPrimingDisabledPermissionAsk() {
         setPermission(ContentSettingValues.ASK);
         checkHeaderPriming(false /* shouldPrimeHeader */);
@@ -192,6 +196,7 @@
     @SmallTest
     @Feature({"Location"})
     @RequiresRestart(value = "Needs to reset cached geolocation from previous tests")
+    @DisabledTest(message = "http://crbug/1479552")
     public void testGeolocationHeaderPrimingDisabledOSPermissionBlocked() {
         setPermission(ContentSettingValues.ALLOW);
         LocationSettingsTestUtil.setSystemLocationSettingEnabled(false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
index bebde89..6130e2e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
@@ -15,6 +15,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.StrictModeContext;
+import org.chromium.base.jank_tracker.PlaceholderJankTracker;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.util.Batch;
@@ -87,7 +88,7 @@
                 cta::getTabModelSelector, cta.getCompositorViewHolderSupplier(),
                 cta.getModalDialogManagerSupplier(), cta::getSnackbarManager,
                 cta.getBrowserControlsManager(), cta.getActivityTabProvider(),
-                cta.getLifecycleDispatcher(), cta.getWindowAndroid(),
+                cta.getLifecycleDispatcher(), cta.getWindowAndroid(), new PlaceholderJankTracker(),
                 rootUiCoordinator.getToolbarManager()::getToolbar, null, null);
         // clang-format on
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
deleted file mode 100644
index 0372b6b..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
+++ /dev/null
@@ -1,439 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// 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.tab.state;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import androidx.test.filters.SmallTest;
-
-import com.google.flatbuffers.FlatBufferBuilder;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.Spy;
-
-import org.chromium.base.Callback;
-import org.chromium.base.StrictModeContext;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.supplier.ObservableSupplierImpl;
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.UiThreadTest;
-import org.chromium.base.test.util.Batch;
-import org.chromium.chrome.browser.tab.MockTab;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabCreationState;
-import org.chromium.chrome.browser.tab.TabImpl;
-import org.chromium.chrome.browser.tab.TabLaunchType;
-import org.chromium.chrome.browser.tab.TabStateAttributes;
-import org.chromium.chrome.browser.tab.TabUserAgent;
-import org.chromium.chrome.browser.tab.WebContentsState;
-import org.chromium.chrome.browser.tab.flatbuffer.CriticalPersistedTabDataFlatBuffer;
-import org.chromium.chrome.browser.tab.flatbuffer.CriticalPersistedTabDataFlatBufferTest;
-import org.chromium.chrome.browser.tab.flatbuffer.LaunchTypeAtCreation;
-import org.chromium.chrome.browser.tab.flatbuffer.LaunchTypeAtCreationTest;
-import org.chromium.chrome.browser.tab.flatbuffer.UserAgentType;
-import org.chromium.chrome.browser.tab.flatbuffer.UserAgentTypeTest;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
-import org.chromium.net.test.EmbeddedTestServer;
-import org.chromium.url.GURL;
-
-import java.nio.ByteBuffer;
-import java.util.concurrent.Semaphore;
-
-/**
- * Test relating to {@link CriticalPersistedTabData}
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-@Batch(Batch.PER_CLASS)
-public class CriticalPersistedTabDataTest {
-    @ClassRule
-    public static ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
-    @Rule
-    public BlankCTATabInitialStateRule mBlankCTATabInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
-
-    private static final int TAB_ID = 1;
-    private static final int PARENT_ID = 2;
-    private static final int ROOT_ID = 3;
-    private static final int CONTENT_STATE_VERSION = 42;
-    private static final byte[] WEB_CONTENTS_STATE_BYTES = {9, 10};
-    private static final WebContentsState WEB_CONTENTS_STATE =
-            new WebContentsState(ByteBuffer.allocateDirect(WEB_CONTENTS_STATE_BYTES.length));
-    private static final long TIMESTAMP = 203847028374L;
-    private static final long LAST_NAVIGATION_COMMITTED_TIMESTAMP = 3141592653589L;
-    private static final String APP_ID = "AppId";
-    private static final String OPENER_APP_ID = "OpenerAppId";
-    private static final int THEME_COLOR = 5;
-    private static final Integer LAUNCH_TYPE_AT_CREATION = 3;
-    private static final @TabUserAgent int USER_AGENT_A = TabUserAgent.MOBILE;
-    private static final @TabUserAgent int USER_AGENT_B = TabUserAgent.DESKTOP;
-    private static final String TITLE_A = "original title";
-    private static final String TITLE_B = "new title";
-    private static final GURL URL_A = new GURL("https://a.com");
-    private static final GURL URL_B = new GURL("https://b.com");
-    private static final int ROOT_ID_A = 42;
-    private static final int ROOT_ID_B = 1;
-    private static final int PARENT_ID_A = 43;
-    private static final int PARENT_ID_B = 2;
-    private static final long TIMESTAMP_A = 44;
-    private static final long TIMESTAMP_B = 3;
-    private static final @TabLaunchType Integer TAB_LAUNCH_TYPE_A = TabLaunchType.FROM_LINK;
-    private static final @TabLaunchType Integer TAB_LAUNCH_TYPE_B = TabLaunchType.FROM_EXTERNAL_APP;
-    private static final byte[] WEB_CONTENTS_STATE_A_BYTES = {4};
-    private static final byte[] WEB_CONTENTS_STATE_B_BYTES = {5, 6};
-    private static final WebContentsState WEB_CONTENTS_STATE_A =
-            new WebContentsState(ByteBuffer.allocateDirect(WEB_CONTENTS_STATE_A_BYTES.length));
-    private static final WebContentsState WEB_CONTENTS_STATE_B =
-            new WebContentsState(ByteBuffer.allocateDirect(WEB_CONTENTS_STATE_B_BYTES.length));
-    private static final String EXPECTED_TITLE = "My_title";
-    private static final String MOCK_DATA_ID = "mock-id";
-
-    static {
-        WEB_CONTENTS_STATE.buffer().put(WEB_CONTENTS_STATE_BYTES);
-        WEB_CONTENTS_STATE_A.buffer().put(WEB_CONTENTS_STATE_A_BYTES);
-        WEB_CONTENTS_STATE_B.buffer().put(WEB_CONTENTS_STATE_B_BYTES);
-    }
-
-    private CriticalPersistedTabData mCriticalPersistedTabData;
-    private MockPersistedTabDataStorage mStorage;
-    private EmbeddedTestServer mTestServer;
-
-    // Tell R8 not to break the ability to mock these classes.
-    @Mock
-    private TabImpl mUnused1;
-    @Mock
-    private CriticalPersistedTabData mUnused2;
-
-    @Spy
-    private MockPersistedTabDataStorage mMockPersistedTabDataStorageSpy;
-
-    private static Tab mockTab(int id, boolean isEncrypted) {
-        Tab tab = MockTab.createAndInitialize(id, isEncrypted);
-        tab.setIsTabSaveEnabled(true);
-        return tab;
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        PersistedTabDataConfiguration.setUseTestConfig(true);
-        mStorage = (MockPersistedTabDataStorage) PersistedTabDataConfiguration.getTestConfig()
-                           .getStorage();
-        mTestServer = sActivityTestRule.getTestServer();
-    }
-
-    @SmallTest
-    @Test
-    public void testNonEncryptedSaveRestore() throws InterruptedException {
-        testSaveRestoreDelete(false);
-    }
-
-    @SmallTest
-    @Test
-    public void testEncryptedSaveRestoreDelete() throws InterruptedException {
-        testSaveRestoreDelete(true);
-    }
-
-    private void testSaveRestoreDelete(boolean isEncrypted) throws InterruptedException {
-        final Semaphore semaphore = new Semaphore(0);
-        Callback<CriticalPersistedTabData> callback = new Callback<CriticalPersistedTabData>() {
-            @Override
-            public void onResult(CriticalPersistedTabData res) {
-                ObservableSupplierImpl<Boolean> supplier = new ObservableSupplierImpl<>();
-                supplier.set(true);
-                if (res != null) {
-                    res.registerIsTabSaveEnabledSupplier(supplier);
-                }
-                mCriticalPersistedTabData = res;
-                semaphore.release();
-            }
-        };
-        final Semaphore saveSemaphore = new Semaphore(0);
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            CriticalPersistedTabData criticalPersistedTabData = new CriticalPersistedTabData(
-                    new MockTab(TAB_ID, isEncrypted), "", "", ROOT_ID, OPENER_APP_ID,
-                    LAUNCH_TYPE_AT_CREATION, USER_AGENT_A, LAST_NAVIGATION_COMMITTED_TIMESTAMP);
-            criticalPersistedTabData.setShouldSaveForTesting(true);
-            mStorage.setSemaphore(saveSemaphore);
-            ObservableSupplierImpl<Boolean> supplier = new ObservableSupplierImpl<>();
-            supplier.set(true);
-            criticalPersistedTabData.registerIsTabSaveEnabledSupplier(supplier);
-            criticalPersistedTabData.save();
-            acquireSemaphore(saveSemaphore);
-            CriticalPersistedTabData.from(new MockTab(TAB_ID, isEncrypted), callback);
-        });
-        semaphore.acquire();
-        Assert.assertNotNull(mCriticalPersistedTabData);
-        assertEquals(mCriticalPersistedTabData.getOpenerAppId(), OPENER_APP_ID);
-        Semaphore deleteSemaphore = new Semaphore(0);
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            mStorage.setSemaphore(deleteSemaphore);
-            mCriticalPersistedTabData.delete();
-            acquireSemaphore(deleteSemaphore);
-            CriticalPersistedTabData.from(new MockTab(TAB_ID, isEncrypted), callback);
-        });
-        semaphore.acquire();
-        Assert.assertNull(mCriticalPersistedTabData);
-        // TODO(crbug.com/1060232) test restored.save() after restored.delete()
-        // Also cover
-        // - Multiple (different) TAB_IDs being stored in the same storage.
-        // - Tests for doing multiple operations on the same TAB_ID:
-        //   - save() multiple times
-        //  - restore() multiple times
-        //  - delete() multiple times
-    }
-
-    private static void acquireSemaphore(Semaphore semaphore) {
-        try {
-            semaphore.acquire();
-        } catch (InterruptedException e) {
-            // Throw Runtime exception to make catching InterruptedException unnecessary
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Test
-    @SmallTest
-    @UiThreadTest
-    public void testTabSaving() throws Throwable {
-        // Thread policies need to be relaxed - starting the test activity makes them stricter
-        // and the spy will fail without the thread policy being relaxed.
-        try (StrictModeContext ignored = StrictModeContext.allowAllThreadPolicies()) {
-            TabImpl tab = new MockTab(1, false);
-            CriticalPersistedTabData spyCriticalPersistedTabData =
-                    spy(CriticalPersistedTabData.from(tab));
-            tab = MockTab.initializeWithCriticalPersistedTabData(tab, spyCriticalPersistedTabData);
-            tab.registerTabSaving();
-
-            tab.setIsTabSaveEnabled(true);
-            verify(spyCriticalPersistedTabData, times(1)).save();
-            verify(spyCriticalPersistedTabData, times(0)).delete();
-
-            tab.setIsTabSaveEnabled(false);
-            verify(spyCriticalPersistedTabData, times(1)).save();
-            verify(spyCriticalPersistedTabData, times(1)).delete();
-
-            tab.setIsTabSaveEnabled(true);
-            verify(spyCriticalPersistedTabData, times(2)).save();
-            verify(spyCriticalPersistedTabData, times(1)).delete();
-        }
-    }
-
-    private CriticalPersistedTabData prepareCPTDShouldTabSave(
-            boolean canGoBack, boolean canGoForward) {
-        TabImpl tab = new MockTab(1, false);
-        TabImpl spyTab = spy(tab);
-        doReturn(canGoBack).when(spyTab).canGoBack();
-        doReturn(canGoForward).when(spyTab).canGoForward();
-        return spy(CriticalPersistedTabData.from(spyTab));
-    }
-
-    @UiThreadTest
-    @SmallTest
-    @Test
-    public void testSerializationBug() throws InterruptedException {
-        Tab tab = mockTab(TAB_ID, false);
-        CriticalPersistedTabData criticalPersistedTabData =
-                new CriticalPersistedTabData(tab, "", "", ROOT_ID, OPENER_APP_ID,
-                        LAUNCH_TYPE_AT_CREATION, USER_AGENT_A, LAST_NAVIGATION_COMMITTED_TIMESTAMP);
-        Serializer<ByteBuffer> serializer = criticalPersistedTabData.getSerializer();
-        serializer.preSerialize();
-        ByteBuffer serialized = serializer.get();
-        PersistedTabDataConfiguration config = PersistedTabDataConfiguration.get(
-                ShoppingPersistedTabData.class, tab.isIncognito());
-        CriticalPersistedTabData deserialized =
-                new CriticalPersistedTabData(tab, serialized, config.getStorage(), config.getId());
-        Assert.assertNotNull(deserialized);
-        assertEquals(OPENER_APP_ID, deserialized.getOpenerAppId());
-    }
-
-    @UiThreadTest
-    @SmallTest
-    @Test
-    public void testOpenerAppIdNull() {
-        Tab tab = mockTab(TAB_ID, false);
-        CriticalPersistedTabData criticalPersistedTabData =
-                new CriticalPersistedTabData(tab, "", "", ROOT_ID, null, LAUNCH_TYPE_AT_CREATION,
-                        USER_AGENT_A, LAST_NAVIGATION_COMMITTED_TIMESTAMP);
-        Serializer<ByteBuffer> serializer = criticalPersistedTabData.getSerializer();
-        serializer.preSerialize();
-        ByteBuffer serialized = serializer.get();
-        PersistedTabDataConfiguration config = PersistedTabDataConfiguration.get(
-                ShoppingPersistedTabData.class, tab.isIncognito());
-        CriticalPersistedTabData deserialized =
-                new CriticalPersistedTabData(tab, serialized, config.getStorage(), config.getId());
-        assertEquals(null, deserialized.getOpenerAppId());
-    }
-
-    @SmallTest
-    @Test
-    public void testConvertTabLaunchTypeToProtoLaunchType() {
-        for (@TabLaunchType Integer tabLaunchType = 0; tabLaunchType < TabLaunchType.SIZE;
-                tabLaunchType++) {
-            CriticalPersistedTabData.getLaunchType(tabLaunchType);
-        }
-    }
-
-    @SmallTest
-    @Test
-    public void testConvertProtoLaunchTypeToTabLaunchType() {
-        for (int type = LaunchTypeAtCreation.SIZE;
-                type < LaunchTypeAtCreation.names.length + LaunchTypeAtCreation.SIZE; type++) {
-            if (type == LaunchTypeAtCreation.UNKNOWN) continue;
-            CriticalPersistedTabData.getLaunchType(type);
-        }
-    }
-
-    @SmallTest
-    @Test
-    public void testConvertTabUserAgentToProtoUserAgentType() {
-        for (@TabUserAgent int tabUserAgent = 0; tabUserAgent <= TabUserAgent.SIZE;
-                tabUserAgent++) {
-            int flatBufferUserAgentType = CriticalPersistedTabData.getUserAgentType(tabUserAgent);
-            Assert.assertNotEquals("TabUserAgent value is invalid.", flatBufferUserAgentType,
-                    UserAgentType.USER_AGENT_UNKNOWN);
-            if (tabUserAgent != TabUserAgent.SIZE) continue;
-            assertEquals("TabUserAgent and ProtoUserAgentType should have the same size.",
-                    flatBufferUserAgentType, UserAgentType.USER_AGENT_SIZE);
-        }
-    }
-
-    @SmallTest
-    @Test
-    public void testConvertProtoUserAgentTypeToTabUserAgent() {
-        for (int type = 0; type < UserAgentType.names.length; type++) {
-            if (type == UserAgentType.USER_AGENT_UNKNOWN) continue;
-            @TabUserAgent
-            int tabUserAgent = CriticalPersistedTabData.getTabUserAgentType(type);
-            Assert.assertNotNull("ProtoUserAgentType value is invalid.", tabUserAgent);
-            if (type != UserAgentType.USER_AGENT_SIZE) continue;
-            assertEquals("TabUserAgent and ProtoUserAgentType should have the same size.",
-                    tabUserAgent, TabUserAgent.SIZE);
-        }
-    }
-
-    @SmallTest
-    @Test
-    public void testFlatBufferValuesUnchanged() {
-        // FlatBuffer enum values should not be changed as they are persisted across restarts.
-        // Changing them would cause backward compatibility issues crbug.com/1286984.
-        assertEquals(-2, LaunchTypeAtCreation.SIZE);
-        assertEquals(-1, LaunchTypeAtCreation.UNKNOWN);
-        assertEquals(0, LaunchTypeAtCreation.FROM_LINK);
-        assertEquals(1, LaunchTypeAtCreation.FROM_EXTERNAL_APP);
-        assertEquals(2, LaunchTypeAtCreation.FROM_CHROME_UI);
-        assertEquals(3, LaunchTypeAtCreation.FROM_RESTORE);
-        assertEquals(4, LaunchTypeAtCreation.FROM_LONGPRESS_FOREGROUND);
-        assertEquals(5, LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND);
-        assertEquals(6, LaunchTypeAtCreation.FROM_REPARENTING);
-        assertEquals(7, LaunchTypeAtCreation.FROM_LAUNCHER_SHORTCUT);
-        assertEquals(8, LaunchTypeAtCreation.FROM_SPECULATIVE_BACKGROUND_CREATION);
-        assertEquals(9, LaunchTypeAtCreation.FROM_BROWSER_ACTIONS);
-        assertEquals(10, LaunchTypeAtCreation.FROM_LAUNCH_NEW_INCOGNITO_TAB);
-        assertEquals(11, LaunchTypeAtCreation.FROM_STARTUP);
-        assertEquals(12, LaunchTypeAtCreation.FROM_START_SURFACE);
-        assertEquals(13, LaunchTypeAtCreation.FROM_TAB_GROUP_UI);
-        assertEquals(14, LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND_IN_GROUP);
-        assertEquals(15, LaunchTypeAtCreation.FROM_APP_WIDGET);
-        assertEquals(16, LaunchTypeAtCreation.FROM_LONGPRESS_INCOGNITO);
-        assertEquals(17, LaunchTypeAtCreation.FROM_RECENT_TABS);
-        assertEquals(18, LaunchTypeAtCreation.FROM_READING_LIST);
-        assertEquals(19, LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI);
-        assertEquals(20, LaunchTypeAtCreation.FROM_RESTORE_TABS_UI);
-        assertEquals(21, LaunchTypeAtCreation.FROM_OMNIBOX);
-        assertEquals("Need to increment 1 to expected value each time a LaunchTypeAtCreation "
-                        + "is added. Also need to add any new LaunchTypeAtCreation to this test.",
-                24, LaunchTypeAtCreation.names.length);
-    }
-
-    @SmallTest
-    @Test
-    @UiThreadTest
-    public void testSetRootIdInitializedTab() {
-        MockTab initializedTab = new MockTab(1, false);
-        initializedTab.setIsInitialized(true);
-        assertTrue(initializedTab.isInitialized());
-        CriticalPersistedTabData criticalPersistedTabData =
-                new CriticalPersistedTabData(initializedTab);
-        initializedTab.getUserDataHost().setUserData(
-                CriticalPersistedTabData.class, criticalPersistedTabData);
-        TabStateAttributes.createForTab(initializedTab, TabCreationState.FROZEN_ON_RESTORE);
-        TabStateAttributes.from(initializedTab).clearTabStateDirtiness();
-        assertEquals(TabStateAttributes.DirtinessState.CLEAN,
-                TabStateAttributes.from(initializedTab).getDirtinessState());
-        initializedTab.setRootId(ROOT_ID_A);
-        Assert.assertNotEquals(TabStateAttributes.DirtinessState.CLEAN,
-                TabStateAttributes.from(initializedTab).getDirtinessState());
-    }
-
-    @SmallTest
-    @Test
-    @UiThreadTest
-    public void testCompatabilityChangeWithOldFlatBuffer() {
-        FlatBufferBuilder fbb = new FlatBufferBuilder();
-        int oaid = fbb.createString(OPENER_APP_ID);
-
-        CriticalPersistedTabDataFlatBufferTest.startCriticalPersistedTabDataFlatBufferTest(fbb);
-        CriticalPersistedTabDataFlatBufferTest.addParentId(fbb, PARENT_ID);
-        CriticalPersistedTabDataFlatBufferTest.addRootId(fbb, ROOT_ID);
-        CriticalPersistedTabDataFlatBufferTest.addTimestampMillis(fbb, TIMESTAMP);
-        CriticalPersistedTabDataFlatBufferTest.addContentStateVersion(fbb, CONTENT_STATE_VERSION);
-        CriticalPersistedTabDataFlatBufferTest.addOpenerAppId(fbb, oaid);
-        CriticalPersistedTabDataFlatBufferTest.addThemeColor(fbb, THEME_COLOR);
-        CriticalPersistedTabDataFlatBufferTest.addLaunchTypeAtCreation(
-                fbb, LaunchTypeAtCreationTest.FROM_LINK);
-        CriticalPersistedTabDataFlatBufferTest.addUserAgent(fbb, UserAgentTypeTest.DEFAULT);
-
-        int r = CriticalPersistedTabDataFlatBufferTest.endCriticalPersistedTabDataFlatBufferTest(
-                fbb);
-        fbb.finish(r);
-
-        ByteBuffer byteBuffer = fbb.dataBuffer();
-        MockTab tab = new MockTab(TAB_ID, false);
-
-        // Check de-serialization works.
-        assertTrue(CriticalPersistedTabData.from(tab).deserialize(byteBuffer));
-
-        CriticalPersistedTabData deserialized = CriticalPersistedTabData.from(tab);
-        assertEquals(CONTENT_STATE_VERSION, deserialized.getContentStateVersion());
-        assertEquals(OPENER_APP_ID, deserialized.getOpenerAppId());
-    }
-
-    private static final ByteBuffer getFlatBufferWithNoWebContentsState() {
-        FlatBufferBuilder fbb = new FlatBufferBuilder();
-        int oaid = fbb.createString(OPENER_APP_ID);
-        CriticalPersistedTabDataFlatBuffer.startCriticalPersistedTabDataFlatBuffer(fbb);
-        CriticalPersistedTabDataFlatBuffer.addParentId(fbb, PARENT_ID);
-        CriticalPersistedTabDataFlatBuffer.addRootId(fbb, ROOT_ID);
-        CriticalPersistedTabDataFlatBuffer.addTimestampMillis(fbb, TIMESTAMP);
-        // WebContentsState intentionally left out
-        CriticalPersistedTabDataFlatBuffer.addContentStateVersion(fbb, CONTENT_STATE_VERSION);
-        CriticalPersistedTabDataFlatBuffer.addOpenerAppId(fbb, oaid);
-        CriticalPersistedTabDataFlatBuffer.addThemeColor(fbb, THEME_COLOR);
-        CriticalPersistedTabDataFlatBuffer.addLaunchTypeAtCreation(
-                fbb, LaunchTypeAtCreation.FROM_LINK);
-        CriticalPersistedTabDataFlatBuffer.addUserAgent(fbb, UserAgentType.DEFAULT);
-        CriticalPersistedTabDataFlatBuffer.addLastNavigationCommittedTimestampMillis(
-                fbb, LAST_NAVIGATION_COMMITTED_TIMESTAMP);
-
-        int r = CriticalPersistedTabDataFlatBuffer.endCriticalPersistedTabDataFlatBuffer(fbb);
-        fbb.finish(r);
-        return fbb.dataBuffer();
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorageTest.java
deleted file mode 100644
index debeaac..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorageTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// 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.tab.state;
-
-import androidx.test.filters.SmallTest;
-
-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.MockitoAnnotations;
-
-import org.chromium.base.FileUtils;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.UiThreadTest;
-import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.chrome.browser.crypto.CipherFactory;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.test.util.ByteBufferTestUtils;
-import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
-import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.concurrent.Semaphore;
-
-/**
- * Tests relating to  {@link FilePersistedTabDataStorage}
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-@Batch(Batch.PER_CLASS)
-@EnableFeatures({ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA + "<Study"})
-@CommandLineFlags.
-Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "force-fieldtrials=Study/Group"})
-public class FilePersistedTabDataStorageTest {
-    private static final int TAB_ID_1 = 1;
-    private static final String DATA_ID_1 = "DataId1";
-    private static final int TAB_ID_2 = 2;
-    private static final String DATA_ID_2 = "DataId2";
-    private static final int TAB_ID_3 = 3;
-    private static final String DATA_ID_3 = "DataId3";
-    private static final int TAB_ID_4 = 4;
-    private static final String DATA_ID_4 = "DataId4";
-
-    private static final byte[] DATA_A = {13, 14};
-    private static final byte[] DATA_B = {9, 10};
-
-    @Rule
-    public TestRule mProcessor = new Features.InstrumentationProcessor();
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
-        FilePersistedTabDataStorage.deleteFilesForTesting();
-    }
-
-    @SmallTest
-    @Test
-    public void testFilePersistedDataStorageNonEncrypted() throws InterruptedException {
-        testFilePersistedDataStorage(new FilePersistedTabDataStorage());
-    }
-
-    @SmallTest
-    @Test
-    public void testFilePersistedDataStorageEncrypted() throws InterruptedException {
-        testFilePersistedDataStorage(new EncryptedFilePersistedTabDataStorage());
-    }
-
-    @SmallTest
-    @Test
-    public void testUnsavedKeys() throws InterruptedException {
-        FilePersistedTabDataStorage persistedTabDataStorage =
-                new EncryptedFilePersistedTabDataStorage();
-        final Semaphore semaphore = new Semaphore(0);
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            persistedTabDataStorage.save(TAB_ID_1, DATA_ID_1,
-                    () -> { return ByteBuffer.wrap(DATA_A); }, semaphore::release);
-        });
-        semaphore.acquire();
-        // Simulate closing the app without saving the keys and reopening
-        CipherFactory.resetInstanceForTesting();
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            persistedTabDataStorage.restore(TAB_ID_1, DATA_ID_1, (res) -> {
-                Assert.assertNull(res);
-                semaphore.release();
-            });
-        });
-        semaphore.acquire();
-    }
-
-    private void testFilePersistedDataStorage(FilePersistedTabDataStorage persistedTabDataStorage)
-            throws InterruptedException {
-        final Semaphore semaphore = new Semaphore(0);
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            persistedTabDataStorage.save(TAB_ID_1, DATA_ID_1,
-                    () -> { return ByteBuffer.wrap(DATA_A); }, semaphore::release);
-        });
-        semaphore.acquire();
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            persistedTabDataStorage.restore(TAB_ID_1, DATA_ID_1, (res) -> {
-                ByteBufferTestUtils.verifyByteBuffer(DATA_A, res);
-                semaphore.release();
-            });
-        });
-        semaphore.acquire();
-
-        File file = FilePersistedTabDataStorage.getFile(TAB_ID_1, DATA_ID_1);
-        Assert.assertTrue(file.exists());
-
-        ThreadUtils.runOnUiThreadBlocking(
-                () -> { persistedTabDataStorage.delete(TAB_ID_1, DATA_ID_1, semaphore::release); });
-        semaphore.acquire();
-        Assert.assertFalse(file.exists());
-    }
-
-    @Test
-    @SmallTest
-    public void testRedundantSaveDropped() throws InterruptedException {
-        FilePersistedTabDataStorage storage = new FilePersistedTabDataStorage();
-        final Semaphore semaphore = new Semaphore(0);
-        storage.addSaveRequest(storage.new FileSaveRequest(TAB_ID_1, DATA_ID_1,
-                ()
-                        -> { return ByteBuffer.wrap(DATA_A); },
-                (res) -> {
-                    Assert.fail(
-                            "First request should not have been executed as there is a subsequent "
-                            + "request in the queue with the same Tab ID/Data ID combination");
-                }));
-        storage.addSaveRequest(storage.new FileSaveRequest(TAB_ID_2, DATA_ID_2,
-                () -> { return ByteBuffer.wrap(DATA_A); }, semaphore::release));
-        storage.addSaveRequest(storage.new FileSaveRequest(TAB_ID_1, DATA_ID_1,
-                () -> { return ByteBuffer.wrap(DATA_B); }, semaphore::release));
-        ThreadUtils.runOnUiThreadBlocking(() -> {
-            storage.processNextItemOnQueue();
-            storage.processNextItemOnQueue();
-        });
-        semaphore.acquire();
-        ThreadUtils.runOnUiThreadBlocking(() -> { storage.processNextItemOnQueue(); });
-        semaphore.acquire();
-        Assert.assertTrue(storage.mQueue.isEmpty());
-    }
-
-    @Test
-    @SmallTest
-    public void testOutOfMemoryError() throws InterruptedException {
-        // Ensure no data for Tab ID 1 / Data ID 1 (could be cross talk from other batch tests)
-        File file = FilePersistedTabDataStorage.getFile(TAB_ID_1, DATA_ID_1);
-        file.delete();
-        Assert.assertFalse(file.exists());
-        FilePersistedTabDataStorage storage = new FilePersistedTabDataStorage();
-        final Semaphore semaphore = new Semaphore(0);
-        storage.addSaveRequest(storage.new FileSaveRequest(TAB_ID_1, DATA_ID_1, () -> {
-            // OutOfMemory error on ByteBuffer supplier.
-            throw new OutOfMemoryError("OutOfMemoryError mock");
-        }, semaphore::release));
-        ThreadUtils.runOnUiThreadBlocking(() -> { storage.processNextItemOnQueue(); });
-        semaphore.acquire();
-        Assert.assertFalse(file.exists());
-    }
-
-    @Test
-    @SmallTest
-    @UiThreadTest
-    public void testShutdown() {
-        FilePersistedTabDataStorage storage =
-                PersistedTabDataConfiguration.getFilePersistedTabDataStorage();
-
-        Assert.assertFalse(FilePersistedTabDataStorage.getFile(TAB_ID_1, DATA_ID_1).exists());
-        Assert.assertFalse(FilePersistedTabDataStorage.getFile(TAB_ID_2, DATA_ID_2).exists());
-
-        storage.addSaveRequest(storage.new FileSaveRequest(
-                TAB_ID_1, DATA_ID_1, () -> { return ByteBuffer.wrap(DATA_B); }, (res) -> {}));
-        storage.addSaveRequest(storage.new FileSaveRequest(
-                TAB_ID_2, DATA_ID_2, () -> { return ByteBuffer.wrap(DATA_A); }, (res) -> {}));
-        Assert.assertEquals(2, storage.getStorageRequestQueueForTesting().size());
-        PersistedTabData.onShutdown();
-        Assert.assertEquals(0, storage.getStorageRequestQueueForTesting().size());
-
-        Assert.assertTrue(FilePersistedTabDataStorage.getFile(TAB_ID_1, DATA_ID_1).exists());
-        Assert.assertTrue(FilePersistedTabDataStorage.getFile(TAB_ID_2, DATA_ID_2).exists());
-    }
-
-    @Test
-    @SmallTest
-    @UiThreadTest
-    public void testShutdownEncrypted() {
-        FilePersistedTabDataStorage encryptedStorage =
-                PersistedTabDataConfiguration.getEncryptedFilePersistedTabDataStorage();
-        Assert.assertFalse(FilePersistedTabDataStorage.getFile(TAB_ID_3, DATA_ID_3).exists());
-        Assert.assertFalse(FilePersistedTabDataStorage.getFile(TAB_ID_4, DATA_ID_4).exists());
-        encryptedStorage.addSaveRequest(encryptedStorage.new FileSaveRequest(
-                TAB_ID_3, DATA_ID_3, () -> { return ByteBuffer.wrap(DATA_B); }, (res) -> {}));
-        encryptedStorage.addSaveRequest(encryptedStorage.new FileSaveRequest(
-                TAB_ID_4, DATA_ID_4, () -> { return ByteBuffer.wrap(DATA_A); }, (res) -> {}));
-        Assert.assertEquals(2, encryptedStorage.getStorageRequestQueueForTesting().size());
-        PersistedTabData.onShutdown();
-        Assert.assertEquals(0, encryptedStorage.getStorageRequestQueueForTesting().size());
-
-        Assert.assertTrue(FilePersistedTabDataStorage.getFile(TAB_ID_3, DATA_ID_3).exists());
-        Assert.assertTrue(FilePersistedTabDataStorage.getFile(TAB_ID_4, DATA_ID_4).exists());
-    }
-
-    @Test
-    @SmallTest
-    @UiThreadTest
-    public void testExecutingRequestInRightQueuePosition() throws IOException {
-        FilePersistedTabDataStorage storage =
-                PersistedTabDataConfiguration.getFilePersistedTabDataStorage();
-        storage.setExecutingSaveRequestForTesting(storage.new FileSaveRequest(
-                TAB_ID_1, DATA_ID_1, () -> { return ByteBuffer.wrap(DATA_A); }, (res) -> {}));
-        storage.addSaveRequest(storage.new FileSaveRequest(
-                TAB_ID_1, DATA_ID_1, () -> { return ByteBuffer.wrap(DATA_B); }, (res) -> {}));
-        PersistedTabData.onShutdown();
-        // Check second save request was the last to execute. mExecutingSaveRequest should
-        // have been inserted at the front of the queue.
-        ByteBufferTestUtils.verifyByteBuffer(DATA_B,
-                ByteBuffer.wrap(FileUtils.readStream(new FileInputStream(
-                        FilePersistedTabDataStorage.getFile(TAB_ID_1, DATA_ID_1)))));
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java
index 2b948472..5bc20336 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java
@@ -67,7 +67,6 @@
         PersistedTabDataConfiguration.setUseTestConfig(true);
         Tab tab = ThreadUtils.runOnUiThreadBlocking(() -> {
             Tab t = MockTab.createAndInitialize(1, false);
-            t.setIsTabSaveEnabled(true);
             return t;
         });
         MockPersistedTabData mockPersistedTabData = ThreadUtils.runOnUiThreadBlocking(() -> {
@@ -148,11 +147,9 @@
     @Test
     public void testOnTabClose() throws TimeoutException {
         TabImpl tab = (TabImpl) MockTab.createAndInitialize(1, false);
-        tab.setIsTabSaveEnabled(true);
         tab.getUserDataHost().setUserData(
                 ShoppingPersistedTabData.class, mShoppingPersistedTabDataMock);
         PersistedTabData.onTabClose(tab);
-        Assert.assertFalse(tab.getIsTabSaveEnabledSupplierForTesting().get());
         verify(mShoppingPersistedTabDataMock, times(1)).disableSaving();
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
index 7f4d0f3..433dd73b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
@@ -20,7 +20,6 @@
 import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.ThreadUtils;
-import org.chromium.base.UserDataHost;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.UiThreadTest;
@@ -749,26 +748,28 @@
                 mOptimizationGuideBridgeJniMock,
                 HintsProto.OptimizationType.SHOPPING_PAGE_PREDICTOR.getNumber(),
                 OptimizationGuideDecision.TRUE, null);
-        TabImpl tab = mock(TabImpl.class);
-        doReturn(ShoppingPersistedTabDataTestUtils.TAB_ID).when(tab).getId();
-        doReturn(ShoppingPersistedTabDataTestUtils.IS_INCOGNITO).when(tab).isIncognito();
-        long timestamp = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
-        doReturn(timestamp).when(tab).getTimestampMillis();
-        for (boolean isInitialized : new boolean[] {false, true}) {
-            doReturn(isInitialized).when(tab).isInitialized();
+        MockTab tab = TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
+            MockTab mockTab =
+                    (MockTab) MockTab.createAndInitialize(ShoppingPersistedTabDataTestUtils.TAB_ID,
+                            ShoppingPersistedTabDataTestUtils.IS_INCOGNITO);
+            long timestamp = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
+            mockTab.setTimestampMillis(timestamp);
+            return mockTab;
+        });
+        for (boolean isDestroyed : new boolean[] {false, true}) {
             Semaphore semaphore = new Semaphore(0);
             TestThreadUtils.runOnUiThreadBlocking(() -> {
-                UserDataHost userDataHost = new UserDataHost();
-                doReturn(userDataHost).when(tab).getUserDataHost();
+                if (isDestroyed) tab.destroy();
                 ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> {
-                    if (isInitialized) {
-                        Assert.assertNotNull(shoppingPersistedTabData);
-                    } else {
+                    if (isDestroyed) {
                         Assert.assertNull(shoppingPersistedTabData);
+                    } else {
+                        Assert.assertNotNull(shoppingPersistedTabData);
                     }
                     semaphore.release();
                 });
             });
+            ShoppingPersistedTabDataTestUtils.acquireSemaphore(semaphore);
         }
     }
 
@@ -951,10 +952,10 @@
     @SmallTest
     @Test
     public void testShoppingPersistedTabDataSupportedForMaintenance() {
-        TabImpl tab = mock(TabImpl.class);
-        doReturn(ShoppingPersistedTabDataTestUtils.TAB_ID).when(tab).getId();
-        doReturn(ShoppingPersistedTabDataTestUtils.IS_INCOGNITO).when(tab).isIncognito();
-        ShoppingPersistedTabData shoppingPersistedTabData = new ShoppingPersistedTabData(tab);
+        MockTab mockTab =
+                (MockTab) MockTab.createAndInitialize(ShoppingPersistedTabDataTestUtils.TAB_ID,
+                        ShoppingPersistedTabDataTestUtils.IS_INCOGNITO);
+        ShoppingPersistedTabData shoppingPersistedTabData = new ShoppingPersistedTabData(mockTab);
         Assert.assertTrue(PersistedTabData.getSupportedMaintenanceClassesForTesting().contains(
                 ShoppingPersistedTabData.class));
     }
@@ -966,7 +967,6 @@
         int count = helper.getCallCount();
         ThreadUtils.runOnUiThreadBlocking(() -> {
             Tab tab = MockTab.createAndInitialize(1, false);
-            tab.setIsTabSaveEnabled(true);
             DeserializeAndLogCheckerShoppingPersistedTabData deserializeChecker =
                     new DeserializeAndLogCheckerShoppingPersistedTabData(tab);
             registerObserverSupplier(deserializeChecker);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/critical_persisted_tab_data_test_v1.fbs b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/critical_persisted_tab_data_test_v1.fbs
deleted file mode 100644
index 8f466d4..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/critical_persisted_tab_data_test_v1.fbs
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-namespace org.chromium.chrome.browser.tab.flatbuffer;
-
-enum LaunchTypeAtCreationTest:int {
-    // SIZE is typically not used for anything other than bound
-    // checking but is included for completeness. It is added
-    // at the start rather than the end to enable other TabLaunchTypes
-    // to be added. It is not a problem that SIZE is not the same
-    // enum value as TabLaunchType.SIZE because the FlatBuffer persisted
-    // enum is mapped directly onto the TabLaunchType value in
-    // CriticalPersistedTabData. An alternative is to set SIZE to a large
-    // value but this is not possible as the enum values need to be sequential.
-    SIZE = -2,
-    // UNKNOWN indicates the TabLaunchType is null/not known.
-    UNKNOWN = -1,
-    FROM_LINK = 0,
-    FROM_EXTERNAL_APP = 1,
-    FROM_CHROME_UI = 2,
-    FROM_RESTORE = 3,
-    FROM_LONGPRESS_FOREGROUND = 4,
-    FROM_LONGPRESS_BACKGROUND = 5,
-    FROM_REPARENTING = 6,
-    FROM_LAUNCHER_SHORTCUT = 7,
-    FROM_SPECULATIVE_BACKGROUND_CREATION = 8,
-    FROM_BROWSER_ACTIONS = 9,
-    FROM_LAUNCH_NEW_INCOGNITO_TAB = 10,
-    FROM_STARTUP = 11,
-    FROM_START_SURFACE = 12,
-    FROM_TAB_GROUP_UI = 13,
-    FROM_LONGPRESS_BACKGROUND_IN_GROUP = 14,
-    FROM_APP_WIDGET = 15,
-    // Deprecated. Use `FROM_LONGPRESS_FOREGROUND` in new code.
-    FROM_LONGPRESS_INCOGNITO = 16,
-    FROM_RECENT_TABS = 17,
-    FROM_READING_LIST = 18,
-    FROM_TAB_SWITCHER_UI = 19,
-    FROM_RESTORE_TABS_UI = 20,
-    // Add new values here and don't change existing values
-    // as they are persisted across restarts. Changing existing
-    // values will lead to backwards compatibility issues crbug.com/1286984.
-}
-
-enum UserAgentTypeTest:int {
-    DEFAULT = 0,
-    MOBILE = 1,
-    DESKTOP = 2,
-    UNSET = 3,
-    USER_AGENT_SIZE = 4,
-    USER_AGENT_UNKNOWN = 5,
-}
-
-table CriticalPersistedTabDataFlatBufferTest {
-    // Parent Tab identifier.
-    parent_id:int;
-
-    // Root Tab identifier.
-    root_id:int;
-
-    // Timestamp when Tab was last accessed.
-    timestamp_millis:long;
-
-    // WebContentsState.
-    web_contents_state_bytes:[byte];
-
-    // Content State version.
-    content_state_version:int;
-
-    // Identifier for app which opened the Tab.
-    opener_app_id:string;
-
-    // Theme color.
-    theme_color:int;
-
-    // Launch type at creation.
-    launch_type_at_creation:LaunchTypeAtCreationTest;
-
-    // User Agent.
-    user_agent:UserAgentTypeTest=DEFAULT;
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
index cee1466..ffe01b6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
@@ -91,9 +91,6 @@
     @MediumTest
     @Feature({"OffTheRecord"})
     public void testRecreateInIncognito() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mActivityTestRule.getActivity().getActivityTab().setIsTabSaveEnabled(false);
-        });
         createTabOnUiThread();
         // Need to wait for contentsState to be initialized for the tab to restore correctly.
         CriteriaHelper.pollUiThread(() -> {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java
index 9b2da07..f6a3174 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java
@@ -64,15 +64,12 @@
         mActivity = sActivityTestRule.getActivity();
         final Tab tab = mActivity.getActivityTab();
         ChromeTabUtils.waitForInteractable(tab);
-        TestThreadUtils.runOnUiThreadBlocking(() -> tab.setIsTabSaveEnabled(false));
     }
 
     private void createTabs(int tabsCount, boolean isIncognito, String url) {
         for (int i = 0; i < tabsCount; i++) {
             Tab tab = ChromeTabUtils.fullyLoadUrlInNewTab(
                     InstrumentationRegistry.getInstrumentation(), mActivity, url, isIncognito);
-
-            TestThreadUtils.runOnUiThreadBlocking(() -> tab.setIsTabSaveEnabled(false));
         }
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
index b4f459c..16d25046 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -49,13 +49,10 @@
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.MockTabAttributes;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabImpl;
 import org.chromium.chrome.browser.tab.TabSelectionType;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.tab.TabStateAttributes;
 import org.chromium.chrome.browser.tab.TabStateExtractor;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
-import org.chromium.chrome.browser.tab.state.PersistedTabDataConfiguration;
 import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData;
 import org.chromium.chrome.browser.tabmodel.NextTabPolicy.NextTabPolicySupplier;
 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelSelectorMetadata;
@@ -673,50 +670,6 @@
     @Test
     @SmallTest
     @Feature({"TabPersistentStore"})
-    public void testFallbackTabStateEmptyByteBufferCriticalPersistedTabData() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            // Always return Empty Byte buffer (ByteBuffer with limit = 0 from storage)
-            PersistedTabDataConfiguration.setUseEmptyByteBufferTestConfig(true);
-        });
-        TabModelMetaDataInfo info = TestTabModelDirectory.TAB_MODEL_METADATA_V5_WITH_INCOGNITO;
-        int numExpectedTabs = info.contents.length;
-
-        // Write out Tab Model and TabState files
-        mMockDirectory.writeTabModelFiles(info, false);
-        for (int i = 0; i < info.contents.length; i++) {
-            mMockDirectory.writeTabStateFile(info.contents[i]);
-        }
-
-        // Initialize the classes.
-        MockTabModelSelector mockSelector =
-                TestThreadUtils.runOnUiThreadBlocking(() -> new MockTabModelSelector(0, 0, null));
-        MockTabCreatorManager mockManager = new MockTabCreatorManager(mockSelector);
-        MockTabPersistentStoreObserver mockObserver = new MockTabPersistentStoreObserver();
-        TabPersistencePolicy persistencePolicy = createTabPersistencePolicy(0, false, true);
-        final TabPersistentStore store =
-                buildTabPersistentStore(persistencePolicy, mockSelector, mockManager);
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            store.addObserver(mockObserver);
-
-            // Load the TabModel metadata.
-            store.loadState(false /* ignoreIncognitoFiles */);
-        });
-        mockObserver.initializedCallback.waitForCallback(0, 1);
-        Assert.assertEquals(numExpectedTabs, mockObserver.mTabCountAtStartup);
-        mockObserver.detailsReadCallback.waitForCallback(0, numExpectedTabs);
-        Assert.assertEquals(numExpectedTabs, mockObserver.details.size());
-
-        // Restore the TabStates, and confirm that the correct number of tabs is created.
-        TestThreadUtils.runOnUiThreadBlocking(() -> { store.restoreTabs(true); });
-        mockObserver.stateLoadedCallback.waitForCallback(0, 1);
-        Assert.assertEquals(info.numRegularTabs, mockSelector.getModel(false).getCount());
-        // No incognito TabState files were written.
-        Assert.assertEquals(0, mockSelector.getModel(true).getCount());
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"TabPersistentStore"})
     public void testSerializeDuringRestore() throws Exception {
         TabStateInfo regularTab =
                 new TabStateInfo(false, 2, 2, "https://google.com", "Google", null);
@@ -905,41 +858,6 @@
         Assert.assertEquals(5, TabRestoreMethod.SKIPPED_EMPTY_URL);
     }
 
-    private Pair<TabPersistentStore, Tab[]> restoreTabsFromTabStateAndPrepareForSaving()
-            throws Exception {
-        TabModelMetaDataInfo info = TestTabModelDirectory.TAB_MODEL_METADATA_V4;
-        int numExpectedTabs = info.contents.length;
-        mMockDirectory.writeTabModelFiles(info, true);
-        MockTabModelSelector mockSelector =
-                TestThreadUtils.runOnUiThreadBlocking(() -> new MockTabModelSelector(0, 0, null));
-        MockTabCreatorManager mockManager = new MockTabCreatorManager(mockSelector);
-        MockTabCreator regularCreator = mockManager.getTabCreator(false);
-        MockTabPersistentStoreObserver mockObserver = new MockTabPersistentStoreObserver();
-        TabPersistencePolicy persistencePolicy = createTabPersistencePolicy(0, false, true);
-        final TabPersistentStore store =
-                buildTabPersistentStore(persistencePolicy, mockSelector, mockManager);
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            store.addObserver(mockObserver);
-            store.loadState(false /* ignoreIncognitoFiles */);
-        });
-        mockObserver.initializedCallback.waitForCallback(0, 1);
-        mockObserver.detailsReadCallback.waitForCallback(0, numExpectedTabs);
-        TestThreadUtils.runOnUiThreadBlocking(() -> { store.restoreTabs(true); });
-        regularCreator.callback.waitForCallback(0, 1);
-        mockObserver.stateLoadedCallback.waitForCallback(0, 1);
-        Tab[] restoredTabs = new Tab[info.numRegularTabs];
-        for (int i = 0; i < info.numRegularTabs; i++) {
-            restoredTabs[i] = mockSelector.getModel(false).getTabAt(i);
-        }
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            for (Tab tab : restoredTabs) {
-                ((TabImpl) tab).registerTabSaving();
-                CriticalPersistedTabData.from(tab).setShouldSave();
-            }
-        });
-        return Pair.create(store, restoredTabs);
-    }
-
     private void addTabsToSaveQueue(TabPersistentStore store, Tab[] tabsToSave) {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             for (int i = 0; i < tabsToSave.length; i++) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java
index 1040843..325bbb4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java
@@ -293,7 +293,6 @@
     @Test
     @SmallTest
     @Feature("TabPersistentStore")
-    // TODO(crbug.com/1119583) Add similar test for CriticalPersistedTabData
     public void testNtpWithStateNotIgnoredDuringRestore() {
         mPersistentStore =
                 new TabPersistentStore(mPersistencePolicy, mTabModelSelector, mTabCreatorManager);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/app/tabmodel/TabPersistentStoreIntegrationTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/app/tabmodel/TabPersistentStoreIntegrationTest.java
index de0ce010..1e70dec7 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/app/tabmodel/TabPersistentStoreIntegrationTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/app/tabmodel/TabPersistentStoreIntegrationTest.java
@@ -37,7 +37,6 @@
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.homepage.HomepageManager;
 import org.chromium.chrome.browser.ntp.RecentlyClosedBridge;
 import org.chromium.chrome.browser.ntp.RecentlyClosedBridgeJni;
@@ -64,8 +63,6 @@
 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelSelectorMetadata;
 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver;
 import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
-import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 
 import java.io.File;
 import java.nio.ByteBuffer;
@@ -163,19 +160,10 @@
     @Test
     @SmallTest
     @Feature({"TabPersistentStore"})
-    @DisableFeatures(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA)
     public void testOpenAndCloseTabCreatesAndDeletesFile_tabState() {
         doTestOpenAndCloseTabCreatesAndDeletesFile();
     }
 
-    @Test
-    @SmallTest
-    @Feature({"TabPersistentStore"})
-    @EnableFeatures(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA)
-    public void testOpenAndCloseTabCreatesAndDeletesFile_persistedTabData() {
-        doTestOpenAndCloseTabCreatesAndDeletesFile();
-    }
-
     private void doTestOpenAndCloseTabCreatesAndDeletesFile() {
         // Setup the test: Create a tab
         TabModel tabModel = mTabModelSelector.getModel(false);
@@ -211,19 +199,10 @@
     @Test
     @SmallTest
     @Feature({"TabPersistentStore"})
-    @DisableFeatures(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA)
     public void testUndoTabClosurePersistsState_tabState() {
         doTestUndoTabClosurePersistsState();
     }
 
-    @Test
-    @SmallTest
-    @Feature({"TabPersistentStore"})
-    @EnableFeatures(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA)
-    public void testUndoTabClosurePersistsState_persistedTabData() {
-        doTestUndoTabClosurePersistsState();
-    }
-
     private void doTestUndoTabClosurePersistsState() {
         AtomicInteger timesMetadataSaved = new AtomicInteger();
         observeOnMetadataSavedAsynchronously(timesMetadataSaved);
@@ -247,7 +226,6 @@
     @Test
     @SmallTest
     @Feature({"TabPersistentStore"})
-    @EnableFeatures(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA)
     public void testCloseTabPersistsState() {
         AtomicInteger timesMetadataSaved = new AtomicInteger();
         observeOnMetadataSavedAsynchronously(timesMetadataSaved);
@@ -274,7 +252,6 @@
     @SmallTest
     @Feature({"TabPersistentStore"})
     @Config(manifest = Config.NONE, shadows = {ShadowHomepageManager.class})
-    @EnableFeatures(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA)
     public void testCloseAllTabsPersistsState() {
         AtomicInteger timesMetadataSaved = new AtomicInteger();
         observeOnMetadataSavedAsynchronously(timesMetadataSaved);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
index 4931dd58..71ddccc3 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
@@ -5,21 +5,16 @@
 package org.chromium.chrome.browser.compositor.overlays.strip;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.graphics.RectF;
 import android.view.ContextThemeWrapper;
 import android.view.View;
 import android.view.ViewStub;
-import android.widget.TextView;
 
 import androidx.appcompat.content.res.AppCompatResources;
-import androidx.core.content.ContextCompat;
 import androidx.test.core.app.ApplicationProvider;
 
 import org.junit.After;
@@ -61,7 +56,6 @@
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.browser_ui.styles.ChromeColors;
-import org.chromium.components.browser_ui.styles.SemanticColorUtils;
 import org.chromium.ui.base.LocalizationUtils;
 
 /** Tests for {@link StripLayoutHelperManager}. */
@@ -438,43 +432,4 @@
                         activeLayoutHelper.getStripLayoutTabsToRender(), 0f, selectedTabId,
                         hoveredTabId);
     }
-
-    @Test
-    @EnableFeatures(ChromeFeatureList.ADVANCED_PERIPHERALS_SUPPORT_TAB_STRIP)
-    public void testUpdateHoverCardColorsOnTabModelSelected() {
-        when(mStandardTabModel.isIncognito()).thenReturn(false);
-        when(mIncognitoTabModel.isIncognito()).thenReturn(true);
-        when(mTabModelSelector.getModel(false)).thenReturn(mStandardTabModel);
-        when(mTabModelSelector.getModel(true)).thenReturn(mIncognitoTabModel);
-
-        var tabHoverCardView = mock(View.class);
-        var titleView = mock(TextView.class);
-        var urlView = mock(TextView.class);
-        when(tabHoverCardView.findViewById(R.id.title)).thenReturn(titleView);
-        when(tabHoverCardView.findViewById(R.id.url)).thenReturn(urlView);
-
-        mStripLayoutHelperManager.getStripLayoutHelper(false).setTabHoverCardView(tabHoverCardView);
-        mStripLayoutHelperManager.getStripLayoutHelper(true).setTabHoverCardView(tabHoverCardView);
-        var tabModelSelectorObserver =
-                mStripLayoutHelperManager.getTabModelSelectorObserverForTesting();
-
-        // Standard tab model is currently considered active as
-        // StripLayoutHelperManager#mIsIncognito is false by default. Switch to the incognito tab
-        // model.
-        tabModelSelectorObserver.onTabModelSelected(mIncognitoTabModel, mStandardTabModel);
-        verify(tabHoverCardView)
-                .setBackgroundTintList(eq(ColorStateList.valueOf(ContextCompat.getColor(
-                        mContext, R.color.default_bg_color_dark_elev_5_baseline))));
-        verify(titleView).setTextColor(eq(mContext.getColor(R.color.default_text_color_light)));
-        verify(urlView).setTextColor(
-                eq(mContext.getColor(R.color.default_text_color_secondary_light)));
-
-        // Switch to the regular tab model.
-        tabModelSelectorObserver.onTabModelSelected(mStandardTabModel, mIncognitoTabModel);
-        verify(tabHoverCardView)
-                .setBackgroundTintList(eq(ColorStateList.valueOf(ChromeColors.getSurfaceColor(
-                        mContext, R.dimen.tab_hover_card_bg_color_elev))));
-        verify(titleView).setTextColor(eq(SemanticColorUtils.getDefaultTextColor(mContext)));
-        verify(urlView).setTextColor(eq(SemanticColorUtils.getDefaultTextColorSecondary(mContext)));
-    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
index 3f95113d..4b8e3b0 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
@@ -36,10 +36,8 @@
 import android.view.HapticFeedbackConstants;
 import android.view.View;
 import android.view.ViewGroup.MarginLayoutParams;
-import android.widget.TextView;
 
 import androidx.appcompat.content.res.AppCompatResources;
-import androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams;
 import androidx.test.core.app.ApplicationProvider;
 
 import org.junit.After;
@@ -48,7 +46,6 @@
 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.Mockito;
 import org.mockito.MockitoAnnotations;
@@ -86,7 +83,6 @@
 import org.chromium.chrome.test.util.browser.tabmodel.MockTabModel;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.shadows.ShadowAppCompatResources;
-import org.chromium.url.JUnitTestGURLs;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -125,7 +121,7 @@
     @Mock
     private PackageManager mPackageManager;
     @Mock
-    private View mTabHoverCardView;
+    private StripTabHoverCardView mTabHoverCardView;
 
     private Activity mActivity;
     private Context mContext;
@@ -2517,112 +2513,13 @@
 
     @Test
     public void testUpdateLastHoveredTab() {
+        // Assume tab0 is selected, tab1 is hovered on.
         initializeTabHoverTest(false, false);
         var hoveredTab = mStripLayoutHelper.getStripLayoutTabsForTesting()[1];
-
-        var titleView = mock(TextView.class);
-        var urlView = mock(TextView.class);
-        var url = JUnitTestGURLs.EXAMPLE_URL;
-        when(mTabHoverCardView.findViewById(R.id.title)).thenReturn(titleView);
-        when(mTabHoverCardView.findViewById(R.id.url)).thenReturn(urlView);
-        when(mModel.getTabAt(1).getUrl()).thenReturn(url);
-
         mStripLayoutHelper.updateLastHoveredTab(hoveredTab);
-
-        verify(titleView).setText(eq(mModel.getTabAt(1).getTitle()));
-        verify(urlView).setText(eq(mModel.getTabAt(1).getUrl().getHost()));
-        verify(mTabHoverCardView).setX(anyFloat());
-        verify(mTabHoverCardView).setY(anyFloat());
-        verify(mTabHoverCardView).setVisibility(eq(View.VISIBLE));
-
-        // Test chrome:// tab hover card display text.
-        url = JUnitTestGURLs.NTP_URL;
-        when(mModel.getTabAt(1).getUrl()).thenReturn(url);
-
-        mStripLayoutHelper.updateLastHoveredTab(hoveredTab);
-        verify(urlView).setText(eq(mModel.getTabAt(1).getUrl().getSpec().replaceFirst("/$", "")));
-    }
-
-    @Test
-    public void testGetHoverCardPosition() {
-        // Use TSR detached treatment for additional coverage that includes position adjustments.
-        TabManagementFieldTrial.TAB_STRIP_REDESIGN_ENABLE_DETACHED.setForTesting(true);
-        initializeTabHoverTest(false, false);
-        var hoveredTab = mStripLayoutHelper.getStripLayoutTabsForTesting()[1];
-        // Set simulated hovered StripLayoutTab drawX for expected hover card position.
-        hoveredTab.setDrawX(10f);
-
-        float[] position = mStripLayoutHelper.getHoverCardPosition(hoveredTab, false);
-        float detachedCardOffset =
-                mContext.getResources().getDimension(R.dimen.tsr_no_feet_tab_hover_card_x_offset);
-        assertEquals("Card x position is incorrect.", hoveredTab.getDrawX() + detachedCardOffset,
-                position[0], 0f);
-        assertEquals("Card y position is incorrect.",
-                SCREEN_HEIGHT + StripLayoutHelper.FOLIO_DETACHED_BOTTOM_MARGIN_DP, position[1], 0f);
-    }
-
-    @Test
-    public void testGetHoverCardPosition_CardWidthExceedsWindowWidth() {
-        initializeTabHoverTest(false, false);
-        var hoveredTab = mStripLayoutHelper.getStripLayoutTabsForTesting()[1];
-
-        // Set window width to be slightly smaller than the default card width.
-        float cardWidth = mContext.getResources().getDimension(R.dimen.tab_hover_card_width);
-        mContext.getResources().getDisplayMetrics().widthPixels = (int) (cardWidth - 1);
-        // Set simulated hovered StripLayoutTab drawX for expected hover card position.
-        hoveredTab.setDrawX(10f);
-        var originalLayoutParams = new LayoutParams((int) cardWidth, 200);
-        when(mTabHoverCardView.getLayoutParams()).thenReturn(originalLayoutParams);
-
-        float[] position = mStripLayoutHelper.getHoverCardPosition(hoveredTab, false);
-        ArgumentCaptor<LayoutParams> captor = ArgumentCaptor.forClass(LayoutParams.class);
-        verify(mTabHoverCardView).setLayoutParams(captor.capture());
-        assertEquals("Card width is incorrect.", Math.round(0.9f * (cardWidth - 1)),
-                captor.getValue().width);
-        assertEquals("Card x position is incorrect.", hoveredTab.getDrawX(), position[0], 0f);
-        assertEquals("Card y position is incorrect.", SCREEN_HEIGHT, position[1], 0f);
-    }
-
-    @Test
-    public void testGetHoverCardPosition_CardCrossesWindowBounds() {
-        initializeTabHoverTest(false, false);
-        var hoveredTab = mStripLayoutHelper.getStripLayoutTabsForTesting()[1];
-        float windowHorizontalMargin = mContext.getResources().getDimension(
-                R.dimen.tab_hover_card_window_horizontal_margin);
-
-        // Assume that the tab's hover card is positioned beyond the left edge of the app window.
-        hoveredTab.setDrawX(-1f);
-        float[] position = mStripLayoutHelper.getHoverCardPosition(hoveredTab, false);
-        assertEquals("Card should maintain a minimum margin from the left edge of the app window.",
-                windowHorizontalMargin, position[0], 0f);
-
-        // Assume that the tab's hover card extends beyond the right edge of the app window.
-        int windowWidth = mContext.getResources().getDisplayMetrics().widthPixels;
-        float cardWidth = mContext.getResources().getDimension(R.dimen.tab_hover_card_width);
-        hoveredTab.setDrawX(windowWidth - cardWidth + 1);
-        position = mStripLayoutHelper.getHoverCardPosition(hoveredTab, false);
-        assertEquals("Card should maintain a minimum margin from the right edge of the app window.",
-                windowWidth - cardWidth - windowHorizontalMargin, position[0], 0f);
-    }
-
-    @Test
-    public void testGetHoverCardPosition_RtlLayout() {
-        // Use TSR detached treatment for additional coverage that includes position adjustments.
-        TabManagementFieldTrial.TAB_STRIP_REDESIGN_ENABLE_DETACHED.setForTesting(true);
-        initializeTabHoverTest(true, false);
-        var hoveredTab = mStripLayoutHelper.getStripLayoutTabsForTesting()[1];
-
-        float cardWidth = mContext.getResources().getDimension(R.dimen.tab_hover_card_width);
-        // Set simulated hovered StripLayoutTab drawX and width for expected hover card position.
-        hoveredTab.setDrawX(28f);
-        hoveredTab.setWidth(cardWidth - 2);
-
-        float[] position = mStripLayoutHelper.getHoverCardPosition(hoveredTab, false);
-        float detachedCardOffset =
-                mContext.getResources().getDimension(R.dimen.tsr_no_feet_tab_hover_card_x_offset);
-        assertEquals("Card x position is incorrect.",
-                hoveredTab.getDrawX() - (cardWidth - hoveredTab.getWidth()) - detachedCardOffset,
-                position[0], 0f);
+        assertEquals(
+                "Last hovered tab is not set.", hoveredTab, mStripLayoutHelper.getLastHoveredTab());
+        verify(mTabHoverCardView).show(mModel.getTabAt(1), hoveredTab, false, SCREEN_HEIGHT);
     }
 
     @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripTabHoverCardViewUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripTabHoverCardViewUnitTest.java
new file mode 100644
index 0000000..76eede1
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripTabHoverCardViewUnitTest.java
@@ -0,0 +1,259 @@
+// Copyright 2023 The Chromium Authors
+// 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.compositor.overlays.strip;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.coordinatorlayout.widget.CoordinatorLayout.LayoutParams;
+import androidx.core.content.ContextCompat;
+import androidx.test.core.app.ApplicationProvider;
+
+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.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.LooperMode;
+import org.robolectric.annotation.LooperMode.Mode;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tasks.tab_management.TabManagementFieldTrial;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.components.browser_ui.styles.ChromeColors;
+import org.chromium.components.browser_ui.styles.SemanticColorUtils;
+import org.chromium.ui.base.LocalizationUtils;
+import org.chromium.url.JUnitTestGURLs;
+
+/** Unit tests for {@link StripTabHoverCardView}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@EnableFeatures({ChromeFeatureList.TAB_STRIP_REDESIGN})
+@Config(manifest = Config.NONE, qualifiers = "sw600dp")
+@LooperMode(Mode.LEGACY)
+public class StripTabHoverCardViewUnitTest {
+    @Rule
+    public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor();
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private TextView mTitleView;
+    @Mock
+    private TextView mUrlView;
+    @Mock
+    private Tab mHoveredTab;
+    @Mock
+    private StripLayoutTab mHoveredStripTab;
+    @Mock
+    private TabModelSelector mTabModelSelector;
+
+    private static final float STRIP_STACK_HEIGHT = 500.f;
+
+    private StripTabHoverCardView mTabHoverCardView;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = new ContextThemeWrapper(ApplicationProvider.getApplicationContext(),
+                org.chromium.chrome.R.style.Theme_BrowserUI_DayNight);
+        mTabHoverCardView = new StripTabHoverCardView(mContext);
+        mTabHoverCardView.setTitleViewForTesting(mTitleView);
+        mTabHoverCardView.setUrlViewForTesting(mUrlView);
+        mContext.getResources().getDisplayMetrics().density = 1f;
+    }
+
+    @Test
+    public void show() {
+        var url = JUnitTestGURLs.EXAMPLE_URL;
+        var title = "Tab 1";
+        when(mHoveredTab.getTitle()).thenReturn(title);
+        when(mHoveredTab.getUrl()).thenReturn(url);
+
+        StripTabHoverCardView cardViewSpy = spy(mTabHoverCardView);
+        cardViewSpy.show(mHoveredTab, mHoveredStripTab, false, STRIP_STACK_HEIGHT);
+
+        verify(mTitleView).setText(eq(mHoveredTab.getTitle()));
+        verify(mUrlView).setText(eq(mHoveredTab.getUrl().getHost()));
+        verify(cardViewSpy).setX(anyFloat());
+        verify(cardViewSpy).setY(anyFloat());
+        verify(cardViewSpy).setVisibility(eq(View.VISIBLE));
+
+        // Test chrome:// tab hover card display text.
+        url = JUnitTestGURLs.NTP_URL;
+        when(mHoveredTab.getUrl()).thenReturn(url);
+
+        mTabHoverCardView.show(mHoveredTab, mHoveredStripTab, false, STRIP_STACK_HEIGHT);
+        verify(mUrlView).setText(eq(mHoveredTab.getUrl().getSpec().replaceFirst("/$", "")));
+    }
+
+    @Test
+    public void getHoverCardPosition() {
+        // Use TSR detached treatment for additional coverage that includes position adjustments.
+        TabManagementFieldTrial.TAB_STRIP_REDESIGN_ENABLE_DETACHED.setForTesting(true);
+        // Set simulated hovered StripLayoutTab drawX for expected hover card position.
+        when(mHoveredStripTab.getDrawX()).thenReturn(10f);
+
+        float[] position =
+                mTabHoverCardView.getHoverCardPosition(mHoveredStripTab, false, STRIP_STACK_HEIGHT);
+        float detachedCardOffset =
+                mContext.getResources().getDimension(R.dimen.tsr_no_feet_tab_hover_card_x_offset);
+        assertEquals("Card x position is incorrect.", 10f + detachedCardOffset, position[0], 0f);
+        assertEquals("Card y position is incorrect.",
+                STRIP_STACK_HEIGHT + StripLayoutHelper.FOLIO_DETACHED_BOTTOM_MARGIN_DP, position[1],
+                0f);
+    }
+
+    @Test
+    public void getHoverCardPosition_CardWidthExceedsWindowWidth() {
+        // Set window width to be slightly smaller than the default card width.
+        float cardWidth = mContext.getResources().getDimension(R.dimen.tab_hover_card_width);
+        mContext.getResources().getDisplayMetrics().widthPixels = (int) (cardWidth - 1);
+        // Set simulated hovered StripLayoutTab drawX for expected hover card position.
+        when(mHoveredStripTab.getDrawX()).thenReturn(10f);
+        var originalLayoutParams = new LayoutParams((int) cardWidth, 200);
+        StripTabHoverCardView cardViewSpy = spy(mTabHoverCardView);
+        when(cardViewSpy.getLayoutParams()).thenReturn(originalLayoutParams);
+
+        float[] position =
+                cardViewSpy.getHoverCardPosition(mHoveredStripTab, false, STRIP_STACK_HEIGHT);
+        ArgumentCaptor<LayoutParams> captor = ArgumentCaptor.forClass(LayoutParams.class);
+        verify(cardViewSpy).setLayoutParams(captor.capture());
+        assertEquals("Card width is incorrect.", Math.round(0.9f * (cardWidth - 1)),
+                captor.getValue().width);
+        assertEquals("Card x position is incorrect.", 10f, position[0], 0f);
+        assertEquals("Card y position is incorrect.", STRIP_STACK_HEIGHT, position[1], 0f);
+    }
+
+    @Test
+    public void getHoverCardPosition_CardCrossesWindowBounds() {
+        float windowHorizontalMargin = mContext.getResources().getDimension(
+                R.dimen.tab_hover_card_window_horizontal_margin);
+
+        // Assume that the tab's hover card is positioned beyond the left edge of the app window.
+        when(mHoveredStripTab.getDrawX()).thenReturn(-1f);
+        float[] position =
+                mTabHoverCardView.getHoverCardPosition(mHoveredStripTab, false, STRIP_STACK_HEIGHT);
+        assertEquals("Card should maintain a minimum margin from the left edge of the app window.",
+                windowHorizontalMargin, position[0], 0f);
+
+        // Assume that the tab's hover card extends beyond the right edge of the app window.
+        int windowWidth = mContext.getResources().getDisplayMetrics().widthPixels;
+        float cardWidth = mContext.getResources().getDimension(R.dimen.tab_hover_card_width);
+        when(mHoveredStripTab.getDrawX()).thenReturn(windowWidth - cardWidth + 1);
+        position =
+                mTabHoverCardView.getHoverCardPosition(mHoveredStripTab, false, STRIP_STACK_HEIGHT);
+        assertEquals("Card should maintain a minimum margin from the right edge of the app window.",
+                windowWidth - cardWidth - windowHorizontalMargin, position[0], 0f);
+    }
+
+    @Test
+    public void getHoverCardPosition_RtlLayout() {
+        // Use TSR detached treatment for additional coverage that includes position adjustments.
+        TabManagementFieldTrial.TAB_STRIP_REDESIGN_ENABLE_DETACHED.setForTesting(true);
+        LocalizationUtils.setRtlForTesting(true);
+
+        float cardWidth = mContext.getResources().getDimension(R.dimen.tab_hover_card_width);
+        // Set simulated hovered StripLayoutTab drawX and width for expected hover card position.
+        when(mHoveredStripTab.getDrawX()).thenReturn(28f);
+        when(mHoveredStripTab.getWidth()).thenReturn(cardWidth - 2);
+
+        float[] position =
+                mTabHoverCardView.getHoverCardPosition(mHoveredStripTab, false, STRIP_STACK_HEIGHT);
+        float detachedCardOffset =
+                mContext.getResources().getDimension(R.dimen.tsr_no_feet_tab_hover_card_x_offset);
+        assertEquals("Card x position is incorrect.", 26f - detachedCardOffset, position[0], 0f);
+    }
+
+    @Test
+    @EnableFeatures(ChromeFeatureList.ADVANCED_PERIPHERALS_SUPPORT_TAB_STRIP)
+    public void updateHoverCardColors() {
+        StripTabHoverCardView cardViewSpy = spy(mTabHoverCardView);
+
+        // Test incognito colors.
+        cardViewSpy.updateHoverCardColors(true);
+        verify(cardViewSpy)
+                .setBackgroundTintList(eq(ColorStateList.valueOf(ContextCompat.getColor(
+                        mContext, R.color.default_bg_color_dark_elev_5_baseline))));
+        verify(mTitleView).setTextColor(eq(mContext.getColor(R.color.default_text_color_light)));
+        verify(mUrlView).setTextColor(
+                eq(mContext.getColor(R.color.default_text_color_secondary_light)));
+
+        // Test standard colors.
+        cardViewSpy.updateHoverCardColors(false);
+        verify(cardViewSpy)
+                .setBackgroundTintList(eq(ColorStateList.valueOf(ChromeColors.getSurfaceColor(
+                        mContext, R.dimen.tab_hover_card_bg_color_elev))));
+        verify(mTitleView).setTextColor(eq(SemanticColorUtils.getDefaultTextColor(mContext)));
+        verify(mUrlView).setTextColor(
+                eq(SemanticColorUtils.getDefaultTextColorSecondary(mContext)));
+    }
+
+    @Test
+    @EnableFeatures(ChromeFeatureList.ADVANCED_PERIPHERALS_SUPPORT_TAB_STRIP)
+    public void initialize() {
+        StripTabHoverCardView cardViewSpy = spy(mTabHoverCardView);
+
+        // View is inflated in standard tab model.
+        when(mTabModelSelector.isIncognitoSelected()).thenReturn(false);
+        cardViewSpy.initialize(mTabModelSelector);
+        verify(cardViewSpy).updateHoverCardColors(false);
+
+        // View is inflated in incognito tab model.
+        when(mTabModelSelector.isIncognitoSelected()).thenReturn(true);
+        cardViewSpy.initialize(mTabModelSelector);
+        verify(cardViewSpy).updateHoverCardColors(true);
+    }
+
+    @Test
+    @EnableFeatures(ChromeFeatureList.ADVANCED_PERIPHERALS_SUPPORT_TAB_STRIP)
+    public void tabModelSelectorObserver_OnTabModelSelected() {
+        var standardTabModel = mock(TabModel.class);
+        var incognitoTabModel = mock(TabModel.class);
+        when(standardTabModel.isIncognito()).thenReturn(false);
+        when(incognitoTabModel.isIncognito()).thenReturn(true);
+
+        StripTabHoverCardView cardViewSpy = spy(mTabHoverCardView);
+
+        // Assume standard tab model.
+        when(mTabModelSelector.isIncognitoSelected()).thenReturn(false);
+        // TabModelSelectorObserver should be added after the view is inflated.
+        cardViewSpy.initialize(mTabModelSelector);
+        var tabModelSelectorObserver = cardViewSpy.getTabModelSelectorObserverForTesting();
+        assertNotNull("TabModelSelectorObserver should be set.", tabModelSelectorObserver);
+
+        // Switch to the incognito tab model.
+        tabModelSelectorObserver.onTabModelSelected(incognitoTabModel, standardTabModel);
+        verify(cardViewSpy).updateHoverCardColors(true);
+
+        // Switch to the standard tab model.
+        tabModelSelectorObserver.onTabModelSelected(standardTabModel, incognitoTabModel);
+        // Invoked once in #onInflate(), subsequently in #onTabModelSelected().
+        verify(cardViewSpy, times(2)).updateHoverCardColors(false);
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java
index a43a01f..d77ae20c 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java
@@ -5,6 +5,8 @@
 package org.chromium.chrome.browser.feed;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -39,6 +41,7 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLog;
 
+import org.chromium.base.jank_tracker.PlaceholderJankTracker;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.JniMocker;
@@ -79,10 +82,17 @@
 import org.chromium.components.feed.proto.wire.ReliabilityLoggingEnums.DiscoverLaunchResult;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.search_engines.TemplateUrlService;
+import org.chromium.components.signin.AccountCapabilitiesConstants;
+import org.chromium.components.signin.base.AccountCapabilities;
+import org.chromium.components.signin.base.AccountInfo;
+import org.chromium.components.signin.base.CoreAccountId;
+import org.chromium.components.signin.identitymanager.ConsentLevel;
 import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.ui.base.WindowAndroid;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Tests for {@link FeedSurfaceCoordinator}.
@@ -255,6 +265,7 @@
         Profile.setLastUsedProfileForTesting(mProfileMock);
         IdentityServicesProvider.setInstanceForTests(mIdentityService);
         when(mIdentityService.getSigninManager(any(Profile.class))).thenReturn(mSigninManager);
+        when(mIdentityService.getIdentityManager(any(Profile.class))).thenReturn(mIdentityManager);
         when(mSigninManager.getIdentityManager()).thenReturn(mIdentityManager);
         SignInPromo.setDisablePromoForTesting(true);
 
@@ -499,6 +510,38 @@
                         SectionHeaderListProperties.STICKY_HEADER_VISIBLILITY_KEY));
     }
 
+    @Test
+    public void testIsPrimaryAccountSupervisedForChildUser() {
+        AccountInfo account = createFakeAccount(/*isChild=*/true);
+        when(mIdentityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN)).thenReturn(account);
+        when(mIdentityManager.findExtendedAccountInfoByEmailAddress(account.getEmail()))
+                .thenReturn(account);
+        assertTrue(mCoordinator.isPrimaryAccountSupervised());
+    }
+
+    @Test
+    public void testIsPrimaryAccountSupervisedForRegularUser() {
+        AccountInfo account = createFakeAccount(/*isChild=*/false);
+        when(mIdentityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN)).thenReturn(account);
+        when(mIdentityManager.findExtendedAccountInfoByEmailAddress(account.getEmail()))
+                .thenReturn(account);
+        assertFalse(mCoordinator.isPrimaryAccountSupervised());
+    }
+
+    @Test
+    public void testIsPrimaryAccountSupervisedForSignedOutUser() {
+        when(mIdentityManager.getPrimaryAccountInfo(ConsentLevel.SIGNIN)).thenReturn(null);
+        assertFalse(mCoordinator.isPrimaryAccountSupervised());
+    }
+
+    private AccountInfo createFakeAccount(boolean isChild) {
+        AccountCapabilities capabilities = new AccountCapabilities(new HashMap<>(
+                Map.of(AccountCapabilitiesConstants.IS_SUBJECT_TO_PARENTAL_CONTROLS_CAPABILITY_NAME,
+                        isChild)));
+        return new AccountInfo(new CoreAccountId("id"), "test@gmail.com", "gaiaId", "John Doe",
+                "John", null, capabilities);
+    }
+
     private boolean hasStreamBound() {
         if (mCoordinator.getMediatorForTesting().getCurrentStreamForTesting() == null) {
             return false;
@@ -508,9 +551,10 @@
     }
 
     private FeedSurfaceCoordinator createCoordinator() {
-        return new FeedSurfaceCoordinator(mActivity, mSnackbarManager, mWindowAndroid, mSnapHelper,
-                null, 0, false, new TestSurfaceDelegate(), mProfileMock, false,
-                mBottomSheetController, mShareDelegateSupplier, mScrollableContainerDelegate,
+        return new FeedSurfaceCoordinator(mActivity, mSnackbarManager, mWindowAndroid,
+                new PlaceholderJankTracker(), mSnapHelper, null, 0, false,
+                new TestSurfaceDelegate(), mProfileMock, false, mBottomSheetController,
+                mShareDelegateSupplier, mScrollableContainerDelegate,
                 NewTabPageLaunchOrigin.UNKNOWN, mPrivacyPreferencesManager,
                 ()
                         -> { return null; },
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
index 886daeae..6df49dc6 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
@@ -92,7 +92,8 @@
 
     private static class MockNativePageBuilder extends NativePageFactory.NativePageBuilder {
         private MockNativePageBuilder() {
-            super(null, null, null, null, null, null, null, null, null, null, null, null, null);
+            super(null, null, null, null, null, null, null, null, null, null, null, null, null,
+                    null);
         }
 
         @Override
@@ -119,7 +120,7 @@
     @Before
     public void setUp() {
         mNativePageFactory = new NativePageFactory(
-                null, null, null, null, null, null, null, null, null, null, null, null);
+                null, null, null, null, null, null, null, null, null, null, null, null, null);
         mNativePageFactory.setNativePageBuilderForTesting(new MockNativePageBuilder());
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
index 96ddd62..5dcc391 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
@@ -50,7 +50,6 @@
 import org.chromium.base.FeatureList;
 import org.chromium.base.FeatureList.TestValues;
 import org.chromium.base.SysUtils;
-import org.chromium.base.UserDataHost;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -69,7 +68,6 @@
 import org.chromium.chrome.browser.tab.RequestDesktopUtilsUnitTest.ShadowTabUtils;
 import org.chromium.chrome.browser.tab.RequestDesktopUtilsUnitTest.ShadowUmaSessionStats;
 import org.chromium.chrome.browser.tab.TabUtilsUnitTest.ShadowProfile;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings.SiteLayout;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettingsConstants;
 import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge;
@@ -243,8 +241,6 @@
     @Mock
     private Tracker mTracker;
     @Mock
-    private CriticalPersistedTabData mCriticalPersistedTabData;
-    @Mock
     private ObservableSupplier<Tab> mCurrentTabSupplier;
     @Mock
     private DisplayAndroid mDisplayAndroid;
@@ -1601,11 +1597,7 @@
     }
 
     private Tab createTab() {
-        Tab tab = mock(Tab.class);
-        UserDataHost tabDataHost = new UserDataHost();
-        when(tab.getUserDataHost()).thenReturn(tabDataHost);
-        tabDataHost.setUserData(CriticalPersistedTabData.class, mCriticalPersistedTabData);
-        return tab;
+        return mock(Tab.class);
     }
 
     private void enableFeature(String featureName, boolean enable) {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabUtilsUnitTest.java
index 8c71f28..11fe6f6e 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabUtilsUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabUtilsUnitTest.java
@@ -156,7 +156,7 @@
         verify(mNavigationController)
                 .setUseDesktopUserAgent(true, false, UseDesktopUserAgentCaller.OTHER);
 
-        // CriticalPersistedTabData#setUserAgent should not be used when it is not forcedByUser.
+        // Tab#setUserAgent should not be used when it is not forcedByUser.
         verify(mTab, never()).setUserAgent(anyInt());
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelImplUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelImplUnitTest.java
index 8cccc76..a20f6324 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelImplUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelImplUnitTest.java
@@ -35,7 +35,6 @@
 import org.chromium.chrome.browser.tab.TabCreationState;
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tab.TabSelectionType;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 
 import java.util.Arrays;
 
@@ -112,10 +111,8 @@
 
     private Tab createTab(final TabModel model, long activeTimestampMillis, int parentId) {
         final int launchType = TabLaunchType.FROM_CHROME_UI;
-        MockTab tab = new MockTab(mNextTabId++, model.isIncognito());
-        CriticalPersistedTabData data = new CriticalPersistedTabData(tab);
+        MockTab tab = (MockTab) MockTab.createAndInitialize(mNextTabId++, model.isIncognito());
         tab.setTimestampMillis(activeTimestampMillis);
-        tab = (MockTab) MockTab.initializeWithCriticalPersistedTabData(tab, data);
         tab.setParentId(parentId);
         tab.setIsInitialized(true);
         model.addTab(tab, -1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
diff --git a/chrome/app/main_dll_loader_win.cc b/chrome/app/main_dll_loader_win.cc
index 18549fb..b9084fa 100644
--- a/chrome/app/main_dll_loader_win.cc
+++ b/chrome/app/main_dll_loader_win.cc
@@ -87,9 +87,12 @@
 // Prefetches and loads |module| after setting the CWD to |module|'s
 // directory. Returns a handle to the loaded module on success, or nullptr on
 // failure.
-HMODULE LoadModuleWithDirectory(const base::FilePath& module) {
+HMODULE LoadModuleWithDirectory(const base::FilePath& module,
+                                const base::CommandLine& cmd_line) {
   ::SetCurrentDirectoryW(module.DirName().value().c_str());
-  base::PreReadFile(module, /*is_executable=*/true);
+  if (!cmd_line.HasSwitch(switches::kNoPreReadMainDll)) {
+    base::PreReadFile(module, /*is_executable=*/true);
+  }
   HMODULE handle = ::LoadLibraryExW(module.value().c_str(), nullptr,
                                     LOAD_WITH_ALTERED_SEARCH_PATH);
   return handle;
@@ -98,13 +101,13 @@
 // Prefetches and loads the appropriate DLL for the process type
 // |process_type_|. Populates |module| with the path of the loaded DLL.
 // Returns a handle to the loaded DLL, or nullptr on failure.
-HMODULE Load(base::FilePath* module) {
+HMODULE Load(base::FilePath* module, const base::CommandLine& cmd_line) {
   *module = GetModulePath(installer::kChromeDll);
   if (module->empty()) {
     PLOG(ERROR) << "Cannot find module " << installer::kChromeDll;
     return nullptr;
   }
-  HMODULE dll = LoadModuleWithDirectory(*module);
+  HMODULE dll = LoadModuleWithDirectory(*module, cmd_line);
   if (!dll)
     PLOG(ERROR) << "Failed to load Chrome DLL from " << module->value();
   return dll;
@@ -146,7 +149,7 @@
   }
 
   base::FilePath file;
-  dll_ = Load(&file);
+  dll_ = Load(&file, cmd_line);
   if (!dll_)
     return chrome::RESULT_CODE_MISSING_DATA;
 
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index adc71458..d2d9742 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -897,6 +897,9 @@
   <message name="IDS_OS_SETTINGS_REVAMP_PERSONALIZATION" desc="Name of the OS settings page which displays personalization preferences.">
     Wallpaper and style
   </message>
+  <message name="IDS_OS_SETTINGS_PERSONALIZATION_MENU_ITEM_DESCRIPTION" desc="Description for the Personalization menu item in the left menu.">
+    Dark theme, screen saver
+  </message>
   <message name="IDS_OS_SETTINGS_OPEN_PERSONALIZATION_HUB" desc="Title for the link to open personalization hub.">
     Set your wallpaper &amp; style
   </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_PERSONALIZATION_MENU_ITEM_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_PERSONALIZATION_MENU_ITEM_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..ffd41e13
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_PERSONALIZATION_MENU_ITEM_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+1e4b8c444191c7118829cd42fe4d832a11e4f939
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 154d4dc..75e585bd 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2648,19 +2648,19 @@
     Not allowed to automatically download multiple files
   </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_DESCRIPTION" desc="Description of the auto-picture-in-picture content setting.">
-    Sites might open a picture-in-picture window when you change to a different tab
+    Sites use this setting to enter picture-in-picture mode if you switch tabs on certain sites. This lets you continue watching a video, while freeing up your screen for other tasks.
   </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED" desc="Label for the enabled option of the auto-picture-in-picture content setting.">
-    Sites can open a picture-in-picture window when you change to a different tab
+    Sites can enter picture-in-picture automatically
   </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED" desc="Label for the disabled option of the auto-picture-in-picture content setting.">
-    Don't allow sites to open a picture-in-picture window when you change to a different tab
+    Don't allow sites to enter picture-in-picture automatically
   </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED_EXCEPTIONS" desc="Label for the allowed exceptions site list of the auto-picture-in-picture content setting.">
-    Allowed to open a picture-in-picture window when you change to a different tab
+    Allowed to enter picture-in-picture automatically
   </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED_EXCEPTIONS" desc="Label for the blocked exceptions site list of the auto-picture-in-picture content setting.">
-    Not allowed to open a picture-in-picture window when you change to a different tab
+    Not allowed to enter picture-in-picture automatically
   </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC_DESCRIPTION" desc="Description of the background sync content setting.">
     After you leave a site, it can keep syncing to finish tasks, like uploading photos or sending a chat message
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED.png.sha1
index 94e1ba4..418a619 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED.png.sha1
@@ -1 +1 @@
-abbeabf2300cf637e1e418456545d75bf350d829
\ No newline at end of file
+33e2203d32e64aa7488f932c20302eeb766fe6bb
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED_EXCEPTIONS.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED_EXCEPTIONS.png.sha1
index 94e1ba4..418a619 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED_EXCEPTIONS.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_ALLOWED_EXCEPTIONS.png.sha1
@@ -1 +1 @@
-abbeabf2300cf637e1e418456545d75bf350d829
\ No newline at end of file
+33e2203d32e64aa7488f932c20302eeb766fe6bb
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED.png.sha1
index 94e1ba4..418a619 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED.png.sha1
@@ -1 +1 @@
-abbeabf2300cf637e1e418456545d75bf350d829
\ No newline at end of file
+33e2203d32e64aa7488f932c20302eeb766fe6bb
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED_EXCEPTIONS.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED_EXCEPTIONS.png.sha1
index 94e1ba4..418a619 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED_EXCEPTIONS.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_BLOCKED_EXCEPTIONS.png.sha1
@@ -1 +1 @@
-abbeabf2300cf637e1e418456545d75bf350d829
\ No newline at end of file
+33e2203d32e64aa7488f932c20302eeb766fe6bb
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_DESCRIPTION.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_DESCRIPTION.png.sha1
index 94e1ba4..418a619 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_DESCRIPTION.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_AUTO_PICTURE_IN_PICTURE_DESCRIPTION.png.sha1
@@ -1 +1 @@
-abbeabf2300cf637e1e418456545d75bf350d829
\ No newline at end of file
+33e2203d32e64aa7488f932c20302eeb766fe6bb
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 5eb1deb..77f6f39 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1931,6 +1931,10 @@
       "preloading/preview/preview_manager.h",
       "preloading/preview/preview_tab.cc",
       "preloading/preview/preview_tab.h",
+      "privacy_sandbox/tracking_protection_notice_factory.cc",
+      "privacy_sandbox/tracking_protection_notice_factory.h",
+      "privacy_sandbox/tracking_protection_notice_service.cc",
+      "privacy_sandbox/tracking_protection_notice_service.h",
       "user_education/browser_tutorial_service.cc",
       "user_education/browser_tutorial_service.h",
       "user_education/user_education_configuration_provider.cc",
@@ -2238,6 +2242,7 @@
     "//components/lookalikes/core:proto",
     "//components/lookalikes/core:safety_tips",
     "//components/media_device_salt",
+    "//components/media_effects",
     "//components/memory_pressure",
     "//components/metrics:call_stack_profile_collector",
     "//components/metrics:call_stack_profile_params",
@@ -4628,6 +4633,7 @@
       "//components/keep_alive_registry",
       "//components/live_caption",
       "//components/live_caption:live_translate",
+      "//components/media_effects",
       "//components/memory_pressure",
       "//components/omnibox/browser:mojo_bindings",
       "//components/services/app_service",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 533cfb91..939c459 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -196,6 +196,7 @@
   "+components/media_router/browser",
   "+components/history_clusters",
   "+components/history_clusters/history_clusters_internals",
+  "+components/media_effects",
   "+components/memory_pressure",
   "+components/messages/android",
   "+components/metal_util",
diff --git a/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.cc b/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.cc
index e72c13f..cf38ff9 100644
--- a/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.cc
+++ b/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/accessibility/live_caption/live_caption_controller_factory.h"
 #include "chrome/browser/accessibility/live_translate_controller_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/live_caption/greedy_text_stabilizer.h"
 #include "components/live_caption/live_caption_controller.h"
 #include "components/live_caption/live_translate_controller.h"
 #include "components/live_caption/pref_names.h"
@@ -38,6 +39,8 @@
 #include "ui/base/l10n/l10n_util.h"
 
 namespace {
+static constexpr int kMinTokenFrequency = 1;
+static constexpr int kWaitKValue = 1;
 
 // Split the transcription into sentences. Spaces are included in the preceding
 // sentence.
@@ -118,6 +121,31 @@
           script_code[0] == USCRIPT_YI || script_code[0] == USCRIPT_KATAKANA);
 }
 
+std::string RemoveLastKWords(const std::string& input) {
+  int words_to_remove = kWaitKValue;
+
+  if (words_to_remove == 0) {
+    return input;
+  }
+
+  size_t length = input.length();
+  size_t last_space_pos = 0;
+
+  while (words_to_remove > 0 && length > 0) {
+    length--;
+    if (std::isspace(input[length])) {
+      words_to_remove--;
+      last_space_pos = length;
+    }
+  }
+
+  if (words_to_remove == 0) {
+    return input.substr(0, last_space_pos);
+  } else {
+    return std::string();
+  }
+}
+
 }  // namespace
 
 namespace captions {
@@ -149,6 +177,12 @@
   context_ = CaptionBubbleContextBrowser::Create(web_contents);
 
   source_language_ = prefs_->GetString(prefs::kLiveCaptionLanguageCode);
+
+  if (base::FeatureList::IsEnabled(
+          media::kLiveCaptionUseGreedyTextStabilizer)) {
+    greedy_text_stabilizer_ =
+        std::make_unique<captions::GreedyTextStabilizer>(kMinTokenFrequency);
+  }
 }
 
 LiveCaptionSpeechRecognitionHost::~LiveCaptionSpeechRecognitionHost() {
@@ -223,7 +257,9 @@
       // cached.
       std::move(reply).Run(live_caption_controller->DispatchTranscription(
           context_.get(),
-          media::SpeechRecognitionResult(cached_translation, result.is_final)));
+          media::SpeechRecognitionResult(
+              GetTextForDispatch(cached_translation, result.is_final),
+              result.is_final)));
     }
   } else {
     std::move(reply).Run(
@@ -315,10 +351,11 @@
   }
 
   LiveCaptionController* live_caption_controller = GetLiveCaptionController();
+  auto text = base::StrCat({cached_translation, formatted_result});
+
   stop_transcriptions_ = !live_caption_controller->DispatchTranscription(
-      context_.get(),
-      media::SpeechRecognitionResult(
-          base::StrCat({cached_translation, formatted_result}), is_final));
+      context_.get(), media::SpeechRecognitionResult(
+                          GetTextForDispatch(text, is_final), is_final));
 }
 
 content::WebContents* LiveCaptionSpeechRecognitionHost::GetWebContents() {
@@ -351,4 +388,19 @@
   return LiveTranslateControllerFactory::GetForProfile(profile);
 }
 
+std::string LiveCaptionSpeechRecognitionHost::GetTextForDispatch(
+    const std::string& input_text,
+    bool is_final) {
+  std::string text = input_text;
+  if (base::FeatureList::IsEnabled(media::kLiveCaptionUseWaitK) && !is_final) {
+    text = RemoveLastKWords(text);
+  }
+
+  if (base::FeatureList::IsEnabled(
+          media::kLiveCaptionUseGreedyTextStabilizer)) {
+    text = greedy_text_stabilizer_->UpdateText(text, is_final);
+  }
+
+  return text;
+}
 }  // namespace captions
diff --git a/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.h b/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.h
index fd2b9721..861cf90 100644
--- a/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.h
+++ b/chrome/browser/accessibility/live_caption/live_caption_speech_recognition_host.h
@@ -26,6 +26,7 @@
 namespace captions {
 
 class CaptionBubbleContextBrowser;
+class GreedyTextStabilizer;
 class LiveCaptionController;
 class LiveTranslateController;
 
@@ -94,6 +95,9 @@
   // does not exist. Lifetime is tied to the BrowserContext.
   LiveTranslateController* GetLiveTranslateController();
 
+  // Processes and returns the text to be dispatched.
+  std::string GetTextForDispatch(const std::string& text, bool is_final);
+
   std::unique_ptr<CaptionBubbleContextBrowser> context_;
 
   // A flag used by the Live Translate feature indicating whether transcriptions
@@ -117,6 +121,8 @@
   // The number of characters sent to the translation service.
   int characters_translated_ = 0;
 
+  std::unique_ptr<captions::GreedyTextStabilizer> greedy_text_stabilizer_;
+
   base::WeakPtrFactory<LiveCaptionSpeechRecognitionHost> weak_factory_{this};
 };
 
diff --git a/chrome/browser/android/webapk/BUILD.gn b/chrome/browser/android/webapk/BUILD.gn
index f69d2dd..adb0a87 100644
--- a/chrome/browser/android/webapk/BUILD.gn
+++ b/chrome/browser/android/webapk/BUILD.gn
@@ -35,6 +35,7 @@
     "//components/crx_file:crx_file",
     "//components/sync",
     "//components/webapps/browser",
+    "//components/webapps/common",
     "//content/public/browser",
     "//services/metrics/public/cpp:ukm_builders",
     "//third_party/smhasher:murmurhash2",
diff --git a/chrome/browser/android/webapk/webapk_helpers.cc b/chrome/browser/android/webapk/webapk_helpers.cc
index afae190..e55384c 100644
--- a/chrome/browser/android/webapk/webapk_helpers.cc
+++ b/chrome/browser/android/webapk/webapk_helpers.cc
@@ -4,15 +4,15 @@
 
 #include "chrome/browser/android/webapk/webapk_helpers.h"
 
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "components/crx_file/id_util.h"
+#include "components/webapps/common/web_app_id.h"
 #include "crypto/sha2.h"
 #include "url/gurl.h"
 
 namespace webapk {
 
-web_app::AppId GenerateAppIdFromManifestId(
-    const web_app::ManifestId& manifest_id) {
+webapps::AppId GenerateAppIdFromManifestId(
+    const webapps::ManifestId& manifest_id) {
   // The app ID is hashed twice: here and in GenerateId.
   // The double-hashing is for historical reasons and it needs to stay
   // this way for backwards compatibility.
diff --git a/chrome/browser/android/webapk/webapk_helpers.h b/chrome/browser/android/webapk/webapk_helpers.h
index 9657232..783344ae 100644
--- a/chrome/browser/android/webapk/webapk_helpers.h
+++ b/chrome/browser/android/webapk/webapk_helpers.h
@@ -6,13 +6,14 @@
 #define CHROME_BROWSER_ANDROID_WEBAPK_WEBAPK_HELPERS_H_
 
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace webapk {
 
 // Generates the chrome-specific `AppId` from the spec-defined manifest id. See
 // the `AppId` type for more information.
-web_app::AppId GenerateAppIdFromManifestId(
-    const web_app::ManifestId& manifest_id);
+webapps::AppId GenerateAppIdFromManifestId(
+    const webapps::ManifestId& manifest_id);
 
 }  // namespace webapk
 
diff --git a/chrome/browser/android/webapk/webapk_sync_bridge.cc b/chrome/browser/android/webapk/webapk_sync_bridge.cc
index 1ba1b3e..d29cea6 100644
--- a/chrome/browser/android/webapk/webapk_sync_bridge.cc
+++ b/chrome/browser/android/webapk/webapk_sync_bridge.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/android/webapk/webapk_database.h"
 #include "chrome/browser/android/webapk/webapk_database_factory.h"
 #include "chrome/browser/android/webapk/webapk_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/common/channel_info.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/base/report_unrecoverable_error.h"
@@ -21,6 +20,7 @@
 #include "components/sync/model/model_type_store.h"
 #include "components/sync/model/mutable_data_batch.h"
 #include "components/sync/protocol/web_app_specifics.pb.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
@@ -41,7 +41,7 @@
 namespace {
 
 const WebApkProto* GetAppById(const Registry& registry,
-                              const web_app::AppId& app_id) {
+                              const webapps::AppId& app_id) {
   auto it = registry.find(app_id);
   if (it != registry.end()) {
     return it->second.get();
@@ -125,7 +125,7 @@
                                DataCallback callback) {
   auto data_batch = std::make_unique<syncer::MutableDataBatch>();
 
-  for (const web_app::AppId& app_id : storage_keys) {
+  for (const webapps::AppId& app_id : storage_keys) {
     const WebApkProto* app = GetAppById(registry_, app_id);
     if (app) {
       data_batch->Put(app_id, CreateSyncEntityData(*app));
@@ -139,7 +139,7 @@
   auto data_batch = std::make_unique<syncer::MutableDataBatch>();
 
   for (const auto& appListing : registry_) {
-    const web_app::AppId app_id = appListing.first;
+    const webapps::AppId app_id = appListing.first;
     const WebApkProto& app = *appListing.second;
     data_batch->Put(app_id, CreateSyncEntityData(app));
   }
diff --git a/chrome/browser/android/webapk/webapk_sync_bridge_unittest.cc b/chrome/browser/android/webapk/webapk_sync_bridge_unittest.cc
index a3f6d3a4..ad84ba6 100644
--- a/chrome/browser/android/webapk/webapk_sync_bridge_unittest.cc
+++ b/chrome/browser/android/webapk/webapk_sync_bridge_unittest.cc
@@ -12,9 +12,9 @@
 #include "chrome/browser/android/webapk/fake_webapk_database_factory.h"
 #include "chrome/browser/android/webapk/webapk_database_factory.h"
 #include "chrome/browser/android/webapk/webapk_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "components/sync/model/data_batch.h"
 #include "components/sync/test/mock_model_type_change_processor.h"
+#include "components/webapps/common/web_app_id.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -74,7 +74,7 @@
 
 void InsertAppIntoRegistry(Registry* registry,
                            std::unique_ptr<WebApkProto> app) {
-  web_app::AppId app_id =
+  webapps::AppId app_id =
       GenerateAppIdFromManifestId(GURL(app->sync_data().manifest_id()));
   ASSERT_FALSE(base::Contains(*registry, app_id));
   registry->emplace(std::move(app_id), std::move(app));
diff --git a/chrome/browser/apps/app_shim/BUILD.gn b/chrome/browser/apps/app_shim/BUILD.gn
index 9ea9942..a2832cb 100644
--- a/chrome/browser/apps/app_shim/BUILD.gn
+++ b/chrome/browser/apps/app_shim/BUILD.gn
@@ -39,6 +39,7 @@
     "//components/crx_file",
     "//components/remote_cocoa/browser",
     "//components/version_info",
+    "//components/webapps/common",
     "//content/public/browser",
     "//content/public/common",
     "//services/preferences/public/cpp:cpp",
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac.cc b/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
index e65cb7ef..9fc1185 100644
--- a/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
@@ -313,7 +313,7 @@
 // The state for an individual app. This includes the state for all
 // profiles that are using the app.
 struct AppShimManager::AppState {
-  AppState(const web_app::AppId& app_id,
+  AppState(const webapps::AppId& app_id,
            std::unique_ptr<AppShimHost> multi_profile_host)
       : app_id(app_id), multi_profile_host(std::move(multi_profile_host)) {}
   AppState(const AppState&) = delete;
@@ -430,7 +430,7 @@
 }
 
 AppShimHost* AppShimManager::FindHost(Profile* profile,
-                                      const web_app::AppId& app_id) {
+                                      const webapps::AppId& app_id) {
   auto found_app = apps_.find(app_id);
   if (found_app == apps_.end())
     return nullptr;
@@ -448,7 +448,7 @@
 
 void AppShimManager::UpdateAppBadge(
     Profile* profile,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     const absl::optional<badging::BadgeManager::BadgeValue>& badge) {
   // TODO(https://crbug.com/1199624): Support updating the app badge for apps
   // that aren't currently running.
@@ -470,7 +470,7 @@
 }
 
 mojo::Remote<mac_notifications::mojom::MacNotificationProvider>
-AppShimManager::LaunchNotificationProvider(const web_app::AppId& app_id) {
+AppShimManager::LaunchNotificationProvider(const webapps::AppId& app_id) {
   CHECK(
       base::FeatureList::IsEnabled(features::kAppShimNotificationAttribution));
 
@@ -510,7 +510,7 @@
 }
 
 Profile* AppShimManager::ProfileForBackgroundShimLaunch(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (profile_manager_) {
     for (Profile* p : profile_manager_->GetLoadedProfiles()) {
       if (!p->IsRegularProfile()) {
@@ -525,7 +525,7 @@
 }
 
 void AppShimManager::LaunchShimInBackgroundMode(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceCallback<void(AppShimHost*)> callback) {
   // A shim can only be launched through an active profile, so find a profile
   // through which to do the launch. This method should only be called for
@@ -673,7 +673,7 @@
 
 void AppShimManager::OnShimProcessConnectedForRegisterOnly(
     std::unique_ptr<AppShimHostBootstrap> bootstrap) {
-  const web_app::AppId& app_id = bootstrap->GetAppId();
+  const webapps::AppId& app_id = bootstrap->GetAppId();
   DCHECK_EQ(bootstrap->GetLaunchType(),
             chrome::mojom::AppShimLaunchType::kRegisterOnly);
 
@@ -1049,7 +1049,7 @@
 }
 
 void AppShimManager::LoadProfileAndApp(const base::FilePath& profile_path,
-                                       const web_app::AppId& app_id,
+                                       const webapps::AppId& app_id,
                                        LoadProfileAndAppCallback callback) {
   // Run |profile_loaded_callback| when the profile is loaded (be that now, or
   // after having to asynchronously load the profile).
@@ -1064,7 +1064,7 @@
 
 void AppShimManager::LoadProfileAndApp_OnProfileLoaded(
     const base::FilePath& profile_path,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     LoadProfileAndAppCallback callback,
     Profile* profile) {
   // It may be that the profile fails to load.
@@ -1086,7 +1086,7 @@
 
 void AppShimManager::LoadProfileAndApp_OnProfileAppRegistryReady(
     const base::FilePath& profile_path,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     LoadProfileAndAppCallback callback) {
   // It may be that the profile was destroyed while waiting for the callback to
   // be issued.
@@ -1110,7 +1110,7 @@
 
 void AppShimManager::LoadProfileAndApp_OnAppEnabled(
     const base::FilePath& profile_path,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     LoadProfileAndAppCallback callback) {
   std::move(callback).Run(ProfileForPath(profile_path));
 }
@@ -1153,7 +1153,7 @@
 std::unique_ptr<AppShimHost> AppShimManager::CreateHost(
     AppShimHost::Client* client,
     const base::FilePath& profile_path,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     bool use_remote_cocoa) {
   return std::make_unique<AppShimHost>(client, app_id, profile_path,
                                        use_remote_cocoa);
@@ -1298,7 +1298,7 @@
   LoadProfileAsync(
       *last_active_profile_paths.begin(),
       base::BindOnce(
-          [](const web_app::AppId& app_id, Profile* profile) {
+          [](const webapps::AppId& app_id, Profile* profile) {
             if (profile) {
               chrome::ShowWebAppSettings(
                   profile, app_id,
@@ -1609,7 +1609,7 @@
 
 AppShimManager::ProfileState* AppShimManager::GetOrCreateProfileState(
     Profile* profile,
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (web_app::AppShimCreationAndLaunchDisabledForTest()) {
     return nullptr;
   }
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac.h b/chrome/browser/apps/app_shim/app_shim_manager_mac.h
index 7386645..154cb7b5 100644
--- a/chrome/browser/apps/app_shim/app_shim_manager_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_manager_mac.h
@@ -30,6 +30,7 @@
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut_mac.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/services/mac_notifications/public/mojom/mac_notifications.mojom.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 class ProfileManager;
@@ -71,33 +72,33 @@
     // Show all app windows (for non-PWA apps). Return true if there existed any
     // windows.
     virtual bool ShowAppWindows(Profile* profile,
-                                const web_app::AppId& app_id) = 0;
+                                const webapps::AppId& app_id) = 0;
 
     // Close all app windows (for non-PWA apps).
     virtual void CloseAppWindows(Profile* profile,
-                                 const web_app::AppId& app_id) = 0;
+                                 const webapps::AppId& app_id) = 0;
 
     // Return true iff |app_id| corresponds to an app that is installed for
     // |profile|. Note that |profile| may be nullptr (in which case it should
     // always return false).
     virtual bool AppIsInstalled(Profile* profile,
-                                const web_app::AppId& app_id) = 0;
+                                const webapps::AppId& app_id) = 0;
 
     // Return true iff the specified app can create an AppShimHost, which will
     // keep the app shim process connected (as opposed to, e.g, a bookmark app
     // that opens in a tab, which will immediately close).
     virtual bool AppCanCreateHost(Profile* profile,
-                                  const web_app::AppId& app_id) = 0;
+                                  const webapps::AppId& app_id) = 0;
 
     // Return true if Cocoa windows for this app should be hosted in the app
     // shim process.
     virtual bool AppUsesRemoteCocoa(Profile* profile,
-                                    const web_app::AppId& app_id) = 0;
+                                    const webapps::AppId& app_id) = 0;
 
     // Return true if a single app shim is used for all profiles (as opposed to
     // one shim per profile).
     virtual bool AppIsMultiProfile(Profile* profile,
-                                   const web_app::AppId& app_id) = 0;
+                                   const webapps::AppId& app_id) = 0;
 
     // Open a dialog to enable the specified extension. Call |callback| after
     // the dialog is executed.
@@ -110,7 +111,7 @@
     // is called.
     virtual void LaunchApp(
         Profile* profile,
-        const web_app::AppId& app_id,
+        const webapps::AppId& app_id,
         const std::vector<base::FilePath>& files,
         const std::vector<GURL>& urls,
         const GURL& override_url,
@@ -120,7 +121,7 @@
     // Launch the shim process for an app. It is guaranteed that |app_id| is
     // installed for |profile| when this method is called.
     virtual void LaunchShim(Profile* profile,
-                            const web_app::AppId& app_id,
+                            const webapps::AppId& app_id,
                             web_app::LaunchShimUpdateBehavior update_behavior,
                             web_app::ShimLaunchMode launch_mode,
                             ShimLaunchedCallback launched_callback,
@@ -132,7 +133,7 @@
 
     virtual std::vector<chrome::mojom::ApplicationDockMenuItemPtr>
     GetAppShortcutsMenuItemInfos(Profile* profile,
-                                 const web_app::AppId& app_id) = 0;
+                                 const webapps::AppId& app_id) = 0;
   };
 
   // Helper function to get the instance on the browser process. This will be
@@ -146,7 +147,7 @@
 
   // Get the host corresponding to a profile and app id, or null if there is
   // none.
-  AppShimHost* FindHost(Profile* profile, const web_app::AppId& app_id);
+  AppShimHost* FindHost(Profile* profile, const webapps::AppId& app_id);
 
   // If the specified |browser| should be using RemoteCocoa (because it is a
   // bookmark app), then get or create an AppShimHost for it, and return
@@ -170,7 +171,7 @@
 
   void UpdateAppBadge(
       Profile* profile,
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       const absl::optional<badging::BadgeManager::BadgeValue>& badge);
 
   // Called to connect to a MacNotificationProvider instance in the app shim
@@ -182,7 +183,7 @@
   // the future this will instead launch an app shim for `app_id` and connect
   // to that.
   mojo::Remote<mac_notifications::mojom::MacNotificationProvider>
-  LaunchNotificationProvider(const web_app::AppId& app_id);
+  LaunchNotificationProvider(const webapps::AppId& app_id);
 
   // AppShimHostBootstrap::Client:
   void OnShimProcessConnected(
@@ -260,7 +261,7 @@
   virtual Profile* ProfileForPath(const base::FilePath& path);
 
   // Return a profile to use for a background shim launch, virtual for tests.
-  virtual Profile* ProfileForBackgroundShimLaunch(const web_app::AppId& app_id);
+  virtual Profile* ProfileForBackgroundShimLaunch(const webapps::AppId& app_id);
 
   // Load a profile and call |callback| when completed or failed.
   virtual void LoadProfileAsync(const base::FilePath& path,
@@ -280,7 +281,7 @@
   virtual std::unique_ptr<AppShimHost> CreateHost(
       AppShimHost::Client* client,
       const base::FilePath& profile_path,
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       bool use_remote_cocoa);
 
   // Open the specified URL in a new Chrome window. This is the fallback when
@@ -347,7 +348,7 @@
     // will open exactly one window.
     bool HasFilesOrURLs() const;
 
-    web_app::AppId app_id;
+    webapps::AppId app_id;
     std::vector<base::FilePath> files;
     std::vector<GURL> urls;
     GURL override_url;
@@ -385,18 +386,18 @@
   // the result. The callback's arguments may be nullptr on failure.
   using LoadProfileAndAppCallback = base::OnceCallback<void(Profile*)>;
   void LoadProfileAndApp(const base::FilePath& profile_path,
-                         const web_app::AppId& app_id,
+                         const webapps::AppId& app_id,
                          LoadProfileAndAppCallback callback);
   void LoadProfileAndApp_OnProfileLoaded(const base::FilePath& profile_path,
-                                         const web_app::AppId& app_id,
+                                         const webapps::AppId& app_id,
                                          LoadProfileAndAppCallback callback,
                                          Profile* profile);
   void LoadProfileAndApp_OnProfileAppRegistryReady(
       const base::FilePath& profile_path,
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       LoadProfileAndAppCallback callback);
   void LoadProfileAndApp_OnAppEnabled(const base::FilePath& profile_path,
-                                      const web_app::AppId& app_id,
+                                      const webapps::AppId& app_id,
                                       LoadProfileAndAppCallback callback);
 
   // Update the profiles menu for the specified host.
@@ -411,10 +412,10 @@
   // Retrieve the ProfileState for a given (Profile, AppId) pair. If one
   // does not exist, create one.
   ProfileState* GetOrCreateProfileState(Profile* profile,
-                                        const web_app::AppId& app_id);
+                                        const webapps::AppId& app_id);
 
   void LaunchShimInBackgroundMode(
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceCallback<void(AppShimHost*)> callback);
 
   // Returns a mapping of profile paths to how many of the files and urls passed
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac_unittest.cc b/chrome/browser/apps/app_shim/app_shim_manager_mac_unittest.cc
index 901273a6..d9c32d4 100644
--- a/chrome/browser/apps/app_shim/app_shim_manager_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/app_shim_manager_mac_unittest.cc
@@ -144,7 +144,7 @@
 
   MOCK_METHOD1(ProfileForPath, Profile*(const base::FilePath&));
   MOCK_METHOD1(ProfileForBackgroundShimLaunch,
-               Profile*(const web_app::AppId& app_id));
+               Profile*(const webapps::AppId& app_id));
   void LoadProfileAsync(const base::FilePath& path,
                         base::OnceCallback<void(Profile*)> callback) override {
     CaptureLoadProfileCallback(path, std::move(callback));
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
index 533efb23..16bd1dd 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
@@ -84,7 +84,7 @@
 
 // Cancels the launch of the app for the given `app_id`, potentially resulting
 // in the app shim exiting.
-void CancelAppLaunch(Profile* profile, const web_app::AppId& app_id) {
+void CancelAppLaunch(Profile* profile, const webapps::AppId& app_id) {
   apps::AppShimManager::Get()->OnAppLaunchCancelled(profile, app_id);
 }
 
@@ -116,7 +116,7 @@
     bool remember_user_choice) {
   absl::optional<GURL> protocol_url = params.protocol_handler_launch_url;
   const bool is_file_launch = !file_launches.empty();
-  web_app::AppId app_id = params.app_id;
+  webapps::AppId app_id = params.app_id;
 
   auto persist_done = base::BindOnce(
       &OnPersistUserChoiceCompleted, std::move(params), file_launches, profile,
@@ -154,7 +154,7 @@
 WebAppShimManagerDelegate::~WebAppShimManagerDelegate() = default;
 
 bool WebAppShimManagerDelegate::ShowAppWindows(Profile* profile,
-                                               const AppId& app_id) {
+                                               const webapps::AppId& app_id) {
   if (UseFallback(profile, app_id))
     return fallback_delegate_->ShowAppWindows(profile, app_id);
   // Non-legacy app windows are handled in AppShimManager.
@@ -162,7 +162,7 @@
 }
 
 void WebAppShimManagerDelegate::CloseAppWindows(Profile* profile,
-                                                const AppId& app_id) {
+                                                const webapps::AppId& app_id) {
   if (UseFallback(profile, app_id)) {
     fallback_delegate_->CloseAppWindows(profile, app_id);
     return;
@@ -175,7 +175,7 @@
 }
 
 bool WebAppShimManagerDelegate::AppIsInstalled(Profile* profile,
-                                               const AppId& app_id) {
+                                               const webapps::AppId& app_id) {
   if (UseFallback(profile, app_id)) {
     return fallback_delegate_->AppIsInstalled(profile, app_id);
   }
@@ -185,15 +185,16 @@
 }
 
 bool WebAppShimManagerDelegate::AppCanCreateHost(Profile* profile,
-                                                 const AppId& app_id) {
+                                                 const webapps::AppId& app_id) {
   if (UseFallback(profile, app_id))
     return fallback_delegate_->AppCanCreateHost(profile, app_id);
   // A host is only created for use with RemoteCocoa.
   return AppUsesRemoteCocoa(profile, app_id);
 }
 
-bool WebAppShimManagerDelegate::AppUsesRemoteCocoa(Profile* profile,
-                                                   const AppId& app_id) {
+bool WebAppShimManagerDelegate::AppUsesRemoteCocoa(
+    Profile* profile,
+    const webapps::AppId& app_id) {
   if (UseFallback(profile, app_id))
     return fallback_delegate_->AppUsesRemoteCocoa(profile, app_id);
   // All PWAs, and bookmark apps that open in their own window (not in a browser
@@ -206,8 +207,9 @@
              web_app::DisplayMode::kBrowser;
 }
 
-bool WebAppShimManagerDelegate::AppIsMultiProfile(Profile* profile,
-                                                  const AppId& app_id) {
+bool WebAppShimManagerDelegate::AppIsMultiProfile(
+    Profile* profile,
+    const webapps::AppId& app_id) {
   if (UseFallback(profile, app_id))
     return fallback_delegate_->AppIsMultiProfile(profile, app_id);
   // All PWAs and bookmark apps are multi-profile.
@@ -228,7 +230,7 @@
 
 void WebAppShimManagerDelegate::LaunchApp(
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<base::FilePath>& files,
     const std::vector<GURL>& urls,
     const GURL& override_url,
@@ -362,7 +364,7 @@
 
 void WebAppShimManagerDelegate::LaunchShim(
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     web_app::LaunchShimUpdateBehavior update_behavior,
     web_app::ShimLaunchMode launch_mode,
     apps::ShimLaunchedCallback launched_callback,
@@ -389,8 +391,9 @@
   return false;
 }
 
-bool WebAppShimManagerDelegate::UseFallback(Profile* profile,
-                                            const AppId& app_id) const {
+bool WebAppShimManagerDelegate::UseFallback(
+    Profile* profile,
+    const webapps::AppId& app_id) const {
   if (!profile)
     return false;
 
@@ -406,8 +409,9 @@
 }
 
 std::vector<chrome::mojom::ApplicationDockMenuItemPtr>
-WebAppShimManagerDelegate::GetAppShortcutsMenuItemInfos(Profile* profile,
-                                                        const AppId& app_id) {
+WebAppShimManagerDelegate::GetAppShortcutsMenuItemInfos(
+    Profile* profile,
+    const webapps::AppId& app_id) {
   if (UseFallback(profile, app_id))
     return fallback_delegate_->GetAppShortcutsMenuItemInfos(profile, app_id);
 
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h
index fd6c4394..11415d6 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h
@@ -33,36 +33,40 @@
   WebAppShimManagerDelegate(
       std::unique_ptr<apps::AppShimManager::Delegate> fallback_delegate);
   ~WebAppShimManagerDelegate() override;
-  bool ShowAppWindows(Profile* profile, const AppId& app_id) override;
-  void CloseAppWindows(Profile* profile, const AppId& app_id) override;
-  bool AppIsInstalled(Profile* profile, const AppId& app_id) override;
-  bool AppCanCreateHost(Profile* profile, const AppId& app_id) override;
-  bool AppUsesRemoteCocoa(Profile* profile, const AppId& app_id) override;
-  bool AppIsMultiProfile(Profile* profile, const AppId& app_id) override;
+  bool ShowAppWindows(Profile* profile, const webapps::AppId& app_id) override;
+  void CloseAppWindows(Profile* profile, const webapps::AppId& app_id) override;
+  bool AppIsInstalled(Profile* profile, const webapps::AppId& app_id) override;
+  bool AppCanCreateHost(Profile* profile,
+                        const webapps::AppId& app_id) override;
+  bool AppUsesRemoteCocoa(Profile* profile,
+                          const webapps::AppId& app_id) override;
+  bool AppIsMultiProfile(Profile* profile,
+                         const webapps::AppId& app_id) override;
   void EnableExtension(Profile* profile,
                        const std::string& extension_id,
                        base::OnceCallback<void()> callback) override;
   void LaunchApp(
       Profile* profile,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<base::FilePath>& files,
       const std::vector<GURL>& urls,
       const GURL& override_url,
       chrome::mojom::AppShimLoginItemRestoreState login_item_restore_state,
       base::OnceClosure launch_finished_callback) override;
   void LaunchShim(Profile* profile,
-                  const AppId& app_id,
+                  const webapps::AppId& app_id,
                   web_app::LaunchShimUpdateBehavior update_behavior,
                   web_app::ShimLaunchMode launch_mode,
                   apps::ShimLaunchedCallback launched_callback,
                   apps::ShimTerminatedCallback terminated_callback) override;
   bool HasNonBookmarkAppWindowsOpen() override;
   std::vector<chrome::mojom::ApplicationDockMenuItemPtr>
-  GetAppShortcutsMenuItemInfos(Profile* profile, const AppId& app_id) override;
+  GetAppShortcutsMenuItemInfos(Profile* profile,
+                               const webapps::AppId& app_id) override;
 
  private:
   // Return true if |fallback_delegate_| should be used instead of |this|.
-  bool UseFallback(Profile* profile, const AppId& app_id) const;
+  bool UseFallback(Profile* profile, const webapps::AppId& app_id) const;
 
   // This is the delegate used by extension-based applications. When they are
   // removed, then this may be deleted.
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
index b720834..6b88fbe 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
@@ -180,10 +180,10 @@
               expected_results.protocol_handler_launch_url);
   }
 
-  const AppId& AppId() const { return app_id_; }
+  const webapps::AppId& AppId() const { return app_id_; }
 
  private:
-  web_app::AppId app_id_;
+  webapps::AppId app_id_;
 };
 
 TEST_F(WebAppShimManagerDelegateTest, LaunchApp) {
@@ -486,7 +486,7 @@
     shortcut_info3.url = GURL("https://anothersite.com");
     web_app_info->shortcuts_menu_item_infos.push_back(shortcut_info3);
 
-    web_app::AppId shortcut_app_id =
+    webapps::AppId shortcut_app_id =
         web_app::test::InstallWebApp(profile(), std::move(web_app_info));
     auto shortcut_menu_items =
         shim_manager.GetAppShortcutsMenuItemInfos(profile(), shortcut_app_id);
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc b/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc
index 3354e28..15d51cde 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc
@@ -45,7 +45,7 @@
                         int64_t position,
                         int64_t length) {
     BlobReader::Read(
-        browser_context_, blob_uuid_,
+        browser_context_->GetBlobRemote(blob_uuid_),
         base::BindOnce(&BlobMediaDataSource::OnBlobReaderDone,
                        weak_factory_.GetWeakPtr(), std::move(callback)),
         position, length);
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
index dc3ba0c..3ddb72c 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
@@ -659,7 +659,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   BlobReader::Read(
-      browser_context(), blob_uuid,
+      browser_context()->GetBlobRemote(blob_uuid),
       base::BindOnce(&MediaGalleriesGetMetadataFunction::GetMetadata, this,
                      metadata_type, blob_uuid),
       0, net::kMaxBytesToSniff);
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 7d43106c..e472889 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -1890,6 +1890,8 @@
     "login/screens/network_screen.h",
     "login/screens/offline_login_screen.cc",
     "login/screens/offline_login_screen.h",
+    "login/screens/online_authentication_screen.cc",
+    "login/screens/online_authentication_screen.h",
     "login/screens/os_install_screen.cc",
     "login/screens/os_install_screen.h",
     "login/screens/os_trial_screen.cc",
@@ -4037,6 +4039,7 @@
     "//chromeos/ash/components/scalable_iph:constants",
     "//chromeos/ash/components/scalable_iph:iph_session",
     "//chromeos/ash/components/scalable_iph:logger",
+    "//chromeos/ash/components/scalable_iph:scalable_iph",
     "//chromeos/ash/components/scalable_iph:scalable_iph_delegate",
     "//chromeos/ash/components/standalone_browser",
     "//chromeos/ash/components/sync_wifi",
diff --git a/chrome/browser/ash/app_list/app_sync_ui_state.cc b/chrome/browser/ash/app_list/app_sync_ui_state.cc
index 44fe5a8..a175274 100644
--- a/chrome/browser/ash/app_list/app_sync_ui_state.cc
+++ b/chrome/browser/ash/app_list/app_sync_ui_state.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/sync/sync_service_factory.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/service/sync_service.h"
-#include "components/sync/service/sync_user_settings.h"
 #include "components/user_manager/user_manager.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
@@ -119,8 +118,7 @@
 }
 
 void AppSyncUIState::CheckAppSync() {
-  if (!sync_service_ ||
-      !sync_service_->GetUserSettings()->IsInitialSyncFeatureSetupComplete()) {
+  if (!sync_service_ || !sync_service_->IsSyncFeatureEnabled()) {
     return;
   }
 
diff --git a/chrome/browser/ash/events/event_rewriter_delegate_impl.cc b/chrome/browser/ash/events/event_rewriter_delegate_impl.cc
index 828a4e5..6191e9dc 100644
--- a/chrome/browser/ash/events/event_rewriter_delegate_impl.cc
+++ b/chrome/browser/ash/events/event_rewriter_delegate_impl.cc
@@ -303,4 +303,24 @@
                                              active_modifier, device_id);
 }
 
+absl::optional<ui::mojom::ExtendedFkeysModifier>
+EventRewriterDelegateImpl::GetExtendedFkeySetting(int device_id,
+                                                  ui::KeyboardCode key_code) {
+  CHECK(key_code == ui::KeyboardCode::VKEY_F11 ||
+        key_code == ui::KeyboardCode::VKEY_F12);
+
+  const mojom::KeyboardSettings* settings =
+      input_device_settings_controller_->GetKeyboardSettings(device_id);
+
+  if (!settings) {
+    return absl::nullopt;
+  }
+
+  CHECK(settings->f11.has_value() && settings->f12.has_value());
+  if (key_code == ui::KeyboardCode::VKEY_F11) {
+    return settings->f11;
+  }
+  return settings->f12;
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/events/event_rewriter_delegate_impl.h b/chrome/browser/ash/events/event_rewriter_delegate_impl.h
index 2a17cae4..7c8efbe 100644
--- a/chrome/browser/ash/events/event_rewriter_delegate_impl.h
+++ b/chrome/browser/ash/events/event_rewriter_delegate_impl.h
@@ -8,6 +8,7 @@
 #include "ash/public/cpp/input_device_settings_controller.h"
 #include "base/memory/raw_ptr.h"
 #include "ui/events/ash/event_rewriter_ash.h"
+#include "ui/events/ash/mojom/extended_fkeys_modifier.mojom-shared.h"
 #include "ui/events/ash/mojom/simulate_right_click_modifier.mojom-shared.h"
 #include "ui/events/ash/mojom/six_pack_shortcut_modifier.mojom-shared.h"
 #include "ui/wm/public/activation_client.h"
@@ -72,6 +73,10 @@
       ui::mojom::SixPackShortcutModifier active_modifier,
       int device_id) override;
 
+  absl::optional<ui::mojom::ExtendedFkeysModifier> GetExtendedFkeySetting(
+      int device_id,
+      ui::KeyboardCode key_code) override;
+
  private:
   PrefService* GetPrefService() const;
 
diff --git a/chrome/browser/ash/events/event_rewriter_unittest.cc b/chrome/browser/ash/events/event_rewriter_unittest.cc
index 44c5417..e5ca52ab 100644
--- a/chrome/browser/ash/events/event_rewriter_unittest.cc
+++ b/chrome/browser/ash/events/event_rewriter_unittest.cc
@@ -43,6 +43,7 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/events/ash/event_rewriter_ash.h"
 #include "ui/events/ash/keyboard_capability.h"
+#include "ui/events/ash/mojom/extended_fkeys_modifier.mojom-shared.h"
 #include "ui/events/ash/mojom/modifier_key.mojom-shared.h"
 #include "ui/events/ash/mojom/modifier_key.mojom.h"
 #include "ui/events/ash/mojom/simulate_right_click_modifier.mojom-shared.h"
@@ -5445,6 +5446,12 @@
       ui::mojom::SixPackShortcutModifier active_modifier,
       int device_id) override {}
 
+  absl::optional<ui::mojom::ExtendedFkeysModifier> GetExtendedFkeySetting(
+      int device_id,
+      ui::KeyboardCode key_code) override {
+    return absl::nullopt;
+  }
+
   std::map<std::string, ui::mojom::ModifierKey> modifier_remapping_;
   base::flat_set<ui::Accelerator> registered_extension_shortcuts_;
 };
@@ -6000,6 +6007,115 @@
   });
 }
 
+class EventRewriterExtendedFkeysTest : public EventRewriterTest {
+ public:
+  void SetUp() override {
+    EventRewriterTest::SetUp();
+    scoped_feature_list_.InitWithFeatures(
+        {ash::features::kInputDeviceSettingsSplit,
+         ::features::kSupportF11AndF12KeyShortcuts},
+        {});
+  }
+};
+
+TEST_F(EventRewriterExtendedFkeysTest, TestRewriteExtendedFkeys) {
+  Preferences::RegisterProfilePrefs(prefs()->registry());
+  mojom::KeyboardSettings settings;
+  settings.f11 = ui::mojom::ExtendedFkeysModifier::kAlt;
+  settings.f12 = ui::mojom::ExtendedFkeysModifier::kShift;
+  settings.top_row_are_fkeys = true;
+
+  EXPECT_CALL(*input_device_settings_controller_mock_,
+              GetKeyboardSettings(kKeyboardDeviceId))
+      .WillRepeatedly(testing::Return(&settings));
+  TestInternalChromeKeyboard({
+      // Alt+F1 -> F11
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F1, ui::DomCode::F1, ui::EF_ALT_DOWN, ui::DomKey::F1},
+       {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11}},
+      // Shift+F2 -> F12
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F2, ui::DomCode::F2, ui::EF_SHIFT_DOWN, ui::DomKey::F2},
+       {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12}},
+  });
+
+  settings.f11 = ui::mojom::ExtendedFkeysModifier::kCtrlShift;
+  settings.f12 = ui::mojom::ExtendedFkeysModifier::kAlt;
+
+  TestInternalChromeKeyboard({
+      // Ctrl+Shift+F1 -> F11
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F1, ui::DomCode::F1, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
+        ui::DomKey::F1},
+       {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11}},
+      // Alt+F2 -> F12
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F2, ui::DomCode::F2, ui::EF_ALT_DOWN, ui::DomKey::F2},
+       {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12}},
+  });
+}
+
+TEST_F(EventRewriterExtendedFkeysTest,
+       TestRewriteExtendedFkeysBlockedBySetting) {
+  Preferences::RegisterProfilePrefs(prefs()->registry());
+  mojom::KeyboardSettings settings;
+  settings.f11 = ui::mojom::ExtendedFkeysModifier::kDisabled;
+  settings.f12 = ui::mojom::ExtendedFkeysModifier::kDisabled;
+  settings.top_row_are_fkeys = true;
+
+  EXPECT_CALL(*input_device_settings_controller_mock_,
+              GetKeyboardSettings(kKeyboardDeviceId))
+      .WillRepeatedly(testing::Return(&settings));
+  TestInternalChromeKeyboard({{
+      ui::ET_KEY_PRESSED,
+      {ui::VKEY_F1, ui::DomCode::F1, ui::EF_ALT_DOWN, ui::DomKey::F1},
+      {ui::VKEY_F1, ui::DomCode::F1, ui::EF_ALT_DOWN, ui::DomKey::F1},
+  }});
+}
+
+TEST_F(EventRewriterExtendedFkeysTest, TestRewriteExtendedFkeysTopRowAreFkeys) {
+  Preferences::RegisterProfilePrefs(prefs()->registry());
+  mojom::KeyboardSettings settings;
+  settings.f11 = ui::mojom::ExtendedFkeysModifier::kAlt;
+  settings.f12 = ui::mojom::ExtendedFkeysModifier::kShift;
+  settings.top_row_are_fkeys = true;
+
+  EXPECT_CALL(*input_device_settings_controller_mock_,
+              GetKeyboardSettings(kKeyboardDeviceId))
+      .WillRepeatedly(testing::Return(&settings));
+  TestInternalChromeKeyboard({
+      // Alt+F1 -> F11
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F1, ui::DomCode::F1, ui::EF_ALT_DOWN, ui::DomKey::F1},
+       {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11}},
+      // Ctrl+Alt+Shift+F1 -> Ctrl+Shift+F11
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F1, ui::DomCode::F1,
+        ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN,
+        ui::DomKey::F1},
+       {ui::VKEY_F11, ui::DomCode::F11, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN,
+        ui::DomKey::F11}},
+      // Shift+F2 -> F12
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F2, ui::DomCode::F2, ui::EF_SHIFT_DOWN, ui::DomKey::F2},
+       {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12}},
+  });
+
+  settings.top_row_are_fkeys = false;
+  TestInternalChromeKeyboard({
+      // Search+Alt+F1 -> F11
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F1, ui::DomCode::F1, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN,
+        ui::DomKey::F1},
+       {ui::VKEY_F11, ui::DomCode::F11, ui::EF_NONE, ui::DomKey::F11}},
+      // Search+Shift+F2 -> F12
+      {ui::ET_KEY_PRESSED,
+       {ui::VKEY_F2, ui::DomCode::F2, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN,
+        ui::DomKey::F2},
+       {ui::VKEY_F12, ui::DomCode::F12, ui::EF_NONE, ui::DomKey::F12}},
+  });
+}
+
 class EventRewriterSettingsSplitTest : public EventRewriterTest {
  public:
   void SetUp() override {
@@ -6243,6 +6359,12 @@
       ui::mojom::SixPackShortcutModifier blocked_modifier,
       ui::mojom::SixPackShortcutModifier active_modifier,
       int device_id) override {}
+
+  absl::optional<ui::mojom::ExtendedFkeysModifier> GetExtendedFkeySetting(
+      int device_id,
+      ui::KeyboardCode key_code) override {
+    return absl::nullopt;
+  }
 };
 
 TEST_F(EventRewriterRemapToRightClickTest, AltClickRemappedToRightClick) {
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_media_parser.cc b/chrome/browser/ash/extensions/file_manager/private_api_media_parser.cc
index 9b6eebe3..55bd952 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_media_parser.cc
+++ b/chrome/browser/ash/extensions/file_manager/private_api_media_parser.cc
@@ -54,7 +54,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   BlobReader::Read(  // Read net::kMaxBytesToSniff bytes from the front.
-      browser_context(), blob_uuid,
+      browser_context()->GetBlobRemote(blob_uuid),
       base::BindOnce(
           &FileManagerPrivateInternalGetContentMimeTypeFunction::SniffMimeType,
           this, blob_uuid),
@@ -108,7 +108,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   BlobReader::Read(  // Read net::kMaxBytesToSniff bytes from the front.
-      browser_context(), blob_uuid,
+      browser_context()->GetBlobRemote(blob_uuid),
       base::BindOnce(
           &FileManagerPrivateInternalGetContentMetadataFunction::CanParseBlob,
           this, blob_uuid, mime_type, include_images),
diff --git a/chrome/browser/ash/login/debug_overlay_browsertest.cc b/chrome/browser/ash/login/debug_overlay_browsertest.cc
index 7247eb7..a0f3847 100644
--- a/chrome/browser/ash/login/debug_overlay_browsertest.cc
+++ b/chrome/browser/ash/login/debug_overlay_browsertest.cc
@@ -21,8 +21,8 @@
 constexpr char kDebugOverlay[] = "debuggerOverlay";
 constexpr char kScreensPanel[] = "DebuggerPanelScreens";
 
-constexpr int kOobeScreensCount = 51;
-constexpr int kLoginScreensCount = 47;
+constexpr int kOobeScreensCount = 52;
+constexpr int kLoginScreensCount = 48;
 constexpr int kOsInstallScreensCount = 2;
 
 std::string ElementsInPanel(const std::string& panel) {
diff --git a/chrome/browser/ash/login/screens/online_authentication_screen.cc b/chrome/browser/ash/login/screens/online_authentication_screen.cc
new file mode 100644
index 0000000..5d0c29d
--- /dev/null
+++ b/chrome/browser/ash/login/screens/online_authentication_screen.cc
@@ -0,0 +1,57 @@
+// Copyright 2023 The Chromium Authors
+// 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/screens/online_authentication_screen.h"
+
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h"
+
+namespace ash {
+namespace {
+
+constexpr char kUserActionBack[] = "back";
+
+}  // namespace
+
+// static
+std::string OnlineAuthenticationScreen::GetResultString(Result result) {
+  switch (result) {
+    case Result::BACK:
+      return "Back";
+  }
+}
+
+OnlineAuthenticationScreen::OnlineAuthenticationScreen(
+    base::WeakPtr<OnlineAuthenticationScreenView> view,
+    const ScreenExitCallback& exit_callback)
+    : BaseScreen(OnlineAuthenticationScreenView::kScreenId,
+                 OobeScreenPriority::DEFAULT),
+      view_(std::move(view)),
+      exit_callback_(exit_callback) {}
+
+OnlineAuthenticationScreen::~OnlineAuthenticationScreen() = default;
+
+void OnlineAuthenticationScreen::ShowImpl() {
+  if (!view_) {
+    return;
+  }
+
+  view_->Show();
+}
+
+void OnlineAuthenticationScreen::HideImpl() {
+  view_->Hide();
+}
+
+void OnlineAuthenticationScreen::OnUserAction(const base::Value::List& args) {
+  const std::string& action_id = args[0].GetString();
+  if (action_id == kUserActionBack) {
+    exit_callback_.Run(Result::BACK);
+  } else {
+    BaseScreen::OnUserAction(args);
+  }
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/login/screens/online_authentication_screen.h b/chrome/browser/ash/login/screens/online_authentication_screen.h
new file mode 100644
index 0000000..5b9c2c3
--- /dev/null
+++ b/chrome/browser/ash/login/screens/online_authentication_screen.h
@@ -0,0 +1,53 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_LOGIN_SCREENS_ONLINE_AUTHENTICATION_SCREEN_H_
+#define CHROME_BROWSER_ASH_LOGIN_SCREENS_ONLINE_AUTHENTICATION_SCREEN_H_
+
+#include <string>
+
+#include "base/functional/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/ash/login/screens/base_screen.h"
+
+namespace ash {
+
+class OnlineAuthenticationScreenView;
+
+class OnlineAuthenticationScreen : public BaseScreen {
+ public:
+  using TView = OnlineAuthenticationScreenView;
+
+  enum class Result {
+    BACK,
+  };
+
+  static std::string GetResultString(Result result);
+
+  using ScreenExitCallback = base::RepeatingCallback<void(Result result)>;
+
+  OnlineAuthenticationScreen(base::WeakPtr<OnlineAuthenticationScreenView> view,
+                             const ScreenExitCallback& exit_callback);
+
+  OnlineAuthenticationScreen(const OnlineAuthenticationScreen&) = delete;
+  OnlineAuthenticationScreen& operator=(const OnlineAuthenticationScreen&) =
+      delete;
+
+  ~OnlineAuthenticationScreen() override;
+
+ private:
+  void ShowImpl() override;
+  void HideImpl() override;
+  void OnUserAction(const base::Value::List& args) override;
+
+  base::WeakPtr<OnlineAuthenticationScreenView> view_;
+  ScreenExitCallback exit_callback_;
+
+  base::WeakPtrFactory<OnlineAuthenticationScreen> weak_ptr_factory_{this};
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_ONLINE_AUTHENTICATION_SCREEN_H_
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc
index 0a6f4003..bfe9668 100644
--- a/chrome/browser/ash/login/wizard_controller.cc
+++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -96,6 +96,7 @@
 #include "chrome/browser/ash/login/screens/network_error.h"
 #include "chrome/browser/ash/login/screens/network_screen.h"
 #include "chrome/browser/ash/login/screens/offline_login_screen.h"
+#include "chrome/browser/ash/login/screens/online_authentication_screen.h"
 #include "chrome/browser/ash/login/screens/packaged_license_screen.h"
 #include "chrome/browser/ash/login/screens/password_selection_screen.h"
 #include "chrome/browser/ash/login/screens/pin_setup_screen.h"
@@ -181,6 +182,7 @@
 #include "chrome/browser/ui/webui/ash/login/multidevice_setup_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/network_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/offline_login_screen_handler.h"
+#include "chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/oobe_ui.h"
 #include "chrome/browser/ui/webui/ash/login/os_install_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/os_trial_screen_handler.h"
@@ -756,6 +758,11 @@
       base::BindRepeating(&WizardController::OnGaiaScreenExit,
                           weak_factory_.GetWeakPtr())));
 
+  append(std::make_unique<OnlineAuthenticationScreen>(
+      oobe_ui->GetView<OnlineAuthenticationScreenHandler>()->AsWeakPtr(),
+      base::BindRepeating(&WizardController::OnOnlineAuthenticationScreenExit,
+                          weak_factory_.GetWeakPtr())));
+
   append(std::make_unique<UserAllowlistCheckScreen>(
       oobe_ui->GetView<UserAllowlistCheckScreenHandler>()->AsWeakPtr(),
       base::BindRepeating(&WizardController::OnUserAllowlistCheckScreenExit,
@@ -1421,6 +1428,9 @@
   AdvanceToScreen(GaiaView::kScreenId);
 }
 
+void WizardController::OnOnlineAuthenticationScreenExit(
+    OnlineAuthenticationScreen::Result result) {}
+
 void WizardController::OnGaiaInfoScreenExit(GaiaInfoScreen::Result result) {
   OnScreenExit(GaiaInfoScreenView::kScreenId,
                GaiaInfoScreen::GetResultString(result));
diff --git a/chrome/browser/ash/login/wizard_controller.h b/chrome/browser/ash/login/wizard_controller.h
index 760b310..f97a78a 100644
--- a/chrome/browser/ash/login/wizard_controller.h
+++ b/chrome/browser/ash/login/wizard_controller.h
@@ -55,6 +55,7 @@
 #include "chrome/browser/ash/login/screens/multidevice_setup_screen.h"
 #include "chrome/browser/ash/login/screens/network_screen.h"
 #include "chrome/browser/ash/login/screens/offline_login_screen.h"
+#include "chrome/browser/ash/login/screens/online_authentication_screen.h"
 #include "chrome/browser/ash/login/screens/os_install_screen.h"
 #include "chrome/browser/ash/login/screens/os_trial_screen.h"
 #include "chrome/browser/ash/login/screens/packaged_license_screen.h"
@@ -78,6 +79,7 @@
 #include "chrome/browser/ash/login/screens/welcome_screen.h"
 #include "chrome/browser/ash/policy/enrollment/auto_enrollment_controller.h"
 #include "chrome/browser/ash/policy/enrollment/enrollment_config.h"
+#include "chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/oobe_ui.h"
 #include "chrome/browser/ui/webui/ash/login/user_allowlist_check_screen_handler.h"
 #include "components/account_id/account_id.h"
@@ -412,6 +414,7 @@
   void OnOobeFlowFinished();
   void OnPackagedLicenseScreenExit(PackagedLicenseScreen::Result result);
   void OnFamilyLinkNoticeScreenExit(FamilyLinkNoticeScreen::Result result);
+  void OnOnlineAuthenticationScreenExit(OnlineAuthenticationScreen::Result);
   void OnUserAllowlistCheckScreenExit(UserAllowlistCheckScreen::Result);
   void OnTpmErrorScreenExit(TpmErrorScreen::Result result);
   void OnPasswordChangeLegacyScreenExit(
diff --git a/chrome/browser/ash/printing/cups_print_job_manager_impl.cc b/chrome/browser/ash/printing/cups_print_job_manager_impl.cc
index 2991b96..d10275c 100644
--- a/chrome/browser/ash/printing/cups_print_job_manager_impl.cc
+++ b/chrome/browser/ash/printing/cups_print_job_manager_impl.cc
@@ -35,7 +35,9 @@
 #include "chrome/browser/printing/print_job_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/scalable_iph/scalable_iph_factory.h"
 #include "chrome/grit/generated_resources.h"
+#include "chromeos/ash/components/scalable_iph/scalable_iph.h"
 #include "chromeos/printing/printing_constants.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -199,6 +201,14 @@
       return false;
     }
 
+    // Record print job with scalable IPH framework.
+    scalable_iph::ScalableIph* scalable_iph =
+        ScalableIphFactory::GetForBrowserContext(profile);
+    if (scalable_iph) {
+      scalable_iph->RecordEvent(
+          scalable_iph::ScalableIph::Event::kPrintJobCreated);
+    }
+
     // Create a new print job.
     auto cpj = std::make_unique<CupsPrintJob>(*printer, job_id, title,
                                               total_page_number, source,
diff --git a/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc b/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
index 2c31beb..0fbc9c2 100644
--- a/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
+++ b/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
@@ -20,6 +20,9 @@
 #include "chrome/browser/ash/login/lock/screen_locker_tester.h"
 #include "chrome/browser/ash/login/test/device_state_mixin.h"
 #include "chrome/browser/ash/login/wizard_controller.h"
+#include "chrome/browser/ash/printing/cups_print_job.h"
+#include "chrome/browser/ash/printing/cups_print_job_manager.h"
+#include "chrome/browser/ash/printing/cups_print_job_manager_factory.h"
 #include "chrome/browser/ash/printing/synced_printers_manager.h"
 #include "chrome/browser/ash/printing/synced_printers_manager_factory.h"
 #include "chrome/browser/ash/scalable_iph/customizable_test_env_browser_test_base.h"
@@ -159,6 +162,35 @@
       app_list_model_updater_observation_{this};
 };
 
+class CupsPrintJobManagerWaiter : public ash::CupsPrintJobManager::Observer {
+ public:
+  CupsPrintJobManagerWaiter(ash::CupsPrintJobManager* print_job_manager,
+                            int job_id)
+      : print_job_manager_(print_job_manager), job_id_(job_id) {
+    CHECK(print_job_manager_);
+    print_job_manager_observation_.Observe(print_job_manager_);
+  }
+
+  void Wait() { run_loop_.Run(); }
+
+  void OnPrintJobCreated(base::WeakPtr<ash::CupsPrintJob> job) override {
+    if (job->job_id() == job_id_) {
+      CHECK(run_loop_.IsRunningOnCurrentThread())
+          << "Observed expected print job id before run_loop_ is running: "
+          << job_id_;
+      run_loop_.Quit();
+    }
+  }
+
+ private:
+  base::ScopedObservation<ash::CupsPrintJobManager,
+                          ash::CupsPrintJobManager::Observer>
+      print_job_manager_observation_{this};
+  raw_ptr<ash::CupsPrintJobManager> print_job_manager_;
+  base::RunLoop run_loop_;
+  int job_id_;
+};
+
 class ScalableIphBrowserTestDebugOff : public ScalableIphBrowserTest {
  public:
   ScalableIphBrowserTestDebugOff() { enable_scalable_iph_debug_ = false; }
@@ -725,6 +757,23 @@
                                ash::SystemWebAppType::PERSONALIZATION);
 }
 
+// TODO(b/301006258): Migrate to use observer pattern, then enable the test.
+IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTest, DISABLED_PrintJobCreated) {
+  EXPECT_CALL(*mock_tracker(),
+              NotifyEvent(scalable_iph::kEventNamePrintJobCreated));
+
+  ash::CupsPrintJobManager* print_job_manager =
+      ash::CupsPrintJobManagerFactory::GetForBrowserContext(
+          browser()->profile());
+  CupsPrintJobManagerWaiter print_job_manager_waiter(print_job_manager,
+                                                     /*job_id=*/0);
+  print_job_manager->CreatePrintJob(
+      "test-printer-id", "title", /*job_id=*/0, /*total_page_number=*/1,
+      ::printing::PrintJob::Source::kPrintPreview, /*source_id=*/"",
+      ash::printing::proto::PrintSettings());
+  print_job_manager_waiter.Wait();
+}
+
 // Logging feature is on by default in `ScalableIphBrowserTest`.
 IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTest, Log) {
   constexpr char kTestFileNamePattern[] = "*scalable_iph_browsertest.cc*";
diff --git a/chrome/browser/badging/badge_manager.cc b/chrome/browser/badging/badge_manager.cc
index 2de5f3a..5f6558b 100644
--- a/chrome/browser/badging/badge_manager.cc
+++ b/chrome/browser/badging/badge_manager.cc
@@ -41,7 +41,7 @@
 namespace {
 
 bool IsLastBadgingTimeWithin(base::TimeDelta time_frame,
-                             const web_app::AppId& app_id,
+                             const webapps::AppId& app_id,
                              const base::Clock* clock,
                              Profile* profile) {
   const base::Time last_badging_time =
@@ -137,7 +137,7 @@
 }
 
 absl::optional<BadgeManager::BadgeValue> BadgeManager::GetBadgeValue(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   const auto& it = badged_apps_.find(app_id);
   if (it == badged_apps_.end())
     return absl::nullopt;
@@ -145,12 +145,12 @@
   return it->second;
 }
 
-bool BadgeManager::HasRecentApiUsage(const web_app::AppId& app_id) const {
+bool BadgeManager::HasRecentApiUsage(const webapps::AppId& app_id) const {
   return IsLastBadgingTimeWithin(kBadgingOverrideLifetime, app_id, clock_,
                                  profile_);
 }
 
-void BadgeManager::SetBadgeForTesting(const web_app::AppId& app_id,
+void BadgeManager::SetBadgeForTesting(const webapps::AppId& app_id,
                                       BadgeValue value,
                                       ukm::UkmRecorder* test_recorder) {
   ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
@@ -166,7 +166,7 @@
   UpdateBadge(app_id, value);
 }
 
-void BadgeManager::ClearBadgeForTesting(const web_app::AppId& app_id,
+void BadgeManager::ClearBadgeForTesting(const webapps::AppId& app_id,
                                         ukm::UkmRecorder* test_recorder) {
   ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
   ukm::builders::Badging(source_id)
@@ -186,7 +186,7 @@
   sync_bridge_ = sync_bridge;
 }
 
-void BadgeManager::UpdateBadge(const web_app::AppId& app_id,
+void BadgeManager::UpdateBadge(const webapps::AppId& app_id,
                                absl::optional<BadgeValue> value) {
   if (sync_bridge_ &&
       !IsLastBadgingTimeWithin(badging::kBadgingMinimumUpdateInterval, app_id,
@@ -213,7 +213,7 @@
     return;
   }
 
-  const std::vector<std::tuple<web_app::AppId, GURL>> app_ids_and_urls =
+  const std::vector<std::tuple<webapps::AppId, GURL>> app_ids_and_urls =
       receivers_.current_context()->GetAppIdsAndUrlsForBadging();
 
   // Convert the mojo badge representation into a BadgeManager::BadgeValue.
@@ -244,7 +244,7 @@
 }
 
 void BadgeManager::ClearBadge() {
-  const std::vector<std::tuple<web_app::AppId, GURL>> app_ids_and_urls =
+  const std::vector<std::tuple<webapps::AppId, GURL>> app_ids_and_urls =
       receivers_.current_context()->GetAppIdsAndUrlsForBadging();
 
   ukm::UkmRecorder* recorder = ukm::UkmRecorder::Get();
@@ -261,44 +261,44 @@
   }
 }
 
-std::vector<std::tuple<web_app::AppId, GURL>>
+std::vector<std::tuple<webapps::AppId, GURL>>
 BadgeManager::FrameBindingContext::GetAppIdsAndUrlsForBadging() const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   content::RenderFrameHost* frame =
       content::RenderFrameHost::FromID(process_id_, frame_id_);
   if (!frame)
-    return std::vector<std::tuple<web_app::AppId, GURL>>{};
+    return std::vector<std::tuple<webapps::AppId, GURL>>{};
 
   const WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(
       Profile::FromBrowserContext(frame->GetBrowserContext()));
   if (!provider)
-    return std::vector<std::tuple<web_app::AppId, GURL>>{};
+    return std::vector<std::tuple<webapps::AppId, GURL>>{};
 
   const web_app::WebAppRegistrar& registrar = provider->registrar_unsafe();
-  const absl::optional<web_app::AppId> app_id =
+  const absl::optional<webapps::AppId> app_id =
       registrar.FindAppWithUrlInScope(frame->GetLastCommittedURL());
   if (!app_id)
-    return std::vector<std::tuple<web_app::AppId, GURL>>{};
-  return std::vector<std::tuple<web_app::AppId, GURL>>{std::make_tuple(
+    return std::vector<std::tuple<webapps::AppId, GURL>>{};
+  return std::vector<std::tuple<webapps::AppId, GURL>>{std::make_tuple(
       app_id.value(), registrar.GetAppStartUrl(app_id.value()))};
 }
 
-std::vector<std::tuple<web_app::AppId, GURL>>
+std::vector<std::tuple<webapps::AppId, GURL>>
 BadgeManager::ServiceWorkerBindingContext::GetAppIdsAndUrlsForBadging() const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   content::RenderProcessHost* render_process_host =
       content::RenderProcessHost::FromID(process_id_);
   if (!render_process_host)
-    return std::vector<std::tuple<web_app::AppId, GURL>>{};
+    return std::vector<std::tuple<webapps::AppId, GURL>>{};
 
   const WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(
       Profile::FromBrowserContext(render_process_host->GetBrowserContext()));
   if (!provider)
-    return std::vector<std::tuple<web_app::AppId, GURL>>{};
+    return std::vector<std::tuple<webapps::AppId, GURL>>{};
 
   const web_app::WebAppRegistrar& registrar = provider->registrar_unsafe();
-  std::vector<std::tuple<web_app::AppId, GURL>> app_ids_urls{};
+  std::vector<std::tuple<webapps::AppId, GURL>> app_ids_urls{};
   for (const auto& app_id : registrar.FindAppsInScope(scope_)) {
     app_ids_urls.push_back(
         std::make_tuple(app_id, registrar.GetAppStartUrl(app_id)));
diff --git a/chrome/browser/badging/badge_manager.h b/chrome/browser/badging/badge_manager.h
index 47439f7..34f03d0 100644
--- a/chrome/browser/badging/badge_manager.h
+++ b/chrome/browser/badging/badge_manager.h
@@ -14,6 +14,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/service_worker_version_base_info.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -100,14 +101,14 @@
 
   // Gets the badge for |app_id|. This will be absl::nullopt if the app is not
   // badged.
-  absl::optional<BadgeValue> GetBadgeValue(const web_app::AppId& app_id);
+  absl::optional<BadgeValue> GetBadgeValue(const webapps::AppId& app_id);
 
-  bool HasRecentApiUsage(const web_app::AppId& app_id) const;
+  bool HasRecentApiUsage(const webapps::AppId& app_id) const;
 
-  void SetBadgeForTesting(const web_app::AppId& app_id,
+  void SetBadgeForTesting(const webapps::AppId& app_id,
                           BadgeValue value,
                           ukm::UkmRecorder* test_recorder);
-  void ClearBadgeForTesting(const web_app::AppId& app_id,
+  void ClearBadgeForTesting(const webapps::AppId& app_id,
                             ukm::UkmRecorder* test_recorder);
   const base::Clock* SetClockForTesting(const base::Clock* clock);
   void SetSyncBridgeForTesting(web_app::WebAppSyncBridge* sync_bridge);
@@ -128,7 +129,7 @@
     // Gets the list of app IDs to badge, based on the state of this
     // BindingContext.  Returns an empty list when no apps exist for this
     // BindingContext.
-    virtual std::vector<std::tuple<web_app::AppId, GURL>>
+    virtual std::vector<std::tuple<webapps::AppId, GURL>>
     GetAppIdsAndUrlsForBadging() const = 0;
   };
 
@@ -141,7 +142,7 @@
 
     // Returns the AppId that matches the frame's URL.  Returns either 0 or 1
     // AppIds.
-    std::vector<std::tuple<web_app::AppId, GURL>> GetAppIdsAndUrlsForBadging()
+    std::vector<std::tuple<webapps::AppId, GURL>> GetAppIdsAndUrlsForBadging()
         const override;
 
    private:
@@ -158,7 +159,7 @@
 
     // Returns the list of AppIds within the service worker's scope. Returns
     // either 0, 1 or more AppIds.
-    std::vector<std::tuple<web_app::AppId, GURL>> GetAppIdsAndUrlsForBadging()
+    std::vector<std::tuple<webapps::AppId, GURL>> GetAppIdsAndUrlsForBadging()
         const override;
 
    private:
@@ -168,7 +169,7 @@
 
   // Updates the badge for |app_id| to be |value|, if it is not absl::nullopt.
   // If value is |absl::nullopt| then this clears the badge.
-  void UpdateBadge(const web_app::AppId& app_id,
+  void UpdateBadge(const webapps::AppId& app_id,
                    absl::optional<BadgeValue> value);
 
   // blink::mojom::BadgeService:
@@ -194,7 +195,7 @@
   std::unique_ptr<BadgeManagerDelegate> delegate_;
 
   // Maps app_id to badge contents.
-  std::map<web_app::AppId, BadgeValue> badged_apps_;
+  std::map<webapps::AppId, BadgeValue> badged_apps_;
 };
 
 // Determines the text to put on the badge based on some badge_content.
diff --git a/chrome/browser/badging/badge_manager_delegate.h b/chrome/browser/badging/badge_manager_delegate.h
index c441ccf6..6d192f2 100644
--- a/chrome/browser/badging/badge_manager_delegate.h
+++ b/chrome/browser/badging/badge_manager_delegate.h
@@ -8,6 +8,7 @@
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/badging/badge_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "url/gurl.h"
 
 class Profile;
@@ -27,7 +28,7 @@
   virtual ~BadgeManagerDelegate() = default;
 
   // Called when the badge for |app_id| has changed.
-  virtual void OnAppBadgeUpdated(const web_app::AppId& app_id) = 0;
+  virtual void OnAppBadgeUpdated(const webapps::AppId& app_id) = 0;
 
  protected:
   Profile* profile() { return profile_; }
diff --git a/chrome/browser/badging/badge_manager_delegate_mac.cc b/chrome/browser/badging/badge_manager_delegate_mac.cc
index c70eebc..1adf184 100644
--- a/chrome/browser/badging/badge_manager_delegate_mac.cc
+++ b/chrome/browser/badging/badge_manager_delegate_mac.cc
@@ -13,7 +13,7 @@
                                                  BadgeManager* badge_manager)
     : BadgeManagerDelegate(profile, badge_manager) {}
 
-void BadgeManagerDelegateMac::OnAppBadgeUpdated(const web_app::AppId& app_id) {
+void BadgeManagerDelegateMac::OnAppBadgeUpdated(const webapps::AppId& app_id) {
   const absl::optional<BadgeManager::BadgeValue>& badge =
       badge_manager()->GetBadgeValue(app_id);
 
diff --git a/chrome/browser/badging/badge_manager_delegate_mac.h b/chrome/browser/badging/badge_manager_delegate_mac.h
index 0e9c32b..bbf368e 100644
--- a/chrome/browser/badging/badge_manager_delegate_mac.h
+++ b/chrome/browser/badging/badge_manager_delegate_mac.h
@@ -19,7 +19,7 @@
   explicit BadgeManagerDelegateMac(Profile* profile,
                                    BadgeManager* badge_manager);
 
-  void OnAppBadgeUpdated(const web_app::AppId& app_id) override;
+  void OnAppBadgeUpdated(const webapps::AppId& app_id) override;
 };
 
 }  // namespace badging
diff --git a/chrome/browser/badging/badge_manager_delegate_win.cc b/chrome/browser/badging/badge_manager_delegate_win.cc
index 05891ce..81b28bd8 100644
--- a/chrome/browser/badging/badge_manager_delegate_win.cc
+++ b/chrome/browser/badging/badge_manager_delegate_win.cc
@@ -65,7 +65,7 @@
                                                  BadgeManager* badge_manager)
     : BadgeManagerDelegate(profile, badge_manager) {}
 
-void BadgeManagerDelegateWin::OnAppBadgeUpdated(const web_app::AppId& app_id) {
+void BadgeManagerDelegateWin::OnAppBadgeUpdated(const webapps::AppId& app_id) {
   const auto& content_and_alt =
       GetBadgeContentAndAlt(badge_manager()->GetBadgeValue(app_id));
 
diff --git a/chrome/browser/badging/badge_manager_delegate_win.h b/chrome/browser/badging/badge_manager_delegate_win.h
index c1c8e794..38d31b9 100644
--- a/chrome/browser/badging/badge_manager_delegate_win.h
+++ b/chrome/browser/badging/badge_manager_delegate_win.h
@@ -22,7 +22,7 @@
   explicit BadgeManagerDelegateWin(Profile* profile,
                                    BadgeManager* badge_manager);
 
-  void OnAppBadgeUpdated(const web_app::AppId& app_id) override;
+  void OnAppBadgeUpdated(const webapps::AppId& app_id) override;
 
  private:
   // Determines if a browser is for a specific hosted app, on this profile.
diff --git a/chrome/browser/badging/badge_manager_unittest.cc b/chrome/browser/badging/badge_manager_unittest.cc
index b403ffe0..f9106f3 100644
--- a/chrome/browser/badging/badge_manager_unittest.cc
+++ b/chrome/browser/badging/badge_manager_unittest.cc
@@ -17,11 +17,11 @@
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/ukm/test_ukm_recorder.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_task_environment.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
@@ -39,7 +39,7 @@
 typedef std::pair<GURL, absl::optional<int>> SetBadgeAction;
 
 constexpr uint64_t kBadgeContents = 1;
-const web_app::AppId kAppId = "1";
+const webapps::AppId kAppId = "1";
 
 class TestBadgeManager : public BadgeManager {
  public:
@@ -134,14 +134,14 @@
 }
 
 TEST_F(BadgeManagerUnittest, SetBadgeForMultipleApps) {
-  const web_app::AppId kOtherAppId = "2";
+  const webapps::AppId kOtherAppId = "2";
   constexpr uint64_t kOtherContents = 2;
 
-  std::vector<web_app::AppId> updated_apps;
+  std::vector<webapps::AppId> updated_apps;
   web_app::WebAppTestRegistryObserverAdapter observer(
       &provider().registrar_unsafe());
   observer.SetWebAppLastBadgingTimeChangedDelegate(base::BindLambdaForTesting(
-      [&updated_apps](const web_app::AppId& app_id, const base::Time& time) {
+      [&updated_apps](const webapps::AppId& app_id, const base::Time& time) {
         updated_apps.push_back(app_id);
       }));
 
@@ -210,20 +210,20 @@
   auto* other_delegate = owned_other_delegate.get();
   other_badge_manager->SetDelegate(std::move(owned_other_delegate));
 
-  std::vector<web_app::AppId> updated_apps;
-  std::vector<web_app::AppId> other_updated_apps;
+  std::vector<webapps::AppId> updated_apps;
+  std::vector<webapps::AppId> other_updated_apps;
   web_app::WebAppTestRegistryObserverAdapter other_observer(
       &new_provider->registrar_unsafe());
   other_observer.SetWebAppLastBadgingTimeChangedDelegate(
       base::BindLambdaForTesting(
-          [&other_updated_apps](const web_app::AppId& app_id,
+          [&other_updated_apps](const webapps::AppId& app_id,
                                 const base::Time& time) {
             other_updated_apps.push_back(app_id);
           }));
   web_app::WebAppTestRegistryObserverAdapter observer(
       &provider().registrar_unsafe());
   observer.SetWebAppLastBadgingTimeChangedDelegate(base::BindLambdaForTesting(
-      [&updated_apps](const web_app::AppId& app_id, const base::Time& time) {
+      [&updated_apps](const webapps::AppId& app_id, const base::Time& time) {
         updated_apps.push_back(app_id);
       }));
 
diff --git a/chrome/browser/badging/test_badge_manager_delegate.cc b/chrome/browser/badging/test_badge_manager_delegate.cc
index 7e5ebc4f..6f626bd 100644
--- a/chrome/browser/badging/test_badge_manager_delegate.cc
+++ b/chrome/browser/badging/test_badge_manager_delegate.cc
@@ -22,7 +22,7 @@
   on_badge_changed_ = on_badge_changed;
 }
 
-void TestBadgeManagerDelegate::OnAppBadgeUpdated(const web_app::AppId& app_id) {
+void TestBadgeManagerDelegate::OnAppBadgeUpdated(const webapps::AppId& app_id) {
   const auto& value = badge_manager()->GetBadgeValue(app_id);
   if (!value)
     cleared_badges_.push_back(app_id);
diff --git a/chrome/browser/badging/test_badge_manager_delegate.h b/chrome/browser/badging/test_badge_manager_delegate.h
index ef51aba..85f4926 100644
--- a/chrome/browser/badging/test_badge_manager_delegate.h
+++ b/chrome/browser/badging/test_badge_manager_delegate.h
@@ -11,6 +11,7 @@
 #include "chrome/browser/badging/badge_manager.h"
 #include "chrome/browser/badging/badge_manager_delegate.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -18,7 +19,7 @@
 
 class BadgeManager;
 
-using AppBadge = std::pair<web_app::AppId, BadgeManager::BadgeValue>;
+using AppBadge = std::pair<webapps::AppId, BadgeManager::BadgeValue>;
 using ScopeBadge = std::pair<GURL, BadgeManager::BadgeValue>;
 
 // Testing delegate that records badge changes for apps.
@@ -33,18 +34,18 @@
   // Resets the lists of cleared and set badges.
   void ResetBadges();
 
-  std::vector<web_app::AppId> cleared_badges() { return cleared_badges_; }
+  std::vector<webapps::AppId> cleared_badges() { return cleared_badges_; }
   std::vector<AppBadge> set_badges() { return set_badges_; }
 
   // BadgeManagerDelegate:
-  void OnAppBadgeUpdated(const web_app::AppId& app_badge) override;
+  void OnAppBadgeUpdated(const webapps::AppId& app_badge) override;
 
  protected:
 
  private:
   base::RepeatingCallback<void()> on_badge_changed_;
 
-  std::vector<web_app::AppId> cleared_badges_;
+  std::vector<webapps::AppId> cleared_badges_;
   std::vector<AppBadge> set_badges_;
 };
 
diff --git a/chrome/browser/banners/app_banner_manager_desktop.cc b/chrome/browser/banners/app_banner_manager_desktop.cc
index fff429d5..e82ded84 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.cc
+++ b/chrome/browser/banners/app_banner_manager_desktop.cc
@@ -240,7 +240,7 @@
 
 bool AppBannerManagerDesktop::ShouldAllowWebAppReplacementInstall() {
   // Only allow replacement install if this specific app is already installed.
-  web_app::AppId app_id = web_app::GenerateAppIdFromManifest(manifest());
+  webapps::AppId app_id = web_app::GenerateAppIdFromManifest(manifest());
   if (!registrar().IsLocallyInstalled(app_id))
     return false;
 
@@ -265,8 +265,8 @@
 }
 
 void AppBannerManagerDesktop::OnWebAppInstalled(
-    const web_app::AppId& installed_app_id) {
-  absl::optional<web_app::AppId> app_id =
+    const webapps::AppId& installed_app_id) {
+  absl::optional<webapps::AppId> app_id =
       registrar().FindAppWithUrlInScope(validated_url_);
   if (app_id.has_value() && *app_id == installed_app_id &&
       registrar().GetAppUserDisplayMode(*app_id) ==
@@ -277,7 +277,7 @@
 }
 
 void AppBannerManagerDesktop::OnWebAppWillBeUninstalled(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   // WebAppTabHelper has a app_id but it is reset during
   // OnWebAppWillBeUninstalled so use IsUrlInAppScope() instead.
   if (registrar().IsUrlInAppScope(validated_url(), app_id))
@@ -285,7 +285,7 @@
 }
 
 void AppBannerManagerDesktop::OnWebAppUninstalled(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   if (uninstalling_app_id_ == app_id) {
     RecheckInstallabilityForLoadedPage();
@@ -308,7 +308,7 @@
 }
 
 void AppBannerManagerDesktop::DidFinishCreatingWebApp(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code) {
   content::WebContents* contents = web_contents();
   if (!contents)
@@ -330,7 +330,7 @@
 }
 
 void AppBannerManagerDesktop::DidCreateWebAppFromMLDialog(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code) {
   if (code == webapps::InstallResultCode::kSuccessNewInstall) {
     TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
diff --git a/chrome/browser/banners/app_banner_manager_desktop.h b/chrome/browser/banners/app_banner_manager_desktop.h
index bf1752c9..314a62e 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.h
+++ b/chrome/browser/banners/app_banner_manager_desktop.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/webapps/browser/banners/app_banner_manager.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents_user_data.h"
 
 namespace extensions {
@@ -71,7 +72,7 @@
   GetSegmentationPlatformService() override;
 
   // Called when the web app install initiated by a banner has completed.
-  virtual void DidFinishCreatingWebApp(const web_app::AppId& app_id,
+  virtual void DidFinishCreatingWebApp(const webapps::AppId& app_id,
                                        webapps::InstallResultCode code);
 
  private:
@@ -85,10 +86,10 @@
   void ShowBannerUi(WebappInstallSource install_source) override;
 
   // web_app::WebAppInstallManagerObserver:
-  void OnWebAppInstalled(const web_app::AppId& app_id) override;
-  void OnWebAppWillBeUninstalled(const web_app::AppId& app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& app_id) override;
+  void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) override;
   void OnWebAppUninstalled(
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
   void OnWebAppInstallManagerDestroyed() override;
 
@@ -96,13 +97,13 @@
                     web_app::WebAppInstalledCallback install_callback);
   // Catch only kSuccessNewInstall and kUserInstallDeclined user responses if
   // the dialog is triggered by ML.
-  void DidCreateWebAppFromMLDialog(const web_app::AppId& app_id,
+  void DidCreateWebAppFromMLDialog(const webapps::AppId& app_id,
                                    webapps::InstallResultCode code);
 
   raw_ptr<segmentation_platform::SegmentationPlatformService>
       segmentation_platform_service_;
   raw_ptr<extensions::ExtensionRegistry> extension_registry_;
-  web_app::AppId uninstalling_app_id_;
+  webapps::AppId uninstalling_app_id_;
 
   base::ScopedObservation<web_app::WebAppInstallManager,
                           web_app::WebAppInstallManagerObserver>
diff --git a/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc b/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc
index 58180f0..440f697 100644
--- a/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc
+++ b/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc
@@ -161,7 +161,7 @@
     bool callback_called = false;
 
     web_app::SetInstalledCallbackForTesting(
-        base::BindLambdaForTesting([&](const web_app::AppId& installed_app_id,
+        base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id,
                                        webapps::InstallResultCode code) {
           EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
           EXPECT_EQ(installed_app_id,
@@ -211,7 +211,7 @@
     bool callback_called = false;
 
     web_app::SetInstalledCallbackForTesting(
-        base::BindLambdaForTesting([&](const web_app::AppId& installed_app_id,
+        base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id,
                                        webapps::InstallResultCode code) {
           EXPECT_EQ(webapps::InstallResultCode::kWebContentsDestroyed, code);
           callback_called = true;
diff --git a/chrome/browser/banners/test_app_banner_manager_desktop.cc b/chrome/browser/banners/test_app_banner_manager_desktop.cc
index 29fb7ff..1dea3f73 100644
--- a/chrome/browser/banners/test_app_banner_manager_desktop.cc
+++ b/chrome/browser/banners/test_app_banner_manager_desktop.cc
@@ -163,7 +163,7 @@
 }
 
 void TestAppBannerManagerDesktop::DidFinishCreatingWebApp(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code) {
   AppBannerManagerDesktop::DidFinishCreatingWebApp(app_id, code);
   OnFinished();
diff --git a/chrome/browser/banners/test_app_banner_manager_desktop.h b/chrome/browser/banners/test_app_banner_manager_desktop.h
index 6d9d6c7..70ad60b 100644
--- a/chrome/browser/banners/test_app_banner_manager_desktop.h
+++ b/chrome/browser/banners/test_app_banner_manager_desktop.h
@@ -72,7 +72,7 @@
  protected:
   // AppBannerManager:
   void OnInstall(blink::mojom::DisplayMode display) override;
-  void DidFinishCreatingWebApp(const web_app::AppId& app_id,
+  void DidFinishCreatingWebApp(const webapps::AppId& app_id,
                                webapps::InstallResultCode code) override;
   void DidFinishLoad(content::RenderFrameHost* render_frame_host,
                      const GURL& validated_url) override;
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc
index f4a81c8..b7dd3cf5 100644
--- a/chrome/browser/browser_features.cc
+++ b/chrome/browser/browser_features.cc
@@ -214,6 +214,16 @@
 BASE_FEATURE(kLockProfileCookieDatabase,
              "LockProfileCookieDatabase",
              base::FEATURE_ENABLED_BY_DEFAULT);
+
+// Don't call the Win32 API PrefetchVirtualMemory when loading chrome.dll inside
+// non-browser processes. This is done by passing flags to these processes. This
+// prevents pulling the entirety of chrome.dll into physical memory (albeit only
+// pri-2 physical memory) under the assumption that during chrome execution,
+// portions of the DLL which are used will already be present, hopefully leading
+// to less needless memory consumption.
+BASE_FEATURE(kNoPreReadMainDll,
+             "NoPreReadMainDll",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 #endif
 
 // Enables showing the email of the flex org admin that setup CBCM in the
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h
index e449b49..9637e2c 100644
--- a/chrome/browser/browser_features.h
+++ b/chrome/browser/browser_features.h
@@ -70,6 +70,7 @@
 #if BUILDFLAG(IS_WIN)
 BASE_DECLARE_FEATURE(kAppBoundEncryptionMetrics);
 BASE_DECLARE_FEATURE(kLockProfileCookieDatabase);
+BASE_DECLARE_FEATURE(kNoPreReadMainDll);
 #endif
 
 BASE_DECLARE_FEATURE(kFlexOrgManagementDisclosure);
diff --git a/chrome/browser/browsing_data/browsing_data_lifetime_policy_handler.cc b/chrome/browser/browsing_data/browsing_data_lifetime_policy_handler.cc
index 0611af4..4956175 100644
--- a/chrome/browser/browsing_data/browsing_data_lifetime_policy_handler.cc
+++ b/chrome/browser/browsing_data/browsing_data_lifetime_policy_handler.cc
@@ -89,10 +89,9 @@
   SimpleSchemaValidatingPolicyHandler::ApplyPolicySettings(policies, prefs);
 
   if (browsing_data::IsPolicyDependencyEnabled()) {
-    std::string log_message;
-    browsing_data::DisableSyncTypes(forced_disabled_sync_types_, prefs,
-                                    policy_name(), log_message);
-    if (log_message != std::string()) {
+    std::string log_message = browsing_data::DisableSyncTypes(
+        forced_disabled_sync_types_, prefs, policy_name());
+    if (!log_message.empty()) {
       LOG_POLICY(INFO, POLICY_PROCESSING) << log_message;
     }
   }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 527fbd4..fb416f3 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -534,6 +534,7 @@
 #include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
 #include "chrome/grit/chrome_unscaled_resources.h"  // nogncheck crbug.com/1125897
 #include "components/commerce/core/commerce_feature_list.h"
+#include "components/media_effects/media_effects_manager_binder.h"
 #include "components/password_manager/content/common/web_ui_constants.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
@@ -2997,6 +2998,12 @@
   }
 #endif
 
+#if BUILDFLAG(IS_WIN)
+  if (base::FeatureList::IsEnabled(features::kNoPreReadMainDll)) {
+    command_line->AppendSwitch(switches::kNoPreReadMainDll);
+  }
+#endif
+
   ThreadProfilerConfiguration::Get()->AppendCommandLineSwitchForChildProcess(
       command_line);
 
@@ -8115,3 +8122,14 @@
 void ChromeContentBrowserClient::SetIsMinimalMode(bool minimal) {
   is_minimal_mode_ = minimal;
 }
+
+#if !BUILDFLAG(IS_ANDROID)
+void ChromeContentBrowserClient::BindVideoEffectsManager(
+    const std::string& device_id,
+    content::BrowserContext* browser_context,
+    mojo::PendingReceiver<video_capture::mojom::VideoEffectsManager>
+        video_effects_manager) {
+  media_effects::BindVideoEffectsManager(device_id, browser_context,
+                                         std::move(video_effects_manager));
+}
+#endif  // !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index f7d2397..d5258126 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -941,6 +941,14 @@
 
   void SetIsMinimalMode(bool minimal) override;
 
+#if !BUILDFLAG(IS_ANDROID)
+  void BindVideoEffectsManager(
+      const std::string& device_id,
+      content::BrowserContext* browser_context,
+      mojo::PendingReceiver<video_capture::mojom::VideoEffectsManager>
+          video_effects_manager) override;
+#endif  // !BUILDFLAG(IS_ANDROID)
+
  protected:
   static bool HandleWebUI(GURL* url, content::BrowserContext* browser_context);
   static bool HandleWebUIReverse(GURL* url,
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc
index 5bdef219..dfdf65e 100644
--- a/chrome/browser/chrome_content_browser_client_unittest.cc
+++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -68,6 +68,7 @@
 #include "url/origin.h"
 
 #if !BUILDFLAG(IS_ANDROID)
+#include "base/test/test_future.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -615,6 +616,23 @@
 
 #endif
 
+#if !BUILDFLAG(IS_ANDROID)
+TEST_F(ChromeContentBrowserClientTest, BindVideoEffectsManager) {
+  TestChromeContentBrowserClient test_content_browser_client;
+  mojo::Remote<video_capture::mojom::VideoEffectsManager> video_effects_manager;
+  test_content_browser_client.BindVideoEffectsManager(
+      "test_device_id", &profile_,
+      video_effects_manager.BindNewPipeAndPassReceiver());
+
+  base::test::TestFuture<video_capture::mojom::VideoEffectsConfigurationPtr>
+      configuration_future;
+  video_effects_manager->GetConfiguration(configuration_future.GetCallback());
+  // The actual value isn't that important here. What matters is that getting a
+  // result means that the plumbing worked.
+  EXPECT_FALSE(configuration_future.Get().is_null());
+}
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 #if BUILDFLAG(IS_CHROMEOS)
 class ChromeContentSettingsRedirectTest
     : public ChromeContentBrowserClientTest {
diff --git a/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/ImplicitPriceDropSubscriptionsManagerUnitTest.java b/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/ImplicitPriceDropSubscriptionsManagerUnitTest.java
index 3804a10..063cc99 100644
--- a/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/ImplicitPriceDropSubscriptionsManagerUnitTest.java
+++ b/chrome/browser/commerce/subscriptions/test/android/java/src/org/chromium/chrome/browser/subscriptions/ImplicitPriceDropSubscriptionsManagerUnitTest.java
@@ -27,13 +27,11 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.Callback;
-import org.chromium.base.UserDataHost;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabImpl;
 import org.chromium.chrome.browser.tab.TabSelectionType;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
@@ -105,10 +103,6 @@
     TabModelSelector mTabModelSelector;
     @Mock
     ShoppingService mShoppingService;
-    @Mock
-    CriticalPersistedTabData mCriticalPersistedTabData1;
-    @Mock
-    CriticalPersistedTabData mCriticalPersistedTabData2;
     @Captor
     ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor;
     @Captor
@@ -123,8 +117,8 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mTab1 = prepareTab(TAB1_ID, URL1, POSITION1, mCriticalPersistedTabData1);
-        mTab2 = prepareTab(TAB2_ID, URL2, POSITION2, mCriticalPersistedTabData2);
+        mTab1 = prepareTab(TAB1_ID, URL1, POSITION1);
+        mTab2 = prepareTab(TAB2_ID, URL2, POSITION2);
         // Mock that tab1 and tab2 are both stale tabs.
         long fakeTimestamp = System.currentTimeMillis()
                 - TimeUnit.SECONDS.toMillis(ShoppingPersistedTabData.getStaleTabThresholdSeconds())
@@ -157,8 +151,8 @@
 
     @Test
     public void testInitialSubscription_WithDuplicateURL() {
-        mTab1 = prepareTab(TAB1_ID, URL1, POSITION1, mCriticalPersistedTabData1);
-        mTab2 = prepareTab(TAB2_ID, URL1, POSITION2, mCriticalPersistedTabData2);
+        mTab1 = prepareTab(TAB1_ID, URL1, POSITION1);
+        mTab2 = prepareTab(TAB2_ID, URL1, POSITION2);
         long fakeTimestamp = System.currentTimeMillis()
                 - TimeUnit.SECONDS.toMillis(ShoppingPersistedTabData.getStaleTabThresholdSeconds())
                 + TimeUnit.DAYS.toMillis(7);
@@ -223,8 +217,8 @@
 
     @Test
     public void testUnsubscribe_NotUnique() {
-        mTab1 = prepareTab(TAB1_ID, URL1, POSITION1, mCriticalPersistedTabData1);
-        mTab2 = prepareTab(TAB2_ID, URL1, POSITION2, mCriticalPersistedTabData2);
+        mTab1 = prepareTab(TAB1_ID, URL1, POSITION1);
+        mTab2 = prepareTab(TAB2_ID, URL1, POSITION2);
         mImplicitSubscriptionsManager.setupForFetchOfferId(mTab1, mTab2, OFFER1_ID, OFFER2_ID);
 
         mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab1);
@@ -246,17 +240,13 @@
         verify(mTabModel).removeObserver(any(TabModelObserver.class));
     }
 
-    private TabImpl prepareTab(int id, String urlString, int position,
-            CriticalPersistedTabData criticalPersistedTabData) {
+    private TabImpl prepareTab(int id, String urlString, int position) {
         TabImpl tab = mock(TabImpl.class);
         doReturn(id).when(tab).getId();
         GURL gurl = new GURL(urlString);
         doReturn(gurl).when(tab).getUrl();
         doReturn(gurl).when(tab).getOriginalUrl();
         doReturn(tab).when(mTabModel).getTabAt(position);
-        UserDataHost userDataHost = new UserDataHost();
-        userDataHost.setUserData(CriticalPersistedTabData.class, criticalPersistedTabData);
-        doReturn(userDataHost).when(tab).getUserDataHost();
         return tab;
     }
 
diff --git a/chrome/browser/download/bubble/download_bubble_ui_controller_unittest.cc b/chrome/browser/download/bubble/download_bubble_ui_controller_unittest.cc
index c553e48b..bc716f0 100644
--- a/chrome/browser/download/bubble/download_bubble_ui_controller_unittest.cc
+++ b/chrome/browser/download/bubble/download_bubble_ui_controller_unittest.cc
@@ -97,7 +97,7 @@
 
   bool GetAllModelsToDisplay(
       std::vector<DownloadUIModelPtr>& models,
-      const web_app::AppId* web_app_id,
+      const webapps::AppId* web_app_id,
       bool force_backfill_download_items = true) override {
     models.clear();
     int download_item_index = 0, offline_item_index = 0;
@@ -127,7 +127,7 @@
 
   MOCK_METHOD(DownloadDisplay::ProgressInfo,
               GetProgressInfo,
-              (const web_app::AppId*),
+              (const webapps::AppId*),
               (const override));
 
  private:
@@ -263,6 +263,7 @@
         .WillRepeatedly(Return(creation_type));
     EXPECT_CALL(item(index), IsPaused()).WillRepeatedly(Return(false));
     EXPECT_CALL(item(index), IsDangerous()).WillRepeatedly(Return(false));
+    EXPECT_CALL(item(index), IsInsecure()).WillRepeatedly(Return(false));
     // Functions called when checking ShouldShowDownloadStartedAnimation().
     EXPECT_CALL(item(index), IsSavePackageDownload())
         .WillRepeatedly(Return(false));
diff --git a/chrome/browser/download/bubble/download_bubble_update_service.cc b/chrome/browser/download/bubble/download_bubble_update_service.cc
index 576166b1..4e6278a 100644
--- a/chrome/browser/download/bubble/download_bubble_update_service.cc
+++ b/chrome/browser/download/bubble/download_bubble_update_service.cc
@@ -263,7 +263,7 @@
 }
 
 DownloadBubbleUpdateService::CacheManager&
-DownloadBubbleUpdateService::GetCacheForWebApp(const web_app::AppId& app_id) {
+DownloadBubbleUpdateService::GetCacheForWebApp(const webapps::AppId& app_id) {
   auto it = web_app_caches_.find(app_id);
   if (it == web_app_caches_.end()) {
     // Create a new CacheManager for this |app_id|.
@@ -274,7 +274,7 @@
 
 const DownloadBubbleUpdateService::CacheManager*
 DownloadBubbleUpdateService::GetExistingCacheForWebApp(
-    const web_app::AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   if (auto it = web_app_caches_.find(app_id); it != web_app_caches_.end()) {
     return &it->second;
   }
@@ -460,7 +460,7 @@
 
 bool DownloadBubbleUpdateService::GetAllModelsToDisplay(
     std::vector<DownloadUIModelPtr>& models,
-    const web_app::AppId* web_app_id,
+    const webapps::AppId* web_app_id,
     bool force_backfill_download_items) {
   if (web_app_id == nullptr) {
     return main_cache_.GetAllModelsToDisplay(models,
@@ -476,7 +476,7 @@
 }
 
 const DownloadBubbleDisplayInfo& DownloadBubbleUpdateService::GetDisplayInfo(
-    const web_app::AppId* web_app_id) {
+    const webapps::AppId* web_app_id) {
   if (web_app_id == nullptr) {
     return main_cache_.GetDisplayInfo();
   }
@@ -575,7 +575,7 @@
 }
 
 ProgressInfo DownloadBubbleUpdateService::GetProgressInfo(
-    const web_app::AppId* web_app_id) const {
+    const webapps::AppId* web_app_id) const {
   if (web_app_id == nullptr) {
     return main_cache_.GetProgressInfo();
   }
diff --git a/chrome/browser/download/bubble/download_bubble_update_service.h b/chrome/browser/download/bubble/download_bubble_update_service.h
index 838e738..906e0125 100644
--- a/chrome/browser/download/bubble/download_bubble_update_service.h
+++ b/chrome/browser/download/bubble/download_bubble_update_service.h
@@ -16,11 +16,11 @@
 #include "chrome/browser/download/bubble/download_display_controller.h"
 #include "chrome/browser/download/download_ui_model.h"
 #include "chrome/browser/ui/download/download_display.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "components/download/content/public/all_download_item_notifier.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/offline_items_collection/core/offline_content_provider.h"
 #include "components/offline_items_collection/core/offline_item.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -83,7 +83,7 @@
   // testing.
   virtual bool GetAllModelsToDisplay(
       std::vector<DownloadUIModel::DownloadUIModelPtr>& models,
-      const web_app::AppId* web_app_id,
+      const webapps::AppId* web_app_id,
       bool force_backfill_download_items = false);
 
   // Returns information relevant to the display state of the download button.
@@ -93,7 +93,7 @@
   // missing items. May be slightly inaccurate in edge cases. Virtual for
   // testing.
   virtual const DownloadBubbleDisplayInfo& GetDisplayInfo(
-      const web_app::AppId* web_app_id);
+      const webapps::AppId* web_app_id);
 
   // Computes progress info based on in-progress downloads. If |web_app_id| is
   // non-null, the results are limited to downloads initiated by the specified
@@ -103,7 +103,7 @@
   // ok, as it is only for the purpose of showing a progress ring around the
   // icon, which is not precise anyway. Virtual for testing.
   virtual DownloadDisplay::ProgressInfo GetProgressInfo(
-      const web_app::AppId* web_app_id) const;
+      const webapps::AppId* web_app_id) const;
 
   // Notifies the appropriate browser windows that a download item was added.
   void NotifyWindowsOfDownloadItemAdded(download::DownloadItem* item);
@@ -379,11 +379,11 @@
  private:
   // Finds the appropriate CacheManager for a web app, creating one if it
   // doesn't exist.
-  CacheManager& GetCacheForWebApp(const web_app::AppId& app_id);
+  CacheManager& GetCacheForWebApp(const webapps::AppId& app_id);
   // As above, but does not create one if it doesn't exist (in which case it
   // returns nullptr).
   const CacheManager* GetExistingCacheForWebApp(
-      const web_app::AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
   // Finds the appropriate CacheManager for a download item, creating one if it
   // doesn't exist.
@@ -446,7 +446,7 @@
   CacheManager main_cache_;
 
   // A separate cache for each web app.
-  std::map<web_app::AppId, CacheManager> web_app_caches_;
+  std::map<webapps::AppId, CacheManager> web_app_caches_;
 
   // Observes the offline content provider.
   base::ScopedObservation<
diff --git a/chrome/browser/download/bubble/download_bubble_update_service_unittest.cc b/chrome/browser/download/bubble/download_bubble_update_service_unittest.cc
index 9228c1bf..40fb351 100644
--- a/chrome/browser/download/bubble/download_bubble_update_service_unittest.cc
+++ b/chrome/browser/download/bubble/download_bubble_update_service_unittest.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/download/download_ui_model.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile_key.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
@@ -26,6 +25,7 @@
 #include "components/offline_items_collection/core/offline_item_state.h"
 #include "components/offline_items_collection/core/test_support/mock_offline_content_provider.h"
 #include "components/safe_browsing/core/common/features.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/download_item_utils.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/mock_download_manager.h"
@@ -163,7 +163,7 @@
                         const std::string& guid,
                         bool is_paused,
                         base::Time start_time = base::Time::Now(),
-                        const web_app::AppId* web_app_id = nullptr,
+                        const webapps::AppId* web_app_id = nullptr,
                         bool is_crx = false,
                         bool observe = true) {
     InitDownloadItem(*download_manager_, *update_service_, download_items_,
@@ -180,7 +180,7 @@
       const std::string& guid,
       bool is_paused,
       base::Time start_time = base::Time::Now(),
-      const web_app::AppId* web_app_id = nullptr,
+      const webapps::AppId* web_app_id = nullptr,
       bool is_crx = false,
       bool observe = true) {
     size_t index = download_items.size();
@@ -704,8 +704,8 @@
 TEST_F(DownloadBubbleUpdateServiceTest, GetAllModelsToDisplayForWebApp) {
   base::Time now = base::Time::Now();
   base::Time before = now - base::Hours(1);
-  web_app::AppId app_a_id = "app_a";
-  web_app::AppId app_b_id = "app_b";
+  webapps::AppId app_a_id = "app_a";
+  webapps::AppId app_b_id = "app_b";
   InitDownloadItem(DownloadState::IN_PROGRESS, "app_a_download",
                    /*is_paused=*/false, now, &app_a_id);
   InitDownloadItem(DownloadState::IN_PROGRESS, "app_b_download",
@@ -757,8 +757,8 @@
 
 TEST_F(DownloadBubbleUpdateServiceTest, GetProgressInfoForWebApp) {
   base::Time now = base::Time::Now();
-  web_app::AppId app_a_id = "app_a";
-  web_app::AppId app_b_id = "app_b";
+  webapps::AppId app_a_id = "app_a";
+  webapps::AppId app_b_id = "app_b";
   InitDownloadItem(DownloadState::IN_PROGRESS, "app_a_download1",
                    /*is_paused=*/false, now, &app_a_id);
   InitDownloadItem(DownloadState::IN_PROGRESS, "app_a_download2",
@@ -817,8 +817,8 @@
 TEST_F(DownloadBubbleUpdateServiceTest, GetAllUIModelsInfoForWebApp) {
   base::Time now = base::Time::Now();
   base::Time two_hours_ago = now - base::Hours(2);
-  web_app::AppId app_a_id = "app_a";
-  web_app::AppId app_b_id = "app_b";
+  webapps::AppId app_a_id = "app_a";
+  webapps::AppId app_b_id = "app_b";
   InitDownloadItem(DownloadState::IN_PROGRESS, "non_app_download",
                    /*is_paused=*/false, now);
   InitOfflineItems({OfflineItemState::PAUSED, OfflineItemState::PAUSED},
@@ -846,7 +846,7 @@
 TEST_F(DownloadBubbleUpdateServiceTest,
        DownloadUpdatedWithWebAppDataAfterCreation) {
   base::Time now = base::Time::Now();
-  web_app::AppId app_id = "app";
+  webapps::AppId app_id = "app";
   // This simulates the restoration of a web app download from the history
   // database, during which the item is created first without the
   // DownloadItemWebAppData, and then subsequently tagged with the data.
diff --git a/chrome/browser/download/bubble/download_bubble_utils.cc b/chrome/browser/download/bubble/download_bubble_utils.cc
index 56936f0..7387f5e 100644
--- a/chrome/browser/download/bubble/download_bubble_utils.cc
+++ b/chrome/browser/download/bubble/download_bubble_utils.cc
@@ -82,14 +82,16 @@
 }
 
 bool IsItemInProgress(const download::DownloadItem* item) {
-  if (item->IsDangerous() || IsPendingDeepScanning(item)) {
+  if (item->IsDangerous() || item->IsInsecure() ||
+      IsPendingDeepScanning(item)) {
     return false;
   }
   return item->GetState() == download::DownloadItem::IN_PROGRESS;
 }
 
 bool IsItemInProgress(const offline_items_collection::OfflineItem& item) {
-  // Offline items cannot be pending deep scanning.
+  // Offline items cannot be pending deep scanning, and insecure warnings are
+  // not shown for them.
   if (item.is_dangerous) {
     return false;
   }
@@ -99,7 +101,8 @@
 }
 
 bool IsModelInProgress(const DownloadUIModel* model) {
-  if (model->IsDangerous() || IsPendingDeepScanning(model)) {
+  if (model->IsDangerous() || model->IsInsecure() ||
+      IsPendingDeepScanning(model)) {
     return false;
   }
   return model->GetState() == download::DownloadItem::IN_PROGRESS;
@@ -140,7 +143,7 @@
   return browser_to_show_animation;
 }
 
-const web_app::AppId* GetWebAppIdForBrowser(const Browser* browser) {
+const webapps::AppId* GetWebAppIdForBrowser(const Browser* browser) {
   return web_app::AppBrowserController::IsWebApp(browser)
              ? &browser->app_controller()->app_id()
              : nullptr;
diff --git a/chrome/browser/download/bubble/download_bubble_utils.h b/chrome/browser/download/bubble/download_bubble_utils.h
index 84689d1..ff68d466 100644
--- a/chrome/browser/download/bubble/download_bubble_utils.h
+++ b/chrome/browser/download/bubble/download_bubble_utils.h
@@ -7,8 +7,8 @@
 
 #include "base/time/time.h"
 #include "chrome/browser/download/download_ui_model.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "components/offline_items_collection/core/offline_item.h"
+#include "components/webapps/common/web_app_id.h"
 
 base::Time GetItemStartTime(const download::DownloadItem* item);
 base::Time GetItemStartTime(const offline_items_collection::OfflineItem& item);
@@ -46,6 +46,6 @@
 
 // Gets a pointer to the web app id, if the browser is for a web app, otherwise
 // nullptr.
-const web_app::AppId* GetWebAppIdForBrowser(const Browser* browser);
+const webapps::AppId* GetWebAppIdForBrowser(const Browser* browser);
 
 #endif  // CHROME_BROWSER_DOWNLOAD_BUBBLE_DOWNLOAD_BUBBLE_UTILS_H_
diff --git a/chrome/browser/download/bubble/download_display_controller.cc b/chrome/browser/download/bubble/download_display_controller.cc
index c4b5b18a..8ec3fecb 100644
--- a/chrome/browser/download/bubble/download_display_controller.cc
+++ b/chrome/browser/download/bubble/download_display_controller.cc
@@ -97,7 +97,7 @@
     }
   } else {
     DownloadDisplay::IconUpdateInfo updates;
-    updates.show_animation = true;
+    updates.show_animation = show_animation;
     display_->UpdateDownloadIcon(updates);
   }
 }
diff --git a/chrome/browser/download/bubble/download_display_controller_unittest.cc b/chrome/browser/download/bubble/download_display_controller_unittest.cc
index 323a64cf..5edc9b80 100644
--- a/chrome/browser/download/bubble/download_display_controller_unittest.cc
+++ b/chrome/browser/download/bubble/download_display_controller_unittest.cc
@@ -175,7 +175,7 @@
   }
 
   const DownloadBubbleDisplayInfo& GetDisplayInfo(
-      const web_app::AppId* web_app_id) override {
+      const webapps::AppId* web_app_id) override {
     info_ = DownloadBubbleDisplayInfo{};
     int download_item_index = 0, offline_item_index = 0;
     // Compose a list of models from the items stored in the test fixture.
@@ -216,7 +216,7 @@
 
   MOCK_METHOD(DownloadDisplay::ProgressInfo,
               GetProgressInfo,
-              (const web_app::AppId*),
+              (const webapps::AppId*),
               (const override));
 
  private:
@@ -332,6 +332,7 @@
     EXPECT_CALL(item(index), GetDangerType())
         .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
     EXPECT_CALL(item(index), IsDangerous()).WillRepeatedly(Return(false));
+    EXPECT_CALL(item(index), IsInsecure()).WillRepeatedly(Return(false));
     int received_bytes =
         state == download::DownloadItem::IN_PROGRESS ? 50 : 100;
     EXPECT_CALL(item(index), GetReceivedBytes())
@@ -400,7 +401,8 @@
                           DownloadState state,
                           download::DownloadDangerType danger_type =
                               download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-                          bool may_show_details = true) {
+                          bool may_show_details = true,
+                          bool is_insecure = false) {
     DCHECK_GT(items_.size(), static_cast<size_t>(item_index));
 
     // In-progress but dangerous downloads are considered complete.
@@ -411,6 +413,8 @@
     EXPECT_CALL(item(item_index), GetState()).WillRepeatedly(Return(state));
     EXPECT_CALL(item(item_index), GetDangerType())
         .WillRepeatedly(Return(danger_type));
+    EXPECT_CALL(item(item_index), IsInsecure())
+        .WillRepeatedly(Return(is_insecure));
     if (state == DownloadState::COMPLETE) {
       EXPECT_CALL(item(item_index), IsDone()).WillRepeatedly(Return(true));
       DownloadPrefs::FromBrowserContext(profile())->SetLastCompleteTime(
@@ -772,6 +776,28 @@
                                  /*is_active=*/false));
 }
 
+TEST_F(DownloadDisplayControllerTest,
+       UpdateToolbarButtonState_InsecureDownload) {
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false,
+                                 /*icon_state=*/DownloadIconState::kComplete,
+                                 /*is_active=*/false));
+
+  InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+                   download::DownloadItem::IN_PROGRESS);
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false,
+                                 /*icon_state=*/DownloadIconState::kProgress,
+                                 /*is_active=*/true));
+
+  UpdateDownloadItem(/*item_index=*/0, DownloadState::IN_PROGRESS,
+                     download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST,
+                     /*may_show_details=*/true, /*is_insecure=*/true);
+  // Insecure downloads should be considered completed and
+  // should display details if there are no other in-progress downloads.
+  EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true,
+                                 /*icon_state=*/DownloadIconState::kComplete,
+                                 /*is_active=*/false));
+}
+
 TEST_F(DownloadDisplayControllerTest, UpdateToolbarButtonState_OnRemovedItem) {
   InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
                    download::DownloadItem::IN_PROGRESS);
diff --git a/chrome/browser/extensions/api/printing/print_job_submitter.cc b/chrome/browser/extensions/api/printing/print_job_submitter.cc
index 2f4d15c..a4b5ca08 100644
--- a/chrome/browser/extensions/api/printing/print_job_submitter.cc
+++ b/chrome/browser/extensions/api/printing/print_job_submitter.cc
@@ -185,9 +185,10 @@
 
 void PrintJobSubmitter::ReadDocumentData() {
   DCHECK(request_.document_blob_uuid);
-  BlobReader::Read(browser_context_, *request_.document_blob_uuid,
-                   base::BindOnce(&PrintJobSubmitter::OnDocumentDataRead,
-                                  weak_ptr_factory_.GetWeakPtr()));
+  BlobReader::Read(
+      browser_context_->GetBlobRemote(*request_.document_blob_uuid),
+      base::BindOnce(&PrintJobSubmitter::OnDocumentDataRead,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void PrintJobSubmitter::OnDocumentDataRead(std::unique_ptr<std::string> data,
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 b201c0f..3440714 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -1059,7 +1059,8 @@
 // server is used.
 // TODO(crbug.com/1413434): test is flaky on linux-chromeos-rel.
 // TODO(crbug.com/1422191): test is flaky on Mac10.14.
-#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC)
+// TODO(crbug.com/1484203): test is flaky on linux tests.
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 #define MAYBE_WebRequestRedirectsWorkers DISABLED_WebRequestRedirectsWorkers
 #else
 #define MAYBE_WebRequestRedirectsWorkers WebRequestRedirectsWorkers
diff --git a/chrome/browser/extensions/extension_service_sync_unittest.cc b/chrome/browser/extensions/extension_service_sync_unittest.cc
index 30c8309..41e3250 100644
--- a/chrome/browser/extensions/extension_service_sync_unittest.cc
+++ b/chrome/browser/extensions/extension_service_sync_unittest.cc
@@ -26,7 +26,6 @@
 #include "chrome/browser/extensions/test_blocklist.h"
 #include "chrome/browser/extensions/updater/extension_updater.h"
 #include "chrome/browser/profiles/profile_key.h"
-#include "chrome/browser/sync/sync_service_factory.h"
 #include "chrome/browser/themes/test/theme_service_changed_waiter.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
@@ -39,8 +38,6 @@
 #include "components/sync/protocol/app_specifics.pb.h"
 #include "components/sync/protocol/entity_specifics.pb.h"
 #include "components/sync/protocol/extension_specifics.pb.h"
-#include "components/sync/service/sync_service.h"
-#include "components/sync/service/sync_user_settings.h"
 #include "components/sync/test/fake_sync_change_processor.h"
 #include "components/sync/test/sync_change_processor_wrapper_for_test.h"
 #include "components/variations/variations_associated_data.h"
@@ -79,8 +76,6 @@
 const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
 const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
 const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd";
-const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
-    syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
 
 ExtensionSyncData GetDisableSyncData(const Extension& extension,
                                      int disable_reasons) {
@@ -321,12 +316,6 @@
       params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
   InitializeExtensionService(params);
 
-  // The user has enabled sync.
-  syncer::SyncService* sync_service =
-      SyncServiceFactory::GetForProfile(profile());
-  sync_service->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-      kSetSourceFromTest);
-
   service()->Init();
   ASSERT_TRUE(extension_system()->is_ready());
 
@@ -357,12 +346,6 @@
 TEST_F(ExtensionServiceSyncTest, ReenableDisabledExtensionFromSync) {
   InitializeEmptyExtensionService();
 
-  // Enable sync.
-  syncer::SyncService* sync_service =
-      SyncServiceFactory::GetForProfile(profile());
-  sync_service->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-      kSetSourceFromTest);
-
   service()->Init();
 
   // Load up a simple extension.
@@ -439,12 +422,6 @@
        DefaultInstalledExtensionsAreNotReenabledOrDisabledBySync) {
   InitializeEmptyExtensionService();
 
-  // Enable sync.
-  syncer::SyncService* sync_service =
-      SyncServiceFactory::GetForProfile(profile());
-  sync_service->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-      kSetSourceFromTest);
-
   service()->Init();
 
   // Load up an extension that's considered default installed.
@@ -503,11 +480,6 @@
       params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
   InitializeExtensionService(params);
 
-  // The user has enabled sync.
-  syncer::SyncService* sync_service =
-      SyncServiceFactory::GetForProfile(profile());
-  sync_service->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-      kSetSourceFromTest);
   // Make sure ExtensionSyncService is created, so it'll be notified of changes.
   extension_sync_service();
 
@@ -563,10 +535,6 @@
       params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
   InitializeExtensionService(params);
 
-  // The user has enabled sync.
-  SyncServiceFactory::GetForProfile(profile())
-      ->GetUserSettings()
-      ->SetInitialSyncFeatureSetupComplete(kSetSourceFromTest);
   // Make sure ExtensionSyncService is created, so it'll be notified of changes.
   extension_sync_service();
 
@@ -1671,10 +1639,6 @@
 TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
   InitializeEmptyExtensionService();
 
-  // The user has enabled sync.
-  SyncServiceFactory::GetForProfile(profile())
-      ->GetUserSettings()
-      ->SetInitialSyncFeatureSetupComplete(kSetSourceFromTest);
   // Make sure ExtensionSyncService is created, so it'll be notified of changes.
   extension_sync_service();
 
@@ -1805,12 +1769,6 @@
 
     InitializeEmptyExtensionService();
 
-    // Enable sync.
-    syncer::SyncService* sync_service =
-        SyncServiceFactory::GetForProfile(profile());
-    sync_service->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-        kSetSourceFromTest);
-
     test_blocklist_.Attach(service()->blocklist_);
     service()->Init();
 
diff --git a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc
index efbb717..0142678 100644
--- a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc
+++ b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc
@@ -115,18 +115,20 @@
   }
 
   // Check segmentation model result.
-  segmentation_platform_service_->GetSelectedSegment(
+  segmentation_platform::PredictionOptions prediction_options;
+  segmentation_platform_service_->GetClassificationResult(
       segmentation_platform::kChromeLowUserEngagementSegmentationKey,
+      prediction_options, /*input_context=*/nullptr,
       base::BindOnce(
           [](bool* is_low_engaged_user, base::OnceClosure closure,
-             const segmentation_platform::SegmentSelectionResult&
-                 segment_selection_result) {
+             const segmentation_platform::ClassificationResult&
+                 classification_result) {
             *is_low_engaged_user =
-                segment_selection_result.is_ready &&
-                segment_selection_result.segment.has_value() &&
-                segment_selection_result.segment.value() ==
-                    segmentation_platform::proto::SegmentId::
-                        OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT;
+                classification_result.status ==
+                    segmentation_platform::PredictionStatus::kSucceeded &&
+                !classification_result.ordered_labels.empty() &&
+                classification_result.ordered_labels[0] ==
+                    segmentation_platform::kChromeLowUserEngagementUmaName;
             std::move(closure).Run();
           },
           &is_low_engaged_user_, std::move(closure)));
diff --git a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl_unittest.cc b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl_unittest.cc
index ba5aab79..94a2608 100644
--- a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl_unittest.cc
+++ b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl_unittest.cc
@@ -16,7 +16,8 @@
 #include "chrome/browser/feature_guide/notifications/internal/utils.h"
 #include "chrome/browser/notifications/scheduler/test/mock_notification_schedule_service.h"
 #include "components/feature_engagement/test/mock_tracker.h"
-#include "components/segmentation_platform/public/segment_selection_result.h"
+#include "components/segmentation_platform/public/constants.h"
+#include "components/segmentation_platform/public/result.h"
 #include "components/segmentation_platform/public/testing/mock_segmentation_platform_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -87,11 +88,11 @@
       queued_params_;
 };
 
-segmentation_platform::SegmentSelectionResult GetSegmentResult() {
-  segmentation_platform::SegmentSelectionResult result;
-  result.is_ready = true;
-  result.segment = segmentation_platform::proto::SegmentId::
-      OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT;
+segmentation_platform::ClassificationResult GetClassificationResult() {
+  segmentation_platform::ClassificationResult result(
+      segmentation_platform::PredictionStatus::kSucceeded);
+  result.ordered_labels.emplace_back(
+      segmentation_platform::kChromeLowUserEngagementUmaName);
   return result;
 }
 
@@ -128,8 +129,9 @@
 };
 
 TEST_F(FeatureNotificationGuideServiceImplTest, BasicFlow) {
-  EXPECT_CALL(segmentation_platform_service_, GetSelectedSegment(_, _))
-      .WillOnce(RunOnceCallback<1>(GetSegmentResult()));
+  EXPECT_CALL(segmentation_platform_service_,
+              GetClassificationResult(_, _, _, _))
+      .WillOnce(RunOnceCallback<3>(GetClassificationResult()));
 
   EXPECT_CALL(tracker_, WouldTriggerHelpUI(_)).WillRepeatedly(Return(true));
   service_->OnSchedulerInitialized(std::set<std::string>());
@@ -160,8 +162,9 @@
 }
 
 TEST_F(FeatureNotificationGuideServiceImplTest, SkipAlreadyScheduledFeatures) {
-  EXPECT_CALL(segmentation_platform_service_, GetSelectedSegment(_, _))
-      .WillOnce(RunOnceCallback<1>(GetSegmentResult()));
+  EXPECT_CALL(segmentation_platform_service_,
+              GetClassificationResult(_, _, _, _))
+      .WillOnce(RunOnceCallback<3>(GetClassificationResult()));
   EXPECT_CALL(tracker_, WouldTriggerHelpUI(_)).WillRepeatedly(Return(true));
   std::set<std::string> scheduled_guids;
   scheduled_guids.insert("guid_incognito_tab");
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index da2c591d..a66353c7 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -667,6 +667,11 @@
     "expiry_milestone": 120
   },
   {
+    "name": "autofill-enable-virtual-cards",
+    "owners": [ "siyua", "chbannon@google.com", "slobodan" ],
+    "expiry_milestone": 125
+  },
+  {
     "name": "autofill-highlight-only-changed-value-in-preview-mode",
     "owners": [ "koerber", "mamir" ],
     "expiry_milestone": 120
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index eee6c200..90dc251a 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -10,6 +10,7 @@
 
 #include "base/android/feature_map.h"
 #include "base/feature_list.h"
+#include "base/features.h"
 #include "base/no_destructor.h"
 #include "chrome/browser/browser_features.h"
 #include "chrome/browser/feature_guide/notifications/feature_notification_guide_service.h"
@@ -108,6 +109,7 @@
     &download::features::kSmartSuggestionForLargeDownloads,
     &download::features::kUseDownloadOfflineContentProvider,
     &download::features::kDownloadsMigrateToJobsAPI,
+    &base::features::kCollectAndroidFrameTimelineMetrics,
     &features::kPWAsDefaultOfflinePage,
     &features::kGenericSensorExtraClasses,
     &features::kBackForwardCache,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 85131d6..bd128b17 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -210,6 +210,8 @@
             "ClearOmniboxFocusAfterNavigation";
     public static final String CLOSE_TAB_SUGGESTIONS = "CloseTabSuggestions";
     public static final String CLOSE_TAB_SAVE_TAB_LIST = "CloseTabSaveTabList";
+    public static final String COLLECT_ANDROID_FRAME_TIMELINE_METRICS =
+            "CollectAndroidFrameTimelineMetrics";
     public static final String COMMAND_LINE_ON_NON_ROOTED = "CommandLineOnNonRooted";
     public static final String COMMERCE_MERCHANT_VIEWER = "CommerceMerchantViewer";
     public static final String COMMERCE_PRICE_TRACKING = "CommercePriceTracking";
@@ -239,7 +241,6 @@
     public static final String CORMORANT = "Cormorant";
     public static final String CREATE_NEW_TAB_INITIALIZE_RENDERER =
             "CreateNewTabInitializeRenderer";
-    public static final String CRITICAL_PERSISTED_TAB_DATA = "CriticalPersistedTabData";
     public static final String DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING =
             "DarkenWebsitesCheckboxInThemesSetting";
     public static final String DEFER_KEEP_SCREEN_ON_DURING_GESTURE =
@@ -532,6 +533,8 @@
             new CachedFlag(CLOSE_TAB_SUGGESTIONS, false);
     public static final CachedFlag sCloseTabSaveTabList =
             new CachedFlag(CLOSE_TAB_SAVE_TAB_LIST, true);
+    public static final CachedFlag sCollectAndroidFrameTimelineMetrics =
+            new CachedFlag(COLLECT_ANDROID_FRAME_TIMELINE_METRICS, true);
     public static final CachedFlag sCommandLineOnNonRooted =
             new CachedFlag(COMMAND_LINE_ON_NON_ROOTED,
                     ChromePreferenceKeys.FLAGS_CACHED_COMMAND_LINE_ON_NON_ROOTED_ENABLED, false);
@@ -643,6 +646,7 @@
         sCctToolbarCustomizations,
         sCloseTabSuggestions,
         sCloseTabSaveTabList,
+        sCollectAndroidFrameTimelineMetrics,
         sCommandLineOnNonRooted,
         sDelayTempStripRemoval,
         sDragDropIntoOmnibox,
diff --git a/chrome/browser/installable/ml_promotion_browsertest.cc b/chrome/browser/installable/ml_promotion_browsertest.cc
index 7166d7e..d015468 100644
--- a/chrome/browser/installable/ml_promotion_browsertest.cc
+++ b/chrome/browser/installable/ml_promotion_browsertest.cc
@@ -263,7 +263,7 @@
 
   void ExpectClasificationCallReturnResult(
       GURL site_url,
-      web_app::ManifestId manifest_id,
+      webapps::ManifestId manifest_id,
       std::string label_result,
       TrainingRequestId request_result,
       content::WebContents* custom_web_contents = nullptr) {
@@ -655,7 +655,7 @@
   provider().command_manager().AwaitAllCommandsCompleteForTesting();
 
   EXPECT_FALSE(provider().registrar_unsafe().is_empty());
-  web_app::AppId app_id = provider().registrar_unsafe().GetAppIds()[0];
+  webapps::AppId app_id = provider().registrar_unsafe().GetAppIds()[0];
   EXPECT_EQ("Web App Test Page with Favicon",
             provider().registrar_unsafe().GetAppShortName(app_id));
   auto user_display_mode =
@@ -908,7 +908,7 @@
   provider().command_manager().AwaitAllCommandsCompleteForTesting();
 
   EXPECT_FALSE(provider().registrar_unsafe().is_empty());
-  web_app::AppId app_id = provider().registrar_unsafe().GetAppIds()[0];
+  webapps::AppId app_id = provider().registrar_unsafe().GetAppIds()[0];
   EXPECT_EQ(GetAppNameBasedOnDialogState(),
             provider().registrar_unsafe().GetAppShortName(app_id));
 }
diff --git a/chrome/browser/installable/ml_promotion_browsertest_base.cc b/chrome/browser/installable/ml_promotion_browsertest_base.cc
index 0f67155..f88232b 100644
--- a/chrome/browser/installable/ml_promotion_browsertest_base.cc
+++ b/chrome/browser/installable/ml_promotion_browsertest_base.cc
@@ -29,12 +29,12 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/test/web_app_test_utils.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/views/test/dialog_test.h"
 #include "ui/views/test/widget_test.h"
@@ -84,7 +84,7 @@
 #else
   web_app::WebAppProvider* provider =
       web_app::WebAppProvider::GetForTest(browser()->profile());
-  base::test::TestFuture<const web_app::AppId&, InstallResultCode>
+  base::test::TestFuture<const webapps::AppId&, InstallResultCode>
       install_future;
 
   provider->scheduler().FetchManifestAndInstall(
@@ -98,7 +98,7 @@
     return success;
   }
 
-  const web_app::AppId& app_id = install_future.Get<web_app::AppId>();
+  const webapps::AppId& app_id = install_future.Get<webapps::AppId>();
   provider->sync_bridge_unsafe().SetAppIsLocallyInstalledForTesting(
       app_id, /*is_locally_installed=*/install_locally);
   return success;
@@ -112,7 +112,7 @@
   // TODO(b/287255120) : Build functionalities for Android.
   return false;
 #else
-  base::test::TestFuture<const web_app::AppId&, InstallResultCode>
+  base::test::TestFuture<const webapps::AppId&, InstallResultCode>
       install_future;
   views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                        dialog_name);
diff --git a/chrome/browser/preferences/BUILD.gn b/chrome/browser/preferences/BUILD.gn
index 5b8a6a27..66f3875 100644
--- a/chrome/browser/preferences/BUILD.gn
+++ b/chrome/browser/preferences/BUILD.gn
@@ -7,14 +7,15 @@
 
 android_library("java") {
   sources = [
-    "android/java/src/org/chromium/chrome/browser/preferences/BaseChromePreferenceKeyChecker.java",
-    "android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyChecker.java",
     "android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java",
     "android/java/src/org/chromium/chrome/browser/preferences/DeprecatedChromePreferenceKeys.java",
     "android/java/src/org/chromium/chrome/browser/preferences/KeyPrefix.java",
     "android/java/src/org/chromium/chrome/browser/preferences/LegacyChromePreferenceKeys.java",
+    "android/java/src/org/chromium/chrome/browser/preferences/NoOpPreferenceKeyChecker.java",
     "android/java/src/org/chromium/chrome/browser/preferences/PrefChangeRegistrar.java",
+    "android/java/src/org/chromium/chrome/browser/preferences/PreferenceKeyChecker.java",
     "android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManager.java",
+    "android/java/src/org/chromium/chrome/browser/preferences/StrictPreferenceKeyChecker.java",
   ]
   deps = [
     "//base:base_java",
@@ -78,10 +79,10 @@
 
 robolectric_library("preferences_junit_tests") {
   sources = [
-    "android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyCheckerTest.java",
     "android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeysTest.java",
     "android/java/src/org/chromium/chrome/browser/preferences/KeyPrefixTest.java",
     "android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java",
+    "android/java/src/org/chromium/chrome/browser/preferences/StrictPreferenceKeyCheckerTest.java",
   ]
   deps = [
     ":java",
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index e58bfa5..0fef110 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -43,7 +43,7 @@
  * LegacyChromePreferenceKeys#getPrefixesInUse()}.
  * 3. Delete the KeyPrefix constant.
  *
- * Tests in ChromePreferenceKeysTest and checks in {@link ChromePreferenceKeyChecker} ensure the
+ * Tests in ChromePreferenceKeysTest and checks in {@link StrictPreferenceKeyChecker} ensure the
  * validity of this file.
  */
 public final class ChromePreferenceKeys {
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/BaseChromePreferenceKeyChecker.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/NoOpPreferenceKeyChecker.java
similarity index 63%
rename from chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/BaseChromePreferenceKeyChecker.java
rename to chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/NoOpPreferenceKeyChecker.java
index aca69c4b..467743ef1 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/BaseChromePreferenceKeyChecker.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/NoOpPreferenceKeyChecker.java
@@ -7,12 +7,14 @@
 /**
  * A placeholder key checker that never throws exceptions. Used in production builds.
  */
-class BaseChromePreferenceKeyChecker {
-    void checkIsKeyInUse(String key) {
+class NoOpPreferenceKeyChecker implements PreferenceKeyChecker {
+    @Override
+    public void checkIsKeyInUse(String key) {
         // No-op.
     }
 
-    void checkIsPrefixInUse(KeyPrefix prefix) {
+    @Override
+    public void checkIsPrefixInUse(KeyPrefix prefix) {
         // No-op.
     }
 }
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/PreferenceKeyChecker.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/PreferenceKeyChecker.java
new file mode 100644
index 0000000..a0d94b1
--- /dev/null
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/PreferenceKeyChecker.java
@@ -0,0 +1,19 @@
+// Copyright 2023 The Chromium Authors
+// 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.preferences;
+
+/**
+ * A SharedPreferences key checker that may check if the key is in use.
+ *
+ * In official builds, {@link NoOpPreferenceKeyChecker} is used, which is a no-op.
+ * In debug builds, {@link StrictPreferenceKeyChecker} is used, which checks if a key is registered.
+ */
+interface PreferenceKeyChecker {
+    // Asserts that the SharedPreferences |key| is registered as "in use".
+    void checkIsKeyInUse(String key);
+
+    // Asserts that the SharedPreferences KeyPrefix |prefix| is registered as "in use".
+    void checkIsPrefixInUse(KeyPrefix prefix);
+}
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManager.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManager.java
index 823ccaaa..026107c 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManager.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManager.java
@@ -12,7 +12,6 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ResettersForTesting;
-import org.chromium.base.StrictModeContext;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.build.BuildConfig;
 
@@ -32,42 +31,6 @@
     }
 
     /**
-     * @return The SharedPreferencesManager singleton.
-     */
-    @CalledByNative
-    public static SharedPreferencesManager getInstance() {
-        return LazyHolder.INSTANCE;
-    }
-
-    private BaseChromePreferenceKeyChecker mKeyChecker;
-
-    private SharedPreferencesManager() {
-        maybeInitializeChecker();
-        // In production builds, use a placeholder key checker.
-        if (mKeyChecker == null) {
-            mKeyChecker = new BaseChromePreferenceKeyChecker();
-        }
-    }
-
-    @VisibleForTesting
-    SharedPreferencesManager(BaseChromePreferenceKeyChecker keyChecker) {
-        mKeyChecker = keyChecker;
-    }
-
-    private void maybeInitializeChecker() {
-        // Create a working key checker, which does not happen in production builds.
-        if (BuildConfig.ENABLE_ASSERTS) {
-            mKeyChecker = ChromePreferenceKeyChecker.getInstance();
-        }
-    }
-
-    public void disableKeyCheckerForTesting() {
-        BaseChromePreferenceKeyChecker swappedOut = mKeyChecker;
-        mKeyChecker = new BaseChromePreferenceKeyChecker();
-        ResettersForTesting.register(() -> mKeyChecker = swappedOut);
-    }
-
-    /**
      * Observes preference changes.
      */
     public interface Observer {
@@ -78,10 +41,36 @@
         void onPreferenceChanged(String key);
     }
 
+    private PreferenceKeyChecker mKeyChecker;
+
     private final Map<Observer, SharedPreferences.OnSharedPreferenceChangeListener> mObservers =
             new HashMap<>();
 
     /**
+     * @return The SharedPreferencesManager singleton.
+     */
+    @CalledByNative
+    public static SharedPreferencesManager getInstance() {
+        return LazyHolder.INSTANCE;
+    }
+
+    private SharedPreferencesManager() {
+        mKeyChecker = BuildConfig.ENABLE_ASSERTS ? new StrictPreferenceKeyChecker()
+                                                 : new NoOpPreferenceKeyChecker();
+    }
+
+    @VisibleForTesting
+    SharedPreferencesManager(PreferenceKeyChecker keyChecker) {
+        mKeyChecker = keyChecker;
+    }
+
+    public void disableKeyCheckerForTesting() {
+        PreferenceKeyChecker swappedOut = mKeyChecker;
+        mKeyChecker = new NoOpPreferenceKeyChecker();
+        ResettersForTesting.register(() -> mKeyChecker = swappedOut);
+    }
+
+    /**
      * @param observer The {@link Observer} to be added for observing preference changes.
      */
     public void addObserver(Observer observer) {
@@ -204,10 +193,7 @@
         mKeyChecker.checkIsKeyInUse(key);
         SharedPreferences.Editor ed = ContextUtils.getAppSharedPreferences().edit();
         ed.putInt(key, value);
-
-        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
-            return ed.commit();
-        }
+        return ed.commit();
     }
 
     /**
@@ -241,9 +227,7 @@
     @CalledByNative
     public int readInt(String key, int defaultValue) {
         mKeyChecker.checkIsKeyInUse(key);
-        try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
-            return ContextUtils.getAppSharedPreferences().getInt(key, defaultValue);
-        }
+        return ContextUtils.getAppSharedPreferences().getInt(key, defaultValue);
     }
 
     /**
@@ -292,10 +276,7 @@
         mKeyChecker.checkIsKeyInUse(key);
         SharedPreferences.Editor ed = ContextUtils.getAppSharedPreferences().edit();
         ed.putLong(key, value);
-
-        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
-            return ed.commit();
-        }
+        return ed.commit();
     }
 
     /**
@@ -330,9 +311,7 @@
      */
     public long readLong(String key, long defaultValue) {
         mKeyChecker.checkIsKeyInUse(key);
-        try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
-            return ContextUtils.getAppSharedPreferences().getLong(key, defaultValue);
-        }
+        return ContextUtils.getAppSharedPreferences().getLong(key, defaultValue);
     }
 
     /**
@@ -369,10 +348,7 @@
         mKeyChecker.checkIsKeyInUse(key);
         SharedPreferences.Editor ed = ContextUtils.getAppSharedPreferences().edit();
         ed.putFloat(key, value);
-
-        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
-            return ed.commit();
-        }
+        return ed.commit();
     }
 
     /**
@@ -397,9 +373,7 @@
      */
     public float readFloat(String key, float defaultValue) {
         mKeyChecker.checkIsKeyInUse(key);
-        try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
-            return ContextUtils.getAppSharedPreferences().getFloat(key, defaultValue);
-        }
+        return ContextUtils.getAppSharedPreferences().getFloat(key, defaultValue);
     }
 
     /**
@@ -450,13 +424,11 @@
     public Double readDouble(String key, double defaultValue) {
         mKeyChecker.checkIsKeyInUse(key);
         SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
-        try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
-            if (!prefs.contains(key)) {
-                return defaultValue;
-            }
-            long ieee754LongValue = prefs.getLong(key, 0L);
-            return Double.longBitsToDouble(ieee754LongValue);
+        if (!prefs.contains(key)) {
+            return defaultValue;
         }
+        long ieee754LongValue = prefs.getLong(key, 0L);
+        return Double.longBitsToDouble(ieee754LongValue);
     }
 
     /**
@@ -500,10 +472,7 @@
         mKeyChecker.checkIsKeyInUse(key);
         SharedPreferences.Editor ed = ContextUtils.getAppSharedPreferences().edit();
         ed.putBoolean(key, value);
-
-        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
-            return ed.commit();
-        }
+        return ed.commit();
     }
 
     /**
@@ -529,9 +498,7 @@
     @CalledByNative
     public boolean readBoolean(String key, boolean defaultValue) {
         mKeyChecker.checkIsKeyInUse(key);
-        try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
-            return ContextUtils.getAppSharedPreferences().getBoolean(key, defaultValue);
-        }
+        return ContextUtils.getAppSharedPreferences().getBoolean(key, defaultValue);
     }
 
     /**
@@ -568,10 +535,7 @@
         mKeyChecker.checkIsKeyInUse(key);
         SharedPreferences.Editor ed = ContextUtils.getAppSharedPreferences().edit();
         ed.putString(key, value);
-
-        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
-            return ed.commit();
-        }
+        return ed.commit();
     }
 
     /**
@@ -598,9 +562,7 @@
     @CalledByNative
     public String readString(String key, @Nullable String defaultValue) {
         mKeyChecker.checkIsKeyInUse(key);
-        try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
-            return ContextUtils.getAppSharedPreferences().getString(key, defaultValue);
-        }
+        return ContextUtils.getAppSharedPreferences().getString(key, defaultValue);
     }
 
     /**
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java
index 20159179..c599b61 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java
@@ -33,7 +33,7 @@
 @RunWith(BaseRobolectricTestRunner.class)
 public class SharedPreferencesManagerTest {
     @Mock
-    private ChromePreferenceKeyChecker mChecker;
+    private PreferenceKeyChecker mChecker;
 
     private static final KeyPrefix TEST_PREFIX = new KeyPrefix("TestPrefix.*");
     private static final String PREFIXED_KEY_1 = TEST_PREFIX.createKey("stemA");
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyChecker.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/StrictPreferenceKeyChecker.java
similarity index 76%
rename from chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyChecker.java
rename to chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/StrictPreferenceKeyChecker.java
index 21e3be5ba..f9b29d4 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyChecker.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/StrictPreferenceKeyChecker.java
@@ -18,21 +18,28 @@
 
 /**
  * Class that checks if given Strings are valid SharedPreferences keys to use.
+ *
+ * Checks that:
+ * 1. Keys are registered as "in use".
+ * 2. The key format is valid, either:
+ *   - "Chrome.[Feature].[Key]"
+ *   - "Chrome.[Feature].[KeyPrefix].[Suffix]"
+ *   - Legacy key prior to this restriction
  */
 @CheckDiscard("Validation is performed in tests and in debug builds.")
-class ChromePreferenceKeyChecker extends BaseChromePreferenceKeyChecker {
-    private static final ChromePreferenceKeyChecker INSTANCE = new ChromePreferenceKeyChecker();
+class StrictPreferenceKeyChecker implements PreferenceKeyChecker {
+    // The dynamic part cannot be empty, but otherwise it is anything that does not contain
+    // stars.
+    private static final Pattern DYNAMIC_PART_PATTERN = Pattern.compile("[^\\*]+");
 
-    private Set<String> mKeysInUse;
-    private Set<String> mLegacyFormatKeys;
-    private List<KeyPrefix> mLegacyPrefixes;
-    private Pattern mDynamicPartPattern;
+    private final Set<String> mKeysInUse;
+    private final Set<String> mLegacyFormatKeys;
+    private final List<KeyPrefix> mLegacyPrefixes;
 
     /**
-     * Constructor called by the singleton, pulls the lists of keys from {@link
-     * ChromePreferenceKeys}.
+     * Constructor that pulls the lists of keys from {@link ChromePreferenceKeys}.
      */
-    private ChromePreferenceKeyChecker() {
+    StrictPreferenceKeyChecker() {
         this(ChromePreferenceKeys.getKeysInUse(), LegacyChromePreferenceKeys.getKeysInUse(),
                 LegacyChromePreferenceKeys.getPrefixesInUse());
     }
@@ -41,22 +48,11 @@
      * Generic constructor, dependencies are passed in.
      */
     @VisibleForTesting
-    ChromePreferenceKeyChecker(
+    StrictPreferenceKeyChecker(
             List<String> keysInUse, List<String> legacyKeys, List<KeyPrefix> legacyPrefixes) {
         mKeysInUse = new HashSet<>(keysInUse);
         mLegacyFormatKeys = new HashSet<>(legacyKeys);
         mLegacyPrefixes = legacyPrefixes;
-
-        // The dynamic part cannot be empty, but otherwise it is anything that does not contain
-        // stars.
-        mDynamicPartPattern = Pattern.compile("[^\\*]+");
-    }
-
-    /**
-     * @return The ChromePreferenceKeyChecker singleton.
-     */
-    public static ChromePreferenceKeyChecker getInstance() {
-        return INSTANCE;
     }
 
     /**
@@ -64,7 +60,7 @@
      * @throws RuntimeException if the key is not in use.
      */
     @Override
-    void checkIsKeyInUse(String key) {
+    public void checkIsKeyInUse(String key) {
         if (!isKeyInUse(key)) {
             throw new RuntimeException("SharedPreferences key \"" + key
                     + "\" is not registered in ChromePreferenceKeys.createKeysInUse()");
@@ -103,7 +99,7 @@
 
             // Check if the dynamic part is correctly formed.
             String dynamicPart = parts[3];
-            return mDynamicPartPattern.matcher(dynamicPart).matches();
+            return DYNAMIC_PART_PATTERN.matcher(dynamicPart).matches();
         } else {
             // Regular key in format "Chrome.[Feature].[Key]" which was not present in |mKeysInUse|.
             // Just check if it is in [keys in use].
@@ -112,7 +108,7 @@
     }
 
     @Override
-    void checkIsPrefixInUse(KeyPrefix prefix) {
+    public void checkIsPrefixInUse(KeyPrefix prefix) {
         if (mLegacyPrefixes.contains(prefix)) {
             return;
         }
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyCheckerTest.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/StrictPreferenceKeyCheckerTest.java
similarity index 94%
rename from chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyCheckerTest.java
rename to chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/StrictPreferenceKeyCheckerTest.java
index 39cf9700..cd115d3f 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyCheckerTest.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/StrictPreferenceKeyCheckerTest.java
@@ -16,10 +16,10 @@
 import java.util.List;
 
 /**
- * Unit tests for {@link ChromePreferenceKeyChecker}.
+ * Unit tests for {@link StrictPreferenceKeyChecker}.
  */
 @RunWith(BaseRobolectricTestRunner.class)
-public class ChromePreferenceKeyCheckerTest {
+public class StrictPreferenceKeyCheckerTest {
     private static final String KEY1_IN_USE = "Chrome.Feature.Key1";
     private static final String KEY2_IN_USE = "Chrome.Feature.Key2";
     private static final String KEY3_NOT_IN_USE = "Chrome.Feature.Key3";
@@ -32,7 +32,7 @@
     private static final String LEGACY_KEY_IN_USE = "legacykey";
     private static final String LEGACY_PREFIX_IN_USE = "legacyprefix_";
 
-    private ChromePreferenceKeyChecker mSubject;
+    private StrictPreferenceKeyChecker mSubject;
 
     @Before
     public void setUp() {
@@ -40,7 +40,7 @@
                 KEY_PREFIX1_IN_USE.pattern(), KEY_PREFIX2_IN_USE.pattern());
         List<String> legacyKeys = Arrays.asList(LEGACY_KEY_IN_USE);
         List<KeyPrefix> legacyPrefixes = Arrays.asList(new KeyPrefix(LEGACY_PREFIX_IN_USE + "*"));
-        mSubject = new ChromePreferenceKeyChecker(keysInUse, legacyKeys, legacyPrefixes);
+        mSubject = new StrictPreferenceKeyChecker(keysInUse, legacyKeys, legacyPrefixes);
     }
 
     @Test
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index f31dedcb..1148a8b 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -927,6 +927,11 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 constexpr char kGestureEducationNotificationShown[] =
     "ash.gesture_education.notification_shown";
+
+// Note that this very name is used outside ChromeOS Ash, where it isn't
+// deprecated.
+constexpr char kSyncInitialSyncFeatureSetupCompleteOnAsh[] =
+    "sync.has_setup_completed";
 #endif
 
 // Deprecated 09/2023.
@@ -1312,6 +1317,10 @@
 #endif
   registry->RegisterBooleanPref(kDownloadBubbleEnabled, true);
   registry->RegisterBooleanPref(kPrivacySandboxManuallyControlled, false);
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  registry->RegisterBooleanPref(kSyncInitialSyncFeatureSetupCompleteOnAsh,
+                                false);
+#endif
 }
 
 }  // namespace
@@ -2474,6 +2483,9 @@
 #endif
   profile_prefs->ClearPref(kDownloadBubbleEnabled);
   profile_prefs->ClearPref(kPrivacySandboxManuallyControlled);
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  profile_prefs->ClearPref(kSyncInitialSyncFeatureSetupCompleteOnAsh);
+#endif
 
   // Please don't delete the following line. It is used by PRESUBMIT.py.
   // END_MIGRATE_OBSOLETE_PROFILE_PREFS
diff --git a/chrome/browser/privacy_sandbox/android/BUILD.gn b/chrome/browser/privacy_sandbox/android/BUILD.gn
index e18fff5..979ffda5 100644
--- a/chrome/browser/privacy_sandbox/android/BUILD.gn
+++ b/chrome/browser/privacy_sandbox/android/BUILD.gn
@@ -14,6 +14,7 @@
     "java/src/org/chromium/chrome/browser/privacy_sandbox/AdMeasurementFragment.java",
     "java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationFragment.java",
     "java/src/org/chromium/chrome/browser/privacy_sandbox/AdPersonalizationRemovedFragment.java",
+    "java/src/org/chromium/chrome/browser/privacy_sandbox/ChromeTrackingProtectionDelegate.java",
     "java/src/org/chromium/chrome/browser/privacy_sandbox/FledgePreference.java",
     "java/src/org/chromium/chrome/browser/privacy_sandbox/LearnMoreFragment.java",
     "java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxBottomSheetNotice.java",
@@ -62,6 +63,7 @@
     "//components/browser_ui/widget/android:java",
     "//components/favicon/android:java",
     "//components/prefs/android:java",
+    "//components/privacy_sandbox/android:java",
     "//components/user_prefs/android:java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/ChromeTrackingProtectionDelegate.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/ChromeTrackingProtectionDelegate.java
new file mode 100644
index 0000000..a801d36
--- /dev/null
+++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/ChromeTrackingProtectionDelegate.java
@@ -0,0 +1,38 @@
+// Copyright 2023 The Chromium Authors
+// 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.privacy_sandbox;
+
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.privacy_sandbox.TrackingProtectionDelegate;
+import org.chromium.components.user_prefs.UserPrefs;
+
+public class ChromeTrackingProtectionDelegate implements TrackingProtectionDelegate {
+    private final Profile mProfile;
+
+    public ChromeTrackingProtectionDelegate(Profile profile) {
+        mProfile = profile;
+    }
+
+    @Override
+    public boolean isBlockAll3PCDEnabled() {
+        return UserPrefs.get(mProfile).getBoolean(Pref.BLOCK_ALL3PC_TOGGLE_ENABLED);
+    }
+
+    @Override
+    public void setBlockAll3PCD(boolean enabled) {
+        UserPrefs.get(mProfile).setBoolean(Pref.BLOCK_ALL3PC_TOGGLE_ENABLED, enabled);
+    }
+
+    @Override
+    public boolean isDoNotTrackEnabled() {
+        return UserPrefs.get(mProfile).getBoolean(Pref.ENABLE_DO_NOT_TRACK);
+    }
+
+    @Override
+    public void setDoNotTrack(boolean enabled) {
+        UserPrefs.get(mProfile).setBoolean(Pref.ENABLE_DO_NOT_TRACK, enabled);
+    }
+}
diff --git a/chrome/browser/privacy_sandbox/tracking_protection_notice_factory.cc b/chrome/browser/privacy_sandbox/tracking_protection_notice_factory.cc
new file mode 100644
index 0000000..efe8668
--- /dev/null
+++ b/chrome/browser/privacy_sandbox/tracking_protection_notice_factory.cc
@@ -0,0 +1,46 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/privacy_sandbox/tracking_protection_notice_factory.h"
+#include <memory>
+#include "base/no_destructor.h"
+#include "chrome/browser/privacy_sandbox/tracking_protection_notice_service.h"
+#include "chrome/browser/privacy_sandbox/tracking_protection_onboarding_factory.h"
+#include "chrome/browser/profiles/profile.h"
+
+TrackingProtectionNoticeFactory*
+TrackingProtectionNoticeFactory::GetInstance() {
+  static base::NoDestructor<TrackingProtectionNoticeFactory> instance;
+  return instance.get();
+}
+
+privacy_sandbox::TrackingProtectionNoticeService*
+TrackingProtectionNoticeFactory::GetForProfile(Profile* profile) {
+  return static_cast<privacy_sandbox::TrackingProtectionNoticeService*>(
+      GetInstance()->GetServiceForBrowserContext(profile, true));
+}
+
+TrackingProtectionNoticeFactory::TrackingProtectionNoticeFactory()
+    : ProfileKeyedServiceFactory("TrackingProtectionNotice") {
+  DependsOn(TrackingProtectionOnboardingFactory::GetInstance());
+}
+
+std::unique_ptr<KeyedService>
+TrackingProtectionNoticeFactory::BuildServiceInstanceForBrowserContext(
+    content::BrowserContext* context) const {
+  Profile* profile = Profile::FromBrowserContext(context);
+  auto* onboarding_sevice =
+      TrackingProtectionOnboardingFactory::GetForProfile(profile);
+
+  return onboarding_sevice
+             ? std::make_unique<
+                   privacy_sandbox::TrackingProtectionNoticeService>(
+                   profile, onboarding_sevice)
+             : nullptr;
+}
+
+bool TrackingProtectionNoticeFactory::ServiceIsCreatedWithBrowserContext()
+    const {
+  return true;
+}
diff --git a/chrome/browser/privacy_sandbox/tracking_protection_notice_factory.h b/chrome/browser/privacy_sandbox/tracking_protection_notice_factory.h
new file mode 100644
index 0000000..71770bb8
--- /dev/null
+++ b/chrome/browser/privacy_sandbox/tracking_protection_notice_factory.h
@@ -0,0 +1,33 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PRIVACY_SANDBOX_TRACKING_PROTECTION_NOTICE_FACTORY_H_
+#define CHROME_BROWSER_PRIVACY_SANDBOX_TRACKING_PROTECTION_NOTICE_FACTORY_H_
+
+#include <memory>
+#include "base/no_destructor.h"
+#include "chrome/browser/privacy_sandbox/tracking_protection_notice_service.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+
+class Profile;
+
+class TrackingProtectionNoticeFactory : public ProfileKeyedServiceFactory {
+ public:
+  static TrackingProtectionNoticeFactory* GetInstance();
+  static privacy_sandbox::TrackingProtectionNoticeService* GetForProfile(
+      Profile* profile);
+
+ private:
+  friend base::NoDestructor<TrackingProtectionNoticeFactory>;
+  TrackingProtectionNoticeFactory();
+  ~TrackingProtectionNoticeFactory() override = default;
+
+  // BrowserContextKeyedServiceFactory:
+  std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
+      content::BrowserContext* context) const override;
+
+  bool ServiceIsCreatedWithBrowserContext() const override;
+};
+
+#endif  // CHROME_BROWSER_PRIVACY_SANDBOX_TRACKING_PROTECTION_NOTICE_FACTORY_H_
diff --git a/chrome/browser/privacy_sandbox/tracking_protection_notice_service.cc b/chrome/browser/privacy_sandbox/tracking_protection_notice_service.cc
new file mode 100644
index 0000000..672d3059d
--- /dev/null
+++ b/chrome/browser/privacy_sandbox/tracking_protection_notice_service.cc
@@ -0,0 +1,46 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/privacy_sandbox/tracking_protection_notice_service.h"
+#include "base/check.h"
+
+#include "chrome/browser/privacy_sandbox/tracking_protection_notice_factory.h"
+#include "chrome/browser/privacy_sandbox/tracking_protection_onboarding_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/privacy_sandbox/tracking_protection_onboarding.h"
+
+namespace privacy_sandbox {
+
+TrackingProtectionNoticeService::TrackingProtectionNoticeService(
+    Profile* profile,
+    TrackingProtectionOnboarding* onboarding_service)
+    : profile_(profile), onboarding_service_(onboarding_service) {
+  CHECK(profile_);
+  CHECK(onboarding_service_);
+}
+
+TrackingProtectionNoticeService::~TrackingProtectionNoticeService() = default;
+
+bool TrackingProtectionNoticeService::IsNoticeNeeded() {
+  return onboarding_service_->ShouldShowOnboardingNotice();
+}
+
+TrackingProtectionNoticeService::TabHelper::TabHelper(
+    content::WebContents* web_contents)
+    : WebContentsObserver(web_contents),
+      content::WebContentsUserData<TrackingProtectionNoticeService::TabHelper>(
+          *web_contents) {}
+
+TrackingProtectionNoticeService::TabHelper::~TabHelper() = default;
+
+bool TrackingProtectionNoticeService::TabHelper::IsHelperNeeded(
+    Profile* profile) {
+  auto* notice_service =
+      TrackingProtectionNoticeFactory::GetForProfile(profile);
+  return notice_service && notice_service->IsNoticeNeeded();
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(TrackingProtectionNoticeService::TabHelper);
+
+}  // namespace privacy_sandbox
diff --git a/chrome/browser/privacy_sandbox/tracking_protection_notice_service.h b/chrome/browser/privacy_sandbox/tracking_protection_notice_service.h
new file mode 100644
index 0000000..41445bb
--- /dev/null
+++ b/chrome/browser/privacy_sandbox/tracking_protection_notice_service.h
@@ -0,0 +1,66 @@
+
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PRIVACY_SANDBOX_TRACKING_PROTECTION_NOTICE_SERVICE_H_
+#define CHROME_BROWSER_PRIVACY_SANDBOX_TRACKING_PROTECTION_NOTICE_SERVICE_H_
+
+#include "base/memory/raw_ptr.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/privacy_sandbox/tracking_protection_onboarding.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+#if BUILDFLAG(IS_ANDROID)
+#error This file should only be included on desktop.
+#endif
+
+class Profile;
+
+namespace privacy_sandbox {
+
+// A service which contains the logic tracking some user interactions with the
+// browser, in order to determine when the best time is to Show the Onboarding
+// Notice, then actually displays it.
+// If the profile is not to be shown the notice at all due to ineligibility,
+// then this service doesn't observe anything (Except the
+// TrackingProtectionOnboarding Service).
+class TrackingProtectionNoticeService : public KeyedService {
+ public:
+  TrackingProtectionNoticeService(
+      Profile* profile,
+      TrackingProtectionOnboarding* onboarding_service);
+  ~TrackingProtectionNoticeService() override;
+
+  class TabHelper : public content::WebContentsObserver,
+                    public content::WebContentsUserData<TabHelper> {
+   public:
+    TabHelper(const TabHelper&) = delete;
+    TabHelper& operator=(const TabHelper&) = delete;
+    ~TabHelper() override;
+
+    // Static method that tells us if the helper is needed. This is to be
+    // checked before creating the helper so we don't unnecessarily create one
+    // for every WebContent.
+    static bool IsHelperNeeded(Profile* profile);
+
+   private:
+    friend class content::WebContentsUserData<TabHelper>;
+    explicit TabHelper(content::WebContents* web_contents);
+
+    WEB_CONTENTS_USER_DATA_KEY_DECL();
+  };
+
+ private:
+  // Indicates if the notice is needed to be displayed.
+  bool IsNoticeNeeded();
+
+  raw_ptr<Profile> profile_;
+  raw_ptr<TrackingProtectionOnboarding> onboarding_service_;
+};
+
+}  // namespace privacy_sandbox
+
+#endif  // CHROME_BROWSER_PRIVACY_SANDBOX_TRACKING_PROTECTION_NOTICE_SERVICE_H_
diff --git a/chrome/browser/profiles/DEPS b/chrome/browser/profiles/DEPS
index f636b39..80e2e00 100644
--- a/chrome/browser/profiles/DEPS
+++ b/chrome/browser/profiles/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/live_caption:constants",
+  "+components/media_effects",
   "+components/profile_metrics",
   "+device/fido/cros/credential_store.h",
   "+device/fido/mac/credential_store.h",
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index b6bd15b..c41e8c8 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -206,6 +206,7 @@
 #include "components/commerce/core/proto/commerce_subscription_db_content.pb.h"
 #include "components/commerce/core/proto/persisted_state_db_content.pb.h"
 #include "components/enterprise/content/clipboard_restriction_service.h"
+#include "components/media_effects/media_effects_service_factory.h"
 #include "components/offline_pages/buildflags/buildflags.h"
 #include "components/omnibox/browser/autocomplete_controller_emitter.h"
 #include "components/optimization_guide/core/optimization_guide_switches.h"
@@ -442,6 +443,7 @@
 #include "chrome/browser/new_tab_page/one_google_bar/one_google_bar_service_factory.h"
 #include "chrome/browser/new_tab_page/promos/promo_service_factory.h"
 #include "chrome/browser/payments/payment_request_display_manager_factory.h"
+#include "chrome/browser/privacy_sandbox/tracking_protection_notice_factory.h"
 #include "chrome/browser/search/background/ntp_background_service_factory.h"
 #include "chrome/browser/search/background/ntp_custom_background_service_factory.h"
 #include "chrome/browser/serial/serial_chooser_context_factory.h"
@@ -817,6 +819,12 @@
 #if BUILDFLAG(IS_ANDROID)
   MediaDrmOriginIdManagerFactory::GetInstance();
 #endif
+
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
+  if (base::FeatureList::IsEnabled(media::kCameraMicEffects)) {
+    MediaEffectsServiceFactory::GetInstance();
+  }
+#endif
   if (MediaEngagementService::IsEnabled()) {
     MediaEngagementServiceFactory::GetInstance();
   }
@@ -1118,6 +1126,9 @@
   TopSitesFactory::GetInstance();
   tpcd::experiment::EligibilityServiceFactory::GetInstance();
   tpcd::metadata::UpdaterServiceFactory::GetInstance();
+#if !BUILDFLAG(IS_ANDROID)
+  TrackingProtectionNoticeFactory::GetInstance();
+#endif
   TrackingProtectionOnboardingFactory::GetInstance();
   TrackingProtectionSettingsFactory::GetInstance();
   translate::TranslateRankerFactory::GetInstance();
diff --git a/chrome/browser/quick_delete/android/junit/src/org/chromium/chrome/browser/quick_delete/QuickDeleteTabsFilterTest.java b/chrome/browser/quick_delete/android/junit/src/org/chromium/chrome/browser/quick_delete/QuickDeleteTabsFilterTest.java
index bfc2cd97..d8f55ca 100644
--- a/chrome/browser/quick_delete/android/junit/src/org/chromium/chrome/browser/quick_delete/QuickDeleteTabsFilterTest.java
+++ b/chrome/browser/quick_delete/android/junit/src/org/chromium/chrome/browser/quick_delete/QuickDeleteTabsFilterTest.java
@@ -31,7 +31,6 @@
 import org.chromium.chrome.browser.browsing_data.TimePeriod;
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 
 import java.util.ArrayList;
@@ -56,9 +55,7 @@
         // Create tabs.
         for (int id = 0; id < countOfTabs; id++) {
             MockTab mockTab = new MockTab(id, /*incognito=*/false);
-            CriticalPersistedTabData mockTabData = new CriticalPersistedTabData(mockTab);
             mockTab.setRootId(id);
-            mockTab.getUserDataHost().setUserData(CriticalPersistedTabData.class, mockTabData);
             mMockTabList.add(mockTab);
         }
         // Update the tab model.
diff --git a/chrome/browser/readaloud/android/BUILD.gn b/chrome/browser/readaloud/android/BUILD.gn
index 3e70876..cf8fb7f 100644
--- a/chrome/browser/readaloud/android/BUILD.gn
+++ b/chrome/browser/readaloud/android/BUILD.gn
@@ -49,6 +49,7 @@
     "java/res/drawable/baseline_replay_10_24.xml",
     "java/res/drawable/error_24.xml",
     "java/res/drawable/forward_30_button.xml",
+    "java/res/drawable/mini_pause_button.xml",
     "java/res/drawable/mini_play_button.xml",
     "java/res/drawable/pause_button.xml",
     "java/res/drawable/play_button.xml",
@@ -165,6 +166,7 @@
     "java/src/org/chromium/chrome/browser/readaloud/player/PlayerMediator.java",
     "java/src/org/chromium/chrome/browser/readaloud/player/PlayerProperties.java",
     "java/src/org/chromium/chrome/browser/readaloud/player/VisibilityState.java",
+    "java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java",
   ]
   deps = [
     ":java_resources",
@@ -184,7 +186,10 @@
 
 robolectric_library("player_junit_java") {
   testonly = true
-  sources = [ "java/src/org/chromium/chrome/browser/readaloud/player/PlayerCoordinatorUnitTest.java" ]
+  sources = [
+    "java/src/org/chromium/chrome/browser/readaloud/player/PlayerCoordinatorUnitTest.java",
+    "java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayoutUnitTest.java",
+  ]
   deps = [
     ":player_java",
     "//base:base_java",
@@ -193,6 +198,7 @@
     "//chrome/android/modules/readaloud/public:java",
     "//chrome/browser/tab:java",
     "//components/browser_ui/bottomsheet/android:java",
+    "//third_party/androidx:androidx_appcompat_appcompat_java",
     "//third_party/androidx:androidx_test_core_java",
     "//third_party/androidx:androidx_test_ext_junit_java",
     "//third_party/junit:junit",
diff --git a/chrome/browser/readaloud/android/java/res/drawable/mini_pause_button.xml b/chrome/browser/readaloud/android/java/res/drawable/mini_pause_button.xml
new file mode 100644
index 0000000..317a356
--- /dev/null
+++ b/chrome/browser/readaloud/android/java/res/drawable/mini_pause_button.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/primary_gray_rounded"/>
+    <item
+        android:drawable="@drawable/ic_pause_white_24dp"
+        android:left="12dp"
+        android:top="12dp"
+        android:right="12dp"
+        android:bottom="12dp"/>
+</layer-list>
\ No newline at end of file
diff --git a/chrome/browser/readaloud/android/java/res/layout/readaloud_mini_player_layout.xml b/chrome/browser/readaloud/android/java/res/layout/readaloud_mini_player_layout.xml
index 514ac66..5f7efbf 100644
--- a/chrome/browser/readaloud/android/java/res/layout/readaloud_mini_player_layout.xml
+++ b/chrome/browser/readaloud/android/java/res/layout/readaloud_mini_player_layout.xml
@@ -5,7 +5,8 @@
 found in the LICENSE file.
 -->
 
-<LinearLayout
+<!-- MiniPlayerLayout is a LinearLayout. -->
+<org.chromium.chrome.browser.readaloud.player.mini.MiniPlayerLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/readaloud_mini_player"
@@ -34,10 +35,11 @@
 
         <!-- Middle layout containing everything but the progress bar. -->
         <RelativeLayout
+            android:id="@+id/mini_player_background"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingHorizontal="16dp">
-            
+
             <!-- Buffering/unknown layout. -->
             <LinearLayout
                 android:id="@+id/buffering_layout"
@@ -56,7 +58,7 @@
                     android:layout_height="@dimen/readaloud_mini_player_play_button_diameter"
                     android:layout_marginVertical="@dimen/readaloud_mini_player_play_button_margin_vertical"
                     android:layout_marginEnd="@dimen/readaloud_mini_player_play_button_margin_end"/>
-    
+
                 <!-- Loading message -->
                 <TextView
                     android:id="@+id/loading_message"
@@ -144,8 +146,8 @@
                     android:layout_gravity="center_vertical"
                     android:paddingEnd="@dimen/readaloud_mini_player_text_padding_end"
                     android:orientation="vertical"
-                    android:clickable="true"
-                    android:focusable="true">
+                    android:clickable="false"
+                    android:focusable="false">
                     <TextView
                         android:id="@+id/title"
                         android:layout_width="match_parent"
@@ -162,7 +164,7 @@
                         android:maxLines="1"/>
                 </LinearLayout>
             </LinearLayout>
-            
+
             <!-- Close button -->
             <ImageView
                 android:id="@+id/close_button"
@@ -187,6 +189,7 @@
             android:max="1000"
             android:progress="0"
             android:progressTint="@macro/progress_bar_foreground"
-            android:progressTintMode="src_atop"/>
+            android:progressTintMode="src_atop"
+            android:visibility="gone"/>
     </FrameLayout>
-</LinearLayout>
\ No newline at end of file
+</org.chromium.chrome.browser.readaloud.player.mini.MiniPlayerLayout>
\ No newline at end of file
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java
new file mode 100644
index 0000000..fef93634
--- /dev/null
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java
@@ -0,0 +1,140 @@
+// Copyright 2023 The Chromium Authors
+// 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.readaloud.player.mini;
+
+import static org.chromium.chrome.modules.readaloud.PlaybackListener.State.BUFFERING;
+import static org.chromium.chrome.modules.readaloud.PlaybackListener.State.ERROR;
+import static org.chromium.chrome.modules.readaloud.PlaybackListener.State.PAUSED;
+import static org.chromium.chrome.modules.readaloud.PlaybackListener.State.PLAYING;
+import static org.chromium.chrome.modules.readaloud.PlaybackListener.State.STOPPED;
+import static org.chromium.chrome.modules.readaloud.PlaybackListener.State.UNKNOWN;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import org.chromium.chrome.browser.readaloud.player.InteractionHandler;
+import org.chromium.chrome.browser.readaloud.player.R;
+import org.chromium.chrome.modules.readaloud.PlaybackListener;
+
+/** Convenience class for manipulating mini player UI layout. */
+public class MiniPlayerLayout extends LinearLayout {
+    private TextView mTitle;
+    private TextView mPublisher;
+    private ProgressBar mProgressBar;
+    private ImageView mPlayPauseView;
+
+    // Layouts related to different playback states.
+    private LinearLayout mNormalLayout;
+    private LinearLayout mBufferingLayout;
+    private LinearLayout mErrorLayout;
+
+    private @PlaybackListener.State int mLastPlaybackState;
+
+    /** Constructor for inflating from XML. */
+    public MiniPlayerLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTitle = (TextView) findViewById(R.id.title);
+        mPublisher = (TextView) findViewById(R.id.publisher);
+        mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+        mPlayPauseView = (ImageView) findViewById(R.id.play_button);
+
+        mNormalLayout = (LinearLayout) findViewById(R.id.normal_layout);
+        mBufferingLayout = (LinearLayout) findViewById(R.id.buffering_layout);
+        mErrorLayout = (LinearLayout) findViewById(R.id.error_layout);
+
+        mLastPlaybackState = PlaybackListener.State.UNKNOWN;
+    }
+
+    void setTitle(String title) {
+        mTitle.setText(title);
+    }
+
+    void setPublisher(String publisher) {
+        mPublisher.setText(publisher);
+    }
+
+    /**
+     * Set progress bar progress.
+     * @param progress Fraction of playback completed in range [0, 1]
+     */
+    void setProgress(float progress) {
+        mProgressBar.setProgress((int) (progress * mProgressBar.getMax()), true);
+    }
+
+    void setInteractionHandler(InteractionHandler handler) {
+        setOnClickListener(R.id.close_button, handler::onCloseClick);
+        setOnClickListener(R.id.mini_player_background, handler::onMiniPlayerExpandClick);
+        setOnClickListener(R.id.play_button, handler::onPlayPauseClick);
+    }
+
+    void onPlaybackStateChanged(@PlaybackListener.State int state) {
+        switch (state) {
+            // UNKNOWN is currently the "reset" state and can be treated same as buffering.
+            case BUFFERING:
+            case UNKNOWN:
+                showOnly(mBufferingLayout);
+                mProgressBar.setVisibility(View.GONE);
+                break;
+
+            case ERROR:
+                showOnly(mErrorLayout);
+                mProgressBar.setVisibility(View.GONE);
+                break;
+
+            case PLAYING:
+                if (mLastPlaybackState != PLAYING && mLastPlaybackState != PAUSED) {
+                    showOnly(mNormalLayout);
+                    mProgressBar.setVisibility(View.VISIBLE);
+                }
+
+                mPlayPauseView.setImageResource(R.drawable.mini_pause_button);
+                mPlayPauseView.setContentDescription(
+                        getResources().getString(R.string.readaloud_pause));
+                break;
+
+            case PAUSED:
+                if (mLastPlaybackState != PLAYING && mLastPlaybackState != PAUSED) {
+                    showOnly(mNormalLayout);
+                    mProgressBar.setVisibility(View.VISIBLE);
+                }
+
+                mPlayPauseView.setImageResource(R.drawable.mini_play_button);
+                mPlayPauseView.setContentDescription(
+                        getResources().getString(R.string.readaloud_play));
+                break;
+
+            // TODO(b/301657446): handle this case
+            case STOPPED:
+            default:
+                break;
+        }
+        mLastPlaybackState = state;
+    }
+
+    // Show `layout` and hide the other two.
+    private void showOnly(LinearLayout layout) {
+        setVisibleIfMatch(mNormalLayout, layout);
+        setVisibleIfMatch(mBufferingLayout, layout);
+        setVisibleIfMatch(mErrorLayout, layout);
+    }
+
+    private static void setVisibleIfMatch(LinearLayout a, LinearLayout b) {
+        a.setVisibility(a == b ? View.VISIBLE : View.GONE);
+    }
+
+    private void setOnClickListener(int id, Runnable handler) {
+        findViewById(id).setOnClickListener((v) -> { handler.run(); });
+    }
+}
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayoutUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayoutUnitTest.java
new file mode 100644
index 0000000..98dae7c
--- /dev/null
+++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayoutUnitTest.java
@@ -0,0 +1,155 @@
+// Copyright 2023 The Chromium Authors
+// 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.readaloud.player.mini;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.view.View;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.readaloud.player.InteractionHandler;
+import org.chromium.chrome.browser.readaloud.player.R;
+import org.chromium.chrome.modules.readaloud.PlaybackListener;
+
+/** Unit tests for {@link PlayerCoordinator}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class MiniPlayerLayoutUnitTest {
+    private final Activity mActivity;
+    private final MiniPlayerLayout mLayout;
+
+    @Mock
+    private InteractionHandler mInteractionHandler;
+
+    public MiniPlayerLayoutUnitTest() {
+        mActivity = Robolectric.buildActivity(AppCompatActivity.class).setup().get();
+        // Need to set theme before inflating layout.
+        mActivity.setTheme(R.style.Theme_BrowserUI_DayNight);
+        mLayout = (MiniPlayerLayout) mActivity.getLayoutInflater().inflate(
+                R.layout.readaloud_mini_player_layout, null);
+        assertNotNull(mLayout);
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testDefaultStateIsBuffering() {
+        assertEquals(View.GONE, mLayout.findViewById(R.id.progress_bar).getVisibility());
+
+        // Only the buffering layout is visible.
+        assertEquals(View.VISIBLE, mLayout.findViewById(R.id.buffering_layout).getVisibility());
+        assertEquals(View.GONE, mLayout.findViewById(R.id.normal_layout).getVisibility());
+        assertEquals(View.GONE, mLayout.findViewById(R.id.error_layout).getVisibility());
+    }
+
+    @Test
+    public void testPlayingState() {
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.PLAYING);
+
+        assertEquals(View.VISIBLE, mLayout.findViewById(R.id.progress_bar).getVisibility());
+
+        // Only the "normal" layout is visible.
+        assertEquals(View.GONE, mLayout.findViewById(R.id.buffering_layout).getVisibility());
+        assertEquals(View.VISIBLE, mLayout.findViewById(R.id.normal_layout).getVisibility());
+        assertEquals(View.GONE, mLayout.findViewById(R.id.error_layout).getVisibility());
+
+        // Can't directly test the play button drawable so instead check the a11y string.
+        assertEquals("Pause", mLayout.findViewById(R.id.play_button).getContentDescription());
+    }
+
+    @Test
+    public void testPausedState() {
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.PAUSED);
+
+        assertEquals(View.VISIBLE, mLayout.findViewById(R.id.progress_bar).getVisibility());
+
+        // Only the "normal" layout is visible.
+        assertEquals(View.GONE, mLayout.findViewById(R.id.buffering_layout).getVisibility());
+        assertEquals(View.VISIBLE, mLayout.findViewById(R.id.normal_layout).getVisibility());
+        assertEquals(View.GONE, mLayout.findViewById(R.id.error_layout).getVisibility());
+
+        // Can't directly test the play button drawable so instead check the a11y string.
+        assertEquals("Play", mLayout.findViewById(R.id.play_button).getContentDescription());
+    }
+
+    @Test
+    public void testErrorState() {
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.ERROR);
+
+        assertEquals(View.GONE, mLayout.findViewById(R.id.progress_bar).getVisibility());
+
+        // Only the error layout is visible.
+        assertEquals(View.GONE, mLayout.findViewById(R.id.buffering_layout).getVisibility());
+        assertEquals(View.GONE, mLayout.findViewById(R.id.normal_layout).getVisibility());
+        assertEquals(View.VISIBLE, mLayout.findViewById(R.id.error_layout).getVisibility());
+    }
+
+    @Test
+    public void testSetTitle() {
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.PLAYING);
+        mLayout.setTitle("Title");
+        assertEquals("Title", ((TextView) mLayout.findViewById(R.id.title)).getText());
+    }
+
+    @Test
+    public void testSetPublisher() {
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.PLAYING);
+        mLayout.setPublisher("Publisher");
+        assertEquals("Publisher", ((TextView) mLayout.findViewById(R.id.publisher)).getText());
+    }
+
+    @Test
+    public void testSetProgress() {
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.PLAYING);
+        mLayout.setProgress(0.5f);
+        // Progress values range from 0 to 1000.
+        assertEquals(500, ((ProgressBar) mLayout.findViewById(R.id.progress_bar)).getProgress());
+    }
+
+    @Test
+    public void testCloseButtonClick() {
+        mLayout.setInteractionHandler(mInteractionHandler);
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.PLAYING);
+
+        assertTrue(mLayout.findViewById(R.id.close_button).performClick());
+        verify(mInteractionHandler).onCloseClick();
+    }
+
+    @Test
+    public void testExpandClick() {
+        mLayout.setInteractionHandler(mInteractionHandler);
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.PLAYING);
+
+        assertTrue(mLayout.findViewById(R.id.mini_player_background).performClick());
+        verify(mInteractionHandler).onMiniPlayerExpandClick();
+    }
+
+    @Test
+    public void testPlayButtonClick() {
+        mLayout.setInteractionHandler(mInteractionHandler);
+        mLayout.onPlaybackStateChanged(PlaybackListener.State.PLAYING);
+
+        assertTrue(mLayout.findViewById(R.id.play_button).performClick());
+        verify(mInteractionHandler).onPlayPauseClick();
+    }
+}
diff --git a/chrome/browser/resources/ash/settings/common/load_time_booleans.ts b/chrome/browser/resources/ash/settings/common/load_time_booleans.ts
index bea5768..9a8eddf1 100644
--- a/chrome/browser/resources/ash/settings/common/load_time_booleans.ts
+++ b/chrome/browser/resources/ash/settings/common/load_time_booleans.ts
@@ -54,6 +54,10 @@
   return loadTimeData.getBoolean('isExternalStorageEnabled');
 }
 
+export function isInputDeviceSettingsSplitEnabled(): boolean {
+  return loadTimeData.getBoolean('enableInputDeviceSettingsSplit');
+}
+
 // Kerberos page
 export function isKerberosEnabled(): boolean {
   return loadTimeData.getBoolean('isKerberosEnabled');
diff --git a/chrome/browser/resources/ash/settings/device_page/device_page.html b/chrome/browser/resources/ash/settings/device_page/device_page.html
index 40067d2..65f0d61 100644
--- a/chrome/browser/resources/ash/settings/device_page/device_page.html
+++ b/chrome/browser/resources/ash/settings/device_page/device_page.html
@@ -10,6 +10,7 @@
     margin-inline-end: 8px;
   }
 </style>
+
 <os-settings-animated-pages id="pages" section="[[section_]]">
   <div id="main" route-path="default">
     <settings-card header-text="$i18n{devicePageTitle}">
@@ -219,6 +220,7 @@
       </settings-customize-mouse-buttons-subpage>
     </os-settings-subpage>
   </template>
+
   <template is="dom-if" if="[[!isRevampWayfindingEnabled_]]">
     <template is="dom-if" route-path="/storage">
       <os-settings-subpage page-title="$i18n{storageTitle}">
@@ -241,8 +243,41 @@
     </template>
   </template>
 
-  <!-- Printing cups printers subpage -->
   <template is="dom-if" if="[[isRevampWayfindingEnabled_]]">
+    <!-- Input subpages -->
+    <template is="dom-if" route-path="/osLanguages/input">
+      <os-settings-subpage page-title="$i18n{inputPageTitle}">
+        <os-settings-input-page prefs="{{prefs}}"
+            languages="[[languages]]"
+            language-helper="[[languageHelper]]">
+        </os-settings-input-page>
+      </os-settings-subpage>
+    </template>
+
+    <template is="dom-if" route-path="/osLanguages/inputMethodOptions">
+      <os-settings-subpage>
+        <settings-input-method-options-page prefs="{{prefs}}"
+            language-helper="[[languageHelper]]">
+        </settings-input-method-options-page>
+      </os-settings-subpage>
+    </template>
+
+    <template is="dom-if" route-path="/osLanguages/editDictionary">
+      <os-settings-subpage page-title="$i18n{editDictionaryLabel}">
+        <os-settings-edit-dictionary-page></os-settings-edit-dictionary-page>
+      </os-settings-subpage>
+    </template>
+
+    <template is="dom-if"
+        route-path="/osLanguages/japaneseManageUserDictionary">
+      <os-settings-subpage
+          page-title="$i18n{japaneseManageUserDictionaryLabel}">
+        <os-settings-japanese-manage-user-dictionary-page>
+        </os-settings-japanese-manage-user-dictionary-page>
+      </os-settings-subpage>
+    </template>
+
+    <!-- Printing cups printers subpage -->
     <template is="dom-if" route-path="/cupsPrinters">
       <os-settings-subpage
           page-title="$i18n{cupsPrintTitle}"
diff --git a/chrome/browser/resources/ash/settings/device_page/device_page.ts b/chrome/browser/resources/ash/settings/device_page/device_page.ts
index 6f03352..288abc5 100644
--- a/chrome/browser/resources/ash/settings/device_page/device_page.ts
+++ b/chrome/browser/resources/ash/settings/device_page/device_page.ts
@@ -37,10 +37,12 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {isExternalStorageEnabled, isRevampWayfindingEnabled} from '../common/load_time_booleans.js';
+import {isExternalStorageEnabled, isInputDeviceSettingsSplitEnabled, isRevampWayfindingEnabled} from '../common/load_time_booleans.js';
+import {PrefsState} from '../common/types.js';
 import {KeyboardPolicies, MousePolicies} from '../mojom-webui/input_device_settings.mojom-webui.js';
 import {GraphicsTabletSettingsObserverReceiver, KeyboardSettingsObserverReceiver, MouseSettingsObserverReceiver, PointingStickSettingsObserverReceiver, TouchpadSettingsObserverReceiver} from '../mojom-webui/input_device_settings_provider.mojom-webui.js';
 import {Section} from '../mojom-webui/routes.mojom-webui.js';
+import {LanguageHelper, LanguagesModel} from '../os_languages_page/languages_types.js';
 import {RouteOriginMixin} from '../route_origin_mixin.js';
 import {Route, Router, routes} from '../router.js';
 
@@ -54,7 +56,7 @@
 const SettingsDevicePageElementBase =
     RouteOriginMixin(I18nMixin(WebUiListenerMixin(PolymerElement)));
 
-class SettingsDevicePageElement extends SettingsDevicePageElementBase {
+export class SettingsDevicePageElement extends SettingsDevicePageElementBase {
   static get is() {
     return 'settings-device-page' as const;
   }
@@ -109,7 +111,7 @@
       isDeviceSettingsSplitEnabled_: {
         type: Boolean,
         value() {
-          return loadTimeData.getBoolean('enableInputDeviceSettingsSplit');
+          return isInputDeviceSettingsSplitEnabled();
         },
         readOnly: true,
       },
@@ -180,6 +182,16 @@
       graphicsTablets: {
         type: Array,
       },
+
+      /**
+       * Set of languages from <settings-languages>
+       */
+      languages: Object,
+
+      /**
+       * Language helper API from <settings-languages>
+       */
+      languageHelper: Object,
     };
   }
 
@@ -192,6 +204,10 @@
     ];
   }
 
+  languages: LanguagesModel|undefined;
+  languageHelper: LanguageHelper|undefined;
+  prefs: PrefsState|undefined;
+
   protected pointingSticks: PointingStick[];
   protected keyboards: Keyboard[];
   protected keyboardPolicies: KeyboardPolicies;
diff --git a/chrome/browser/resources/ash/settings/device_page/keyboard.html b/chrome/browser/resources/ash/settings/device_page/keyboard.html
index 3effdd4..af60a390 100644
--- a/chrome/browser/resources/ash/settings/device_page/keyboard.html
+++ b/chrome/browser/resources/ash/settings/device_page/keyboard.html
@@ -156,8 +156,9 @@
     on-click="onShowKeyboardShortcutViewerClick_"
     label="$i18n{showKeyboardShortcutViewer}"
     external
-    deep-link-focus-id$="[[Setting.kKeyboardShortcuts]]"></cr-link-row>
-<cr-link-row id="showLanguagesInput"
+    deep-link-focus-id$="[[Setting.kKeyboardShortcuts]]">
+</cr-link-row>
+<cr-link-row id="inputRow"
     class="hr" on-click="onShowInputSettingsClick_"
     label="$i18n{keyboardShowInputSettings}"
     role-description="$i18n{subpageArrowRoleDescription}">
diff --git a/chrome/browser/resources/ash/settings/device_page/keyboard.ts b/chrome/browser/resources/ash/settings/device_page/keyboard.ts
index 77163c3..c3536b5b 100644
--- a/chrome/browser/resources/ash/settings/device_page/keyboard.ts
+++ b/chrome/browser/resources/ash/settings/device_page/keyboard.ts
@@ -19,6 +19,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {isInputDeviceSettingsSplitEnabled} from '../common/load_time_booleans.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {Setting} from '../mojom-webui/setting.mojom-webui.js';
 import {RouteOriginMixin} from '../route_origin_mixin.js';
@@ -136,7 +137,7 @@
       isDeviceSettingsSplitEnabled_: {
         type: Boolean,
         value() {
-          return loadTimeData.getBoolean('enableInputDeviceSettingsSplit');
+          return isInputDeviceSettingsSplitEnabled();
         },
         readOnly: true,
       },
@@ -171,7 +172,7 @@
     this.browserProxy_.initializeKeyboard();
     this.setUpKeyMapTargets_();
 
-    this.addFocusConfig(routes.OS_LANGUAGES_INPUT, '#showLanguagesInput');
+    this.addFocusConfig(routes.OS_LANGUAGES_INPUT, '#inputRow');
   }
 
   override currentRouteChanged(newRoute: Route, oldRoute?: Route) {
diff --git a/chrome/browser/resources/ash/settings/device_page/per_device_keyboard.html b/chrome/browser/resources/ash/settings/device_page/per_device_keyboard.html
index b3df2a3c..e67d1b6 100644
--- a/chrome/browser/resources/ash/settings/device_page/per_device_keyboard.html
+++ b/chrome/browser/resources/ash/settings/device_page/per_device_keyboard.html
@@ -112,7 +112,7 @@
     external
     deep-link-focus-id$="[[Setting.kKeyboardShortcuts]]">
 </cr-link-row>
-<cr-link-row id="showLanguagesInput"
+<cr-link-row id="inputRow"
     class="hr" on-click="onShowInputSettingsClick"
     label="$i18n{keyboardShowInputSettings}"
     role-description="$i18n{subpageArrowRoleDescription}">
diff --git a/chrome/browser/resources/ash/settings/device_page/pointers.ts b/chrome/browser/resources/ash/settings/device_page/pointers.ts
index be03d07..60ca984 100644
--- a/chrome/browser/resources/ash/settings/device_page/pointers.ts
+++ b/chrome/browser/resources/ash/settings/device_page/pointers.ts
@@ -20,6 +20,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {isInputDeviceSettingsSplitEnabled} from '../common/load_time_booleans.js';
 import {DeepLinkingMixin} from '../deep_linking_mixin.js';
 import {Setting} from '../mojom-webui/setting.mojom-webui.js';
 import {RouteObserverMixin} from '../route_observer_mixin.js';
@@ -135,7 +136,7 @@
       isDeviceSettingsSplitEnabled_: {
         type: Boolean,
         value() {
-          return loadTimeData.getBoolean('enableInputDeviceSettingsSplit');
+          return isInputDeviceSettingsSplitEnabled();
         },
         readOnly: true,
       },
diff --git a/chrome/browser/resources/ash/settings/main_page_container/main_page_container.html b/chrome/browser/resources/ash/settings/main_page_container/main_page_container.html
index bc3e4d8..eb702ff 100644
--- a/chrome/browser/resources/ash/settings/main_page_container/main_page_container.html
+++ b/chrome/browser/resources/ash/settings/main_page_container/main_page_container.html
@@ -187,7 +187,9 @@
         if="[[shouldStampPage_(pageAvailability, Section.kDevice)]]"
         restamp>
       <page-displayer section="[[Section.kDevice]]">
-        <settings-device-page prefs="{{prefs}}">
+        <settings-device-page prefs="{{prefs}}"
+            languages="[[languages_]]"
+            language-helper="[[languageHelper_]]">
         </settings-device-page>
       </page-displayer>
     </template>
diff --git a/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_device_detail_subpage.ts b/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_device_detail_subpage.ts
index 1c66a12..9e350a1 100644
--- a/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_device_detail_subpage.ts
+++ b/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_device_detail_subpage.ts
@@ -26,6 +26,7 @@
 import {AudioOutputCapability, BluetoothSystemProperties, DeviceConnectionState, DeviceType, PairedBluetoothDeviceProperties} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {isInputDeviceSettingsSplitEnabled} from '../common/load_time_booleans.js';
 import {OsSettingsSubpageElement} from '../os_settings_page/os_settings_subpage.js';
 import {RouteOriginMixin} from '../route_origin_mixin.js';
 import {Route, Router, routes} from '../router.js';
@@ -129,7 +130,7 @@
     this.addEventListener(
         'forget-bluetooth-device', this.forgetDeviceConfirmed_);
 
-    if (loadTimeData.getBoolean('enableInputDeviceSettingsSplit')) {
+    if (isInputDeviceSettingsSplitEnabled()) {
       this.addFocusConfig(routes.PER_DEVICE_MOUSE, '#changeMouseSettings');
       this.addFocusConfig(
           routes.PER_DEVICE_KEYBOARD, '#changeKeyboardSettings');
@@ -513,7 +514,7 @@
   }
 
   private onMouseRowClick_(): void {
-    if (loadTimeData.getBoolean('enableInputDeviceSettingsSplit')) {
+    if (isInputDeviceSettingsSplitEnabled()) {
       Router.getInstance().navigateTo(routes.PER_DEVICE_MOUSE);
     } else {
       Router.getInstance().navigateTo(routes.POINTERS);
@@ -521,7 +522,7 @@
   }
 
   private onKeyboardRowClick_(): void {
-    if (loadTimeData.getBoolean('enableInputDeviceSettingsSplit')) {
+    if (isInputDeviceSettingsSplitEnabled()) {
       Router.getInstance().navigateTo(routes.PER_DEVICE_KEYBOARD);
     } else {
       Router.getInstance().navigateTo(routes.KEYBOARD);
diff --git a/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.html b/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.html
index 3e98d3f..b21a0372 100644
--- a/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.html
+++ b/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.html
@@ -54,7 +54,6 @@
           </div>
         </div>
         <controlled-button id="addShareButton"
-            class="action-button"
             on-click="openAddSmbDialog_"
             label="$i18n{addSmbShare}"
             disabled="[[!prefs.network_file_shares.allowed.value]]"
diff --git a/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.ts b/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.ts
index 52f1f9e2..6b398c83 100644
--- a/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.ts
+++ b/chrome/browser/resources/ash/settings/os_files_page/files_settings_card.ts
@@ -66,7 +66,6 @@
         readOnly: true,
       },
 
-
       isRevampWayfindingEnabled_: {
         type: Boolean,
         value: () => {
diff --git a/chrome/browser/resources/ash/settings/os_files_page/smb_shares_page.html b/chrome/browser/resources/ash/settings/os_files_page/smb_shares_page.html
index 76fb6e76..b93d87b 100644
--- a/chrome/browser/resources/ash/settings/os_files_page/smb_shares_page.html
+++ b/chrome/browser/resources/ash/settings/os_files_page/smb_shares_page.html
@@ -13,7 +13,7 @@
         icon-aria-label="$i18n{smbSharesTitle}">
     </cr-policy-pref-indicator>
   </template>
-  <cr-button class="action-button" id="addShare"
+  <cr-button id="addShare"
       on-click="onAddShareClick_"
       disabled="[[!prefs.network_file_shares.allowed.value]]">
     $i18n{addSmbShare}
diff --git a/chrome/browser/resources/ash/settings/os_people_page/account_manager_subpage.ts b/chrome/browser/resources/ash/settings/os_people_page/account_manager_subpage.ts
index a153d6e..6927d23 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/account_manager_subpage.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/account_manager_subpage.ts
@@ -291,7 +291,7 @@
     return this.accounts_.filter(account => !account.isDeviceAccount);
   }
 
-  private onReauthenticationClick_(event: DomRepeatEvent<Account>) {
+  private onReauthenticationClick_(event: DomRepeatEvent<Account>): void {
     if (event.model.item.unmigrated) {
       this.browserProxy_.migrateAccount(event.model.item.email);
     } else {
@@ -316,7 +316,8 @@
     this.deviceAccount_ = deviceAccount;
   }
 
-  private onAccountActionsMenuButtonClick_(event: DomRepeatEvent<Account>) {
+  private onAccountActionsMenuButtonClick_(event: DomRepeatEvent<Account>):
+      void {
     this.actionMenuAccount_ = event.model.item;
 
     assertInstanceof(event.target, HTMLElement);
diff --git a/chrome/browser/resources/ash/settings/os_people_page/fingerprint_list_subpage.ts b/chrome/browser/resources/ash/settings/os_people_page/fingerprint_list_subpage.ts
index ae6a660..7236487 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/fingerprint_list_subpage.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/fingerprint_list_subpage.ts
@@ -114,7 +114,7 @@
     return false;
   }
 
-  override currentRouteChanged(newRoute: Route) {
+  override currentRouteChanged(newRoute: Route): void {
     if (newRoute !== routes.FINGERPRINT) {
       this.showSetupFingerprintDialog_ = false;
       return;
diff --git a/chrome/browser/resources/ash/settings/os_people_page/lock_screen_password_prompt_dialog.ts b/chrome/browser/resources/ash/settings/os_people_page/lock_screen_password_prompt_dialog.ts
index be174402..6ca42fec8 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/lock_screen_password_prompt_dialog.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/lock_screen_password_prompt_dialog.ts
@@ -42,7 +42,7 @@
     return {};
   }
 
-  override connectedCallback() {
+  override connectedCallback(): void {
     super.connectedCallback();
 
     recordLockScreenProgress(LockScreenProgress.START_SCREEN_LOCK);
diff --git a/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts b/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts
index c7939eb9..ae929ca 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts
@@ -237,13 +237,13 @@
     this.authFactorConfig.observeFactorChanges(remote);
   }
 
-  override connectedCallback() {
+  override connectedCallback(): void {
     super.connectedCallback();
 
     this.updateNumFingerprints_();
   }
 
-  override currentRouteChanged(newRoute: Route) {
+  override currentRouteChanged(newRoute: Route): void {
     if (newRoute === routes.LOCK_SCREEN) {
       this.updateNumFingerprints_();
       this.attemptDeepLink();
diff --git a/chrome/browser/resources/ash/settings/os_people_page/os_personalization_options.ts b/chrome/browser/resources/ash/settings/os_people_page/os_personalization_options.ts
index 29faca7..b52be07 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/os_personalization_options.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/os_personalization_options.ts
@@ -68,7 +68,7 @@
   }
 
   // <if expr="_google_chrome">
-  private onUseSpellingServiceToggle_(event: Event) {
+  private onUseSpellingServiceToggle_(event: Event): void {
     // If turning on using the spelling service, automatically turn on
     // spellcheck so that the spelling service can run.
     if ((event.target as SettingsToggleButtonElement).checked) {
diff --git a/chrome/browser/resources/ash/settings/os_people_page/os_sync_controls_subpage.ts b/chrome/browser/resources/ash/settings/os_people_page/os_sync_controls_subpage.ts
index eeee1e2..7485172 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/os_sync_controls_subpage.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/os_sync_controls_subpage.ts
@@ -168,8 +168,8 @@
   /**
    * Called when the sync data radio button selection changes.
    */
-  private onSyncDataRadioSelectionChanged_(event:
-                                               CustomEvent<{value: string}>) {
+  private onSyncDataRadioSelectionChanged_(event: CustomEvent<{value: string}>):
+      void {
     assertExists(this.osSyncPrefs);
     const syncAllDataTypes =
         event.detail.value === RadioButtonNames.SYNC_EVERYTHING;
@@ -195,7 +195,8 @@
   /**
    * Called when the link to the browser's sync settings is clicked.
    */
-  private onBrowserSyncSettingsClicked_(event: CustomEvent<{event: Event}>) {
+  private onBrowserSyncSettingsClicked_(event: CustomEvent<{event: Event}>):
+      void {
     // Prevent the default link click behavior.
     event.detail.event.preventDefault();
 
diff --git a/chrome/browser/resources/ash/settings/os_people_page/os_sync_encryption_options.ts b/chrome/browser/resources/ash/settings/os_people_page/os_sync_encryption_options.ts
index 21e3b1c..2a8034d 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/os_sync_encryption_options.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/os_sync_encryption_options.ts
@@ -129,7 +129,7 @@
         (this.syncStatus && this.syncStatus.supervisedUser));
   }
 
-  private disableEncryptionOptionsChanged_() {
+  private disableEncryptionOptionsChanged_(): void {
     if (this.disableEncryptionOptions_) {
       this.creatingNewPassphrase_ = false;
     }
@@ -145,21 +145,21 @@
     return passphrase !== '' && confirmation !== '';
   }
 
-  private onNewPassphraseInputKeypress_(e: KeyboardEvent) {
+  private onNewPassphraseInputKeypress_(e: KeyboardEvent): void {
     if (e.type === 'keypress' && e.key !== 'Enter') {
       return;
     }
     this.saveNewPassphrase_();
   }
 
-  private onSaveNewPassphraseClick_() {
+  private onSaveNewPassphraseClick_(): void {
     this.saveNewPassphrase_();
   }
 
   /**
    * Sends the newly created custom sync passphrase to the browser.
    */
-  private saveNewPassphrase_() {
+  private saveNewPassphrase_(): void {
     assert(this.creatingNewPassphrase_);
     chrome.metricsPrivate.recordUserAction('Sync_SaveNewPassphraseClicked');
 
@@ -189,8 +189,8 @@
         });
   }
 
-  private onEncryptionRadioSelectionChanged_(event:
-                                                 CustomEvent<{value: string}>) {
+  private onEncryptionRadioSelectionChanged_(
+      event: CustomEvent<{value: string}>): void {
     this.creatingNewPassphrase_ =
         event.detail.value === RadioButtonNames.ENCRYPT_WITH_PASSPHRASE;
   }
@@ -198,7 +198,7 @@
   /**
    * Computed binding returning the selected encryption radio button.
    */
-  private selectedEncryptionRadio_() {
+  private selectedEncryptionRadio_(): RadioButtonNames {
     return this.syncPrefs!.encryptAllData || this.creatingNewPassphrase_ ?
         RadioButtonNames.ENCRYPT_WITH_PASSPHRASE :
         RadioButtonNames.ENCRYPT_WITH_GOOGLE;
@@ -224,7 +224,7 @@
     return !emptyPassphrase && !mismatchedPassphrase;
   }
 
-  private onLearnMoreClick_(event: Event) {
+  private onLearnMoreClick_(event: Event): void {
     if ((event.target as HTMLElement).tagName === 'A') {
       // Stop the propagation of events, so that clicking on links inside
       // checkboxes or radio buttons won't change the value.
diff --git a/chrome/browser/resources/ash/settings/os_people_page/os_sync_subpage.ts b/chrome/browser/resources/ash/settings/os_people_page/os_sync_subpage.ts
index 3118a0a1..9ba5c2f1 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/os_sync_subpage.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/os_sync_subpage.ts
@@ -244,7 +244,7 @@
     this.setupCancelConfirmed_ = false;
   }
 
-  override connectedCallback() {
+  override connectedCallback(): void {
     super.connectedCallback();
 
     this.addWebUiListener(
@@ -258,7 +258,7 @@
     }
   }
 
-  override disconnectedCallback() {
+  override disconnectedCallback(): void {
     super.disconnectedCallback();
 
     const router = Router.getInstance();
@@ -347,7 +347,7 @@
     return expectedPageStatus === this.pageStatus_;
   }
 
-  private onNavigateToPage_() {
+  private onNavigateToPage_(): void {
     assert(Router.getInstance().currentRoute === this.route);
     if (this.beforeunloadCallback_) {
       return;
@@ -376,7 +376,7 @@
     window.addEventListener('unload', this.unloadCallback_);
   }
 
-  private onNavigateAwayFromPage_() {
+  private onNavigateAwayFromPage_(): void {
     if (!this.beforeunloadCallback_) {
       return;
     }
@@ -399,7 +399,7 @@
   /**
    * Handler for when the sync preferences are updated.
    */
-  private handleSyncPrefsChanged_(syncPrefs: SyncPrefs) {
+  private handleSyncPrefsChanged_(syncPrefs: SyncPrefs): void {
     this.syncPrefs = syncPrefs;
     this.pageStatus_ = PageStatus.CONFIGURE;
   }
@@ -422,7 +422,7 @@
     return this.i18n('syncAdvancedPageTitle');
   }
 
-  private onSyncDashboardLinkClick_() {
+  private onSyncDashboardLinkClick_(): void {
     window.open(loadTimeData.getString('syncDashboardUrl'));
   }
 
@@ -467,7 +467,7 @@
   /**
    * Whether the encryption dropdown should be expanded by default.
    */
-  private expandEncryptionIfNeeded_() {
+  private expandEncryptionIfNeeded_(): void {
     // Force the dropdown to expand.
     if (this.forceEncryptionExpanded) {
       this.forceEncryptionExpanded = false;
@@ -478,7 +478,7 @@
     this.encryptionExpanded_ = this.dataEncrypted_;
   }
 
-  private onResetSyncClick_(event: Event) {
+  private onResetSyncClick_(event: Event): void {
     if ((event.target as HTMLElement).tagName === 'A') {
       // Stop the propagation of events as the |cr-expand-button|
       // prevents the default which will prevent the navigation to the link.
@@ -489,7 +489,7 @@
   /**
    * Sends the user-entered existing password to re-enable sync.
    */
-  private onSubmitExistingPassphraseClick_(e: KeyboardEvent) {
+  private onSubmitExistingPassphraseClick_(e: KeyboardEvent): void {
     if (e.type === 'keypress' && e.key !== 'Enter') {
       return;
     }
@@ -502,7 +502,7 @@
     this.existingPassphrase_ = '';
   }
 
-  private onPassphraseChanged_(e: CustomEvent<{didChange: boolean}>) {
+  private onPassphraseChanged_(e: CustomEvent<{didChange: boolean}>): void {
     this.handlePageStatusChanged_(
         this.computePageStatusAfterPassphraseChange_(e.detail.didChange));
   }
@@ -523,7 +523,7 @@
   /**
    * Called when the page status updates.
    */
-  private handlePageStatusChanged_(pageStatus: PageStatus) {
+  private handlePageStatusChanged_(pageStatus: PageStatus): void {
     const router = Router.getInstance();
     switch (pageStatus) {
       case PageStatus.SPINNER:
@@ -550,7 +550,7 @@
     }
   }
 
-  private onLearnMoreClick_(event: Event) {
+  private onLearnMoreClick_(event: Event): void {
     if ((event.target as HTMLElement).tagName === 'A') {
       // Stop the propagation of events, so that clicking on links inside
       // checkboxes or radio buttons won't change the value.
@@ -563,7 +563,7 @@
         this.syncPrefs !== undefined && !!this.syncPrefs.passphraseRequired;
   }
 
-  private onSyncAdvancedClick_() {
+  private onSyncAdvancedClick_(): void {
     const router = Router.getInstance();
     router.navigateTo(routes.OS_SYNC);
   }
@@ -572,7 +572,7 @@
    * Focuses the passphrase input element if it is available and the page is
    * visible.
    */
-  private focusPassphraseInput_() {
+  private focusPassphraseInput_(): void {
     const passphraseInput = this.shadowRoot!.querySelector<CrInputElement>(
         '#existingPassphraseInput');
     const router = Router.getInstance();
diff --git a/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts b/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts
index a23495bf2..6c97329 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts
@@ -155,7 +155,7 @@
     return el;
   }
 
-  private openSetLocalPasswordDialog_() {
+  private openSetLocalPasswordDialog_(): void {
     this.setLocalPasswordDialog().showModal();
   }
 }
diff --git a/chrome/browser/resources/ash/settings/os_people_page/pin_autosubmit_dialog.ts b/chrome/browser/resources/ash/settings/os_people_page/pin_autosubmit_dialog.ts
index 6ac3521..c6f4cc2 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/pin_autosubmit_dialog.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/pin_autosubmit_dialog.ts
@@ -118,7 +118,7 @@
     ];
   }
 
-  override connectedCallback() {
+  override connectedCallback(): void {
     super.connectedCallback();
 
     this.resetState();
diff --git a/chrome/browser/resources/ash/settings/os_people_page/set_local_password_dialog.ts b/chrome/browser/resources/ash/settings/os_people_page/set_local_password_dialog.ts
index 5640cca..c6a1ba0 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/set_local_password_dialog.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/set_local_password_dialog.ts
@@ -47,7 +47,7 @@
   public authToken: string|null;
   private showError_: boolean;
 
-  override ready() {
+  override ready(): void {
     super.ready();
 
     // Dynamic checks to make sure that our static type declaration about named
diff --git a/chrome/browser/resources/ash/settings/os_people_page/setup_pin_dialog.ts b/chrome/browser/resources/ash/settings/os_people_page/setup_pin_dialog.ts
index c7806c31..e897c61a 100644
--- a/chrome/browser/resources/ash/settings/os_people_page/setup_pin_dialog.ts
+++ b/chrome/browser/resources/ash/settings/os_people_page/setup_pin_dialog.ts
@@ -71,7 +71,7 @@
   private isConfirmStep_: boolean;
   private quickUnlockPrivate: Object;
 
-  override connectedCallback() {
+  override connectedCallback(): void {
     super.connectedCallback();
 
     this.$.dialog.showModal();
diff --git a/chrome/browser/resources/ash/settings/os_settings.ts b/chrome/browser/resources/ash/settings/os_settings.ts
index 8f6ff78..10f6e1d0 100644
--- a/chrome/browser/resources/ash/settings/os_settings.ts
+++ b/chrome/browser/resources/ash/settings/os_settings.ts
@@ -126,6 +126,7 @@
 export {PrefsState} from './common/types.js';
 export {SettingsAudioElement} from './device_page/audio.js';
 export {setCrosAudioConfigForTesting} from './device_page/cros_audio_config.js';
+export {SettingsDevicePageElement} from './device_page/device_page.js';
 export {DevicePageBrowserProxy, DevicePageBrowserProxyImpl, IdleBehavior, LidClosedBehavior, NoteAppInfo, NoteAppLockScreenSupport, setDisplayApiForTesting, StorageSpaceState} from './device_page/device_page_browser_proxy.js';
 export * as fakeCrosAudioConfig from './device_page/fake_cros_audio_config.js';
 export {fakeGraphicsTabletButtonActions, fakeGraphicsTablets, fakeKeyboards, fakeKeyboards2, fakeMice, fakeMice2, fakeMouseButtonActions, fakePointingSticks, fakePointingSticks2, fakeStyluses, fakeTouchpads, fakeTouchpads2} from './device_page/fake_input_device_data.js';
diff --git a/chrome/browser/resources/ash/settings/os_settings_menu/menu_item.html b/chrome/browser/resources/ash/settings/os_settings_menu/menu_item.html
index 9faf7df7..057e587 100644
--- a/chrome/browser/resources/ash/settings/os_settings_menu/menu_item.html
+++ b/chrome/browser/resources/ash/settings/os_settings_menu/menu_item.html
@@ -18,6 +18,7 @@
     border-style: solid;
     color: var(--cros-text-color-primary);
     display: flex;
+    flex-direction: row;
     margin-bottom: 8px;
     margin-inline-end: 2px;
     min-height: 32px;
@@ -68,7 +69,6 @@
   iron-icon {
     margin-inline-end: 16px;
     pointer-events: none;
-    vertical-align: top;
   }
 
   :host-context(body:not(.jelly-enabled)):host(.iron-selected) > iron-icon {
@@ -78,7 +78,20 @@
   :host-context(body.jelly-enabled):host(.iron-selected) > iron-icon {
     fill: var(--cros-sys-on_primary);
   }
+
+  /* Label & sublabel styles */
+  #sublabel {
+    color: var(--cros-sys-on_surface_variant);
+    font: var(--cros-body-2-font);
+  }
+
+  :host(.iron-selected) #sublabel {
+    color: var(--cros-sys-surface_variant);
+  }
 </style>
 
 <iron-icon icon="[[icon]]" hidden="[[!icon]]"></iron-icon>
-<slot></slot>
+<div id="labelWrapper">
+  <slot></slot>
+  <div id="sublabel">[[sublabel]]</div>
+</div>
diff --git a/chrome/browser/resources/ash/settings/os_settings_menu/menu_item.ts b/chrome/browser/resources/ash/settings/os_settings_menu/menu_item.ts
index 256189ea1..cbc7e39 100644
--- a/chrome/browser/resources/ash/settings/os_settings_menu/menu_item.ts
+++ b/chrome/browser/resources/ash/settings/os_settings_menu/menu_item.ts
@@ -40,11 +40,17 @@
         type: String,
         value: '',
       },
+
+      sublabel: {
+        type: String,
+        value: '',
+      },
     };
   }
 
   icon: string;
   path: string;
+  sublabel: string;
 
   override ready(): void {
     super.ready();
diff --git a/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.html b/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.html
index 445ef3f..3e4d951 100644
--- a/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.html
+++ b/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.html
@@ -89,7 +89,9 @@
     on-iron-select="onItemSelected_"
     on-iron-deselect="onItemDeselected_">
   <template id="topMenuRepeat" is="dom-repeat" items="[[basicMenuItems_]]">
-    <os-settings-menu-item path="[[item.path]]" icon="[[item.icon]]">
+    <os-settings-menu-item path="[[item.path]]"
+        icon="[[item.icon]]"
+        sublabel="[[item.sublabel]]">
       [[item.label]]
     </os-settings-menu-item>
   </template>
@@ -109,7 +111,9 @@
           attr-for-selected="path"
           selected="[[selectedItemPath_]]">
         <template is="dom-repeat" items="[[advancedMenuItems_]]">
-          <os-settings-menu-item path="[[item.path]]" icon="[[item.icon]]">
+          <os-settings-menu-item path="[[item.path]]"
+              icon="[[item.icon]]"
+              sublabel="[[item.sublabel]]">
             [[item.label]]
           </os-settings-menu-item>
         </template>
diff --git a/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts b/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts
index 794eecb70..4c7f694 100644
--- a/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts
+++ b/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts
@@ -34,6 +34,9 @@
   path: string;
   icon: string;
   label: string;
+
+  // Sublabels should only exist when OsSettingsRevampWayfinding is enabled.
+  sublabel?: string;
 }
 
 export interface OsSettingsMenuElement {
@@ -196,6 +199,7 @@
           path: `/${routesMojom.PERSONALIZATION_SECTION_PATH}`,
           icon: 'os-settings:personalization',
           label: this.i18n('personalizationPageTitle'),
+          sublabel: this.i18n('personalizationMenuItemDescription'),
         },
         {
           section: Section.kPrivacyAndSecurity,
diff --git a/chrome/browser/resources/ash/settings/os_settings_routes.ts b/chrome/browser/resources/ash/settings/os_settings_routes.ts
index 8cba987f..03ffd46 100644
--- a/chrome/browser/resources/ash/settings/os_settings_routes.ts
+++ b/chrome/browser/resources/ash/settings/os_settings_routes.ts
@@ -13,7 +13,7 @@
 import {assert} from 'chrome://resources/js/assert_ts.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 
-import {androidAppsVisible, isArcVmEnabled, isCrostiniSupported, isGuest, isKerberosEnabled, isPluginVmAvailable, isPowerwashAllowed, isRevampWayfindingEnabled} from './common/load_time_booleans.js';
+import {androidAppsVisible, isArcVmEnabled, isCrostiniSupported, isGuest, isInputDeviceSettingsSplitEnabled, isKerberosEnabled, isPluginVmAvailable, isPowerwashAllowed, isRevampWayfindingEnabled} from './common/load_time_booleans.js';
 import * as routesMojom from './mojom-webui/routes.mojom-webui.js';
 
 /**
@@ -344,7 +344,7 @@
       r.DEVICE, routesMojom.DISPLAY_SUBPAGE_PATH, Subpage.kDisplay);
   r.AUDIO =
       createSubpage(r.DEVICE, routesMojom.AUDIO_SUBPAGE_PATH, Subpage.kAudio);
-  if (loadTimeData.getBoolean('enableInputDeviceSettingsSplit')) {
+  if (isInputDeviceSettingsSplitEnabled()) {
     r.PER_DEVICE_KEYBOARD = createSubpage(
         r.DEVICE, routesMojom.PER_DEVICE_KEYBOARD_SUBPAGE_PATH,
         Subpage.kPerDeviceKeyboard);
@@ -489,6 +489,24 @@
       Subpage.kDetailedBuildInfo);
 
   if (isRevampWayfindingEnabled()) {
+    // Device section, Input subpages.
+    const inputParentRoute = isInputDeviceSettingsSplitEnabled() ?
+        r.PER_DEVICE_KEYBOARD :
+        r.KEYBOARD;
+    assert(inputParentRoute);
+    r.OS_LANGUAGES_INPUT = createSubpage(
+        inputParentRoute, routesMojom.INPUT_SUBPAGE_PATH, Subpage.kInput);
+    r.OS_LANGUAGES_INPUT_METHOD_OPTIONS = createSubpage(
+        r.OS_LANGUAGES_INPUT, routesMojom.INPUT_METHOD_OPTIONS_SUBPAGE_PATH,
+        Subpage.kInputMethodOptions);
+    r.OS_LANGUAGES_EDIT_DICTIONARY = createSubpage(
+        r.OS_LANGUAGES_INPUT, routesMojom.EDIT_DICTIONARY_SUBPAGE_PATH,
+        Subpage.kEditDictionary);
+    r.OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY = createSubpage(
+        r.OS_LANGUAGES_INPUT,
+        routesMojom.JAPANESE_MANAGE_USER_DICTIONARY_SUBPAGE_PATH,
+        Subpage.kJapaneseManageUserDictionary);
+
     // System Preferences section.
     r.SYSTEM_PREFERENCES = createSection(
         r.BASIC, routesMojom.SYSTEM_PREFERENCES_SECTION_PATH,
@@ -520,22 +538,10 @@
           Subpage.kNetworkFileShares);
     }
 
-    // Languages and Input subpages.
+    // Language subpages.
     r.OS_LANGUAGES_LANGUAGES = createSubpage(
         r.SYSTEM_PREFERENCES, routesMojom.LANGUAGES_SUBPAGE_PATH,
         Subpage.kLanguages);
-    r.OS_LANGUAGES_INPUT = createSubpage(
-        r.SYSTEM_PREFERENCES, routesMojom.INPUT_SUBPAGE_PATH, Subpage.kInput);
-    r.OS_LANGUAGES_INPUT_METHOD_OPTIONS = createSubpage(
-        r.OS_LANGUAGES_INPUT, routesMojom.INPUT_METHOD_OPTIONS_SUBPAGE_PATH,
-        Subpage.kInputMethodOptions);
-    r.OS_LANGUAGES_EDIT_DICTIONARY = createSubpage(
-        r.OS_LANGUAGES_INPUT, routesMojom.EDIT_DICTIONARY_SUBPAGE_PATH,
-        Subpage.kEditDictionary);
-    r.OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY = createSubpage(
-        r.OS_LANGUAGES_INPUT,
-        routesMojom.JAPANESE_MANAGE_USER_DICTIONARY_SUBPAGE_PATH,
-        Subpage.kJapaneseManageUserDictionary);
 
     // Search and Assistant subpages.
     r.SEARCH_SUBPAGE = createSubpage(
diff --git a/chrome/browser/resources/ash/settings/system_preferences_page/system_preferences_page.html b/chrome/browser/resources/ash/settings/system_preferences_page/system_preferences_page.html
index db4bbad..f064b1f 100644
--- a/chrome/browser/resources/ash/settings/system_preferences_page/system_preferences_page.html
+++ b/chrome/browser/resources/ash/settings/system_preferences_page/system_preferences_page.html
@@ -70,7 +70,7 @@
     </template>
   </template>
 
-  <!-- Languages and Input subpages -->
+  <!-- Languages subpages -->
   <template is="dom-if" route-path="/osLanguages/languages">
     <os-settings-subpage page-title="$i18n{languagesPageTitle}">
       <os-settings-languages-page-v2 prefs="{{prefs}}"
@@ -80,36 +80,6 @@
     </os-settings-subpage>
   </template>
 
-  <template is="dom-if" route-path="/osLanguages/input">
-    <os-settings-subpage page-title="$i18n{inputPageTitle}">
-      <os-settings-input-page prefs="{{prefs}}"
-          languages="[[languages]]"
-          language-helper="[[languageHelper]]">
-      </os-settings-input-page>
-    </os-settings-subpage>
-  </template>
-
-  <template is="dom-if" route-path="/osLanguages/inputMethodOptions">
-    <os-settings-subpage>
-      <settings-input-method-options-page prefs="{{prefs}}"
-          language-helper="[[languageHelper]]">
-      </settings-input-method-options-page>
-    </os-settings-subpage>
-  </template>
-
-  <template is="dom-if" route-path="/osLanguages/editDictionary">
-    <os-settings-subpage page-title="$i18n{editDictionaryLabel}">
-      <os-settings-edit-dictionary-page></os-settings-edit-dictionary-page>
-    </os-settings-subpage>
-  </template>
-
-  <template is="dom-if" route-path="/osLanguages/japaneseManageUserDictionary">
-    <os-settings-subpage page-title="$i18n{japaneseManageUserDictionaryLabel}">
-      <os-settings-japanese-manage-user-dictionary-page>
-      </os-settings-japanese-manage-user-dictionary-page>
-    </os-settings-subpage>
-  </template>
-
   <!-- Search and Assistant subpages -->
   <template is="dom-if" if="[[shouldShowQuickAnswersSettings_]]">
     <template is="dom-if" route-path="/osSearch/search">
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn
index c6dd0f9..25773cfc 100644
--- a/chrome/browser/resources/chromeos/login/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -283,6 +283,7 @@
     "screens/common/marketing_opt_in.js",
     "screens/common/multidevice_setup.js",
     "screens/common/offline_ad_login.js",
+    "screens/common/online_authentication_screen.js",
     "screens/common/oobe_reset.js",
     "screens/common/os_install.js",
     "screens/common/os_trial.js",
diff --git a/chrome/browser/resources/chromeos/login/debug/debug.js b/chrome/browser/resources/chromeos/login/debug/debug.js
index e261254..f1bca319 100644
--- a/chrome/browser/resources/chromeos/login/debug/debug.js
+++ b/chrome/browser/resources/chromeos/login/debug/debug.js
@@ -1803,6 +1803,10 @@
       id: 'user-allowlist-check-screen',
       kind: ScreenKind.NORMAL,
     },
+    {
+      id: 'online-authentication-screen',
+      kind: ScreenKind.NORMAL,
+    },
   ];
 
   class DebugButton {
diff --git a/chrome/browser/resources/chromeos/login/screens.js b/chrome/browser/resources/chromeos/login/screens.js
index fe778e71..9c35db04 100644
--- a/chrome/browser/resources/chromeos/login/screens.js
+++ b/chrome/browser/resources/chromeos/login/screens.js
@@ -33,6 +33,7 @@
 import './screens/common/marketing_opt_in.js';
 import './screens/common/multidevice_setup.js';
 import './screens/common/offline_ad_login.js';
+import './screens/common/online_authentication_screen.js';
 import './screens/common/oobe_reset.js';
 import './screens/common/os_install.js';
 import './screens/common/os_trial.js';
@@ -128,6 +129,7 @@
   {tag: 'marketing-opt-in-element', id: 'marketing-opt-in'},
   {tag: 'multidevice-setup-element', id: 'multidevice-setup-screen'},
   {tag: 'offline-ad-login-element', id: 'offline-ad-login'},
+  { tag: 'online-authentication-screen-element', id: 'online-authentication-screen' },
   {tag: 'oobe-reset-element', id: 'reset'},
   {
     tag: 'os-install-element',
diff --git a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
index 7040d06f..84ca716 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
@@ -793,6 +793,7 @@
     "marketing_opt_in.js",
     "multidevice_setup.js",
     "offline_ad_login.js",
+    "online_authentication_screen.js",
     "oobe_reset.js",
     "os_install.js",
     "os_trial.js",
diff --git a/chrome/browser/resources/chromeos/login/screens/common/online_authentication_screen.html b/chrome/browser/resources/chromeos/login/screens/common/online_authentication_screen.html
new file mode 100644
index 0000000..9064354c
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/screens/common/online_authentication_screen.html
@@ -0,0 +1,9 @@
+<!--
+Copyright 2023 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<oobe-loading-dialog title-key="gaiaLoading" for-step="loading">
+  <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon>
+</oobe-loading-dialog>
diff --git a/chrome/browser/resources/chromeos/login/screens/common/online_authentication_screen.js b/chrome/browser/resources/chromeos/login/screens/common/online_authentication_screen.js
new file mode 100644
index 0000000..ca96401
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/screens/common/online_authentication_screen.js
@@ -0,0 +1,86 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Oobe signin screen implementation.
+ */
+
+import '//resources/polymer/v3_0/iron-icon/iron-icon.js';
+import '../../components/dialogs/oobe_loading_dialog.js';
+
+
+import { assert } from '//resources/ash/common/assert.js';
+import { html, mixinBehaviors, PolymerElement } from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+
+import { LoginScreenBehavior, LoginScreenBehaviorInterface } from '../../components/behaviors/login_screen_behavior.js';
+import { MultiStepBehavior, MultiStepBehaviorInterface } from '../../components/behaviors/multi_step_behavior.js';
+import { OobeI18nBehavior, OobeI18nBehaviorInterface } from '../../components/behaviors/oobe_i18n_behavior.js';
+
+
+
+/**
+ * UI mode for the dialog.
+ * @enum {string}
+ */
+const DialogMode = {
+  LOADING: 'loading',
+};
+
+
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {LoginScreenBehaviorInterface}
+ * @implements {MultiStepBehaviorInterface}
+ * @implements {OobeI18nBehaviorInterface}
+ */
+const OnlineAuthenticationScreenElementBase = mixinBehaviors(
+  [OobeI18nBehavior, LoginScreenBehavior, MultiStepBehavior], PolymerElement);
+
+
+/**
+ * @polymer
+ */
+class OnlineAuthenticationScreenElement extends OnlineAuthenticationScreenElementBase {
+  static get is() {
+    return 'online-authentication-screen-element';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+    };
+  }
+
+  get EXTERNAL_API() {
+    return [];
+  }
+
+  defaultUIStep() {
+    return DialogMode.LOADING;
+  }
+
+  get UI_STEPS() {
+    return DialogMode;
+  }
+
+  /** @override */
+  ready() {
+    super.ready();
+    this.initializeLoginScreen('OnlineAuthenticationScreen');
+  }
+
+  /**
+   * Event handler that is invoked just before the frame is shown.
+   * @param {Object} data Screen init payload
+   */
+  onBeforeShow() {
+  }
+}
+
+customElements.define(OnlineAuthenticationScreenElement.is, OnlineAuthenticationScreenElement);
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 312c8b0..ca88ca13 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -64,6 +64,8 @@
     "images/safe_browsing_banner.svg",
     "images/sync_banner_dark.svg",
     "images/sync_banner.svg",
+    "images/tracking_protection_banner_dark.svg",
+    "images/tracking_protection_banner.svg",
     "privacy_sandbox/privacy_sandbox.html",
     "settings.html",
   ]
@@ -267,6 +269,7 @@
   # -----------------non_web_component_files start ----------------------------
 
   non_web_component_files = [
+    "a11y_page/a11y_browser_proxy.ts",
     "about_page/about_page_browser_proxy.ts",
     "appearance_page/appearance_browser_proxy.ts",
     "autofill_page/address_edit_dialog_components.ts",
@@ -344,11 +347,6 @@
     non_web_component_files += [ "autofill_page/passkeys_browser_proxy.ts" ]
   }
 
-  if (is_mac) {
-    non_web_component_files +=
-        [ "a11y_page/mac_system_settings_browser_proxy.ts" ]
-  }
-
   # -----------------non_web_component_files end -------------------------------
 
   icons_html_files = [
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_browser_proxy.ts b/chrome/browser/resources/settings/a11y_page/a11y_browser_proxy.ts
new file mode 100644
index 0000000..74f213a
--- /dev/null
+++ b/chrome/browser/resources/settings/a11y_page/a11y_browser_proxy.ts
@@ -0,0 +1,30 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+export interface AccessibilityBrowserProxy {
+  openTrackpadGesturesSettings(): void;
+  recordOverscrollHistoryNavigationChanged(enabled: boolean): void;
+}
+
+export class AccessibilityBrowserProxyImpl implements
+    AccessibilityBrowserProxy {
+  openTrackpadGesturesSettings() {
+    chrome.send('openTrackpadGesturesSettings');
+  }
+
+  recordOverscrollHistoryNavigationChanged(enabled: boolean) {
+    chrome.metricsPrivate.recordBoolean(
+        'Settings.OverscrollHistoryNavigation.Enabled', enabled);
+  }
+
+  static getInstance(): AccessibilityBrowserProxy {
+    return instance || (instance = new AccessibilityBrowserProxyImpl());
+  }
+
+  static setInstance(obj: AccessibilityBrowserProxy) {
+    instance = obj;
+  }
+}
+
+let instance: AccessibilityBrowserProxy|null = null;
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html
index f8efe8c8..f077105 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -72,6 +72,7 @@
             class="hr"
             hidden$="[[!showOverscrollHistoryNavigationToggle_]]"
             pref="{{prefs.settings.a11y.overscroll_history_navigation}}"
+            on-change="onOverscrollHistoryNavigationChange_"
             label="$i18n{overscrollHistoryNavigationTitle}"
             sub-label="$i18n{overscrollHistoryNavigationSubtitle}">
         </settings-toggle-button>
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.ts b/chrome/browser/resources/settings/a11y_page/a11y_page.ts
index 980b9c1..96287ce7 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.ts
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.ts
@@ -33,6 +33,7 @@
 import {routes} from '../route.js';
 import {Router} from '../router.js';
 
+import {AccessibilityBrowserProxy, AccessibilityBrowserProxyImpl} from './a11y_browser_proxy.js';
 import {getTemplate} from './a11y_page.html.js';
 
 // clang-format off
@@ -40,9 +41,6 @@
 import {LanguageHelper, LanguagesModel} from '../languages_page/languages_types.js';
 
 // </if>
-// <if expr="is_macosx">
-import {MacSystemSettingsBrowserProxyImpl} from './mac_system_settings_browser_proxy.js';
-// </if>
 // clang-format on
 
 
@@ -176,6 +174,9 @@
     };
   }
 
+  private accessibilityBrowserProxy: AccessibilityBrowserProxy =
+      AccessibilityBrowserProxyImpl.getInstance();
+
   // <if expr="not is_chromeos">
   languages: LanguagesModel;
   languageHelper: LanguageHelper;
@@ -267,10 +268,17 @@
     }
   }
 
+  // <if expr="is_win or is_linux">
+  private onOverscrollHistoryNavigationChange_(event: Event) {
+    const enabled = (event.target as SettingsToggleButtonElement).checked;
+    this.accessibilityBrowserProxy.recordOverscrollHistoryNavigationChanged(
+        enabled);
+  }
+  // </if>
+
   // <if expr="is_macosx">
   private onMacTrackpadGesturesLinkClick_() {
-    MacSystemSettingsBrowserProxyImpl.getInstance()
-        .openTrackpadGesturesSettings();
+    this.accessibilityBrowserProxy.openTrackpadGesturesSettings();
   }
   // </if>
 }
diff --git a/chrome/browser/resources/settings/a11y_page/mac_system_settings_browser_proxy.ts b/chrome/browser/resources/settings/a11y_page/mac_system_settings_browser_proxy.ts
deleted file mode 100644
index f3a8455..0000000
--- a/chrome/browser/resources/settings/a11y_page/mac_system_settings_browser_proxy.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-export interface MacSystemSettingsBrowserProxy {
-  openTrackpadGesturesSettings(): void;
-}
-
-export class MacSystemSettingsBrowserProxyImpl implements
-    MacSystemSettingsBrowserProxy {
-  openTrackpadGesturesSettings() {
-    chrome.send('openTrackpadGesturesSettings');
-  }
-
-  static getInstance(): MacSystemSettingsBrowserProxy {
-    return instance || (instance = new MacSystemSettingsBrowserProxyImpl());
-  }
-
-  static setInstance(obj: MacSystemSettingsBrowserProxy) {
-    instance = obj;
-  }
-}
-
-let instance: MacSystemSettingsBrowserProxy|null = null;
diff --git a/chrome/browser/resources/settings/images/tracking_protection_banner.svg b/chrome/browser/resources/settings/images/tracking_protection_banner.svg
new file mode 100644
index 0000000..7e940cd5
--- /dev/null
+++ b/chrome/browser/resources/settings/images/tracking_protection_banner.svg
@@ -0,0 +1 @@
+<svg width="680" height="226" viewBox="0 0 680 226" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path d="M0 0h680v226H0V0Z" fill="#F1F3F4"/><circle cx="340.5" cy="190.5" r="126.5" fill="#fff"/><circle cx="340.5" cy="35.5" r="126.5" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M240.512 113c23.142-29.814 59.325-49 99.988-49s76.845 19.186 99.987 49c-23.142 29.814-59.324 49-99.987 49s-76.846-19.186-99.988-49Z" fill="#D2E3FC"/><path d="M514.3 99.6c4 0 7.3-3.3 7.3-7.3s-3.3-7.3-7.3-7.3-7.3 3.3-7.3 7.3 3.3 7.3 7.3 7.3Z" fill="#D93025"/><path fill-rule="evenodd" clip-rule="evenodd" d="M548.6 145.2c11.929 0 21.6-9.671 21.6-21.6 0-11.929-9.671-21.6-21.6-21.6-11.929 0-21.6 9.671-21.6 21.6 0 11.929 9.671 21.6 21.6 21.6Zm23.6-21.6c0 13.034-10.566 23.6-23.6 23.6S525 136.634 525 123.6s10.566-23.6 23.6-23.6 23.6 10.566 23.6 23.6Z" fill="#DADCE0"/><path d="m607.965 166.857.009.003 28.191 10.497.004.001c6.805 2.613 10.412 10.146 7.721 17.104l-.001.003c-2.606 6.795-10.335 10.322-17.108 7.724l-.009-.003-28.191-10.497-.004-.001c-6.793-2.609-10.318-10.335-7.72-17.107 2.606-6.795 10.335-10.322 17.108-7.724Z" stroke="#34A853" stroke-width="2"/><path d="M123.931 88.158c-1.7 2.1-5 2-6.6-.1-4.6-6.5-4.5-15.5.7-22 5.3-6.7 14-8.7 21.5-5.7 2.5 1.1 3.3 4.2 1.7 6.3l-17.3 21.5Z" fill="#FBBC04"/><path d="M152 196c0 2.8-2.2 5-5 5-2.8.1-5-2.2-5-5s2.2-5 5-5c2.7 0 5 2.2 5 5Z" fill="#D2E3FC"/><path d="m569.823 61.523-19.7-14.7c-1.2-.9-1.5-2.7-.6-4l14.7-19.7c.9-1.2 2.7-1.5 4-.6l19.7 14.7c1.2.9 1.5 2.7.6 4l-14.7 19.7c-1 1.2-2.8 1.5-4 .6Z" fill="#FBBC04"/><path fill-rule="evenodd" clip-rule="evenodd" d="M62.615 97.004c-.572-.05-1.063.368-1.11.895v.004L59.004 124v.002c-.052.572.367 1.063.893 1.111l.005.001L86 127.613c.573.051 1.065-.368 1.113-.895l.001-.004 2.5-26.096v-.001c.05-.573-.369-1.065-.896-1.113h-.004l-26.096-2.5h-.002Zm-3.103.712c.154-1.672 1.66-2.851 3.287-2.703h.004l26.096 2.5h.002c1.672.153 2.851 1.66 2.703 3.286v.005l-2.5 26.096v.002c-.154 1.672-1.66 2.851-3.287 2.703l-.004-.001-26.096-2.499h-.002c-1.672-.154-2.85-1.661-2.703-3.287v-.004l2.5-26.096v-.002Z" fill="#34A853"/><path d="m422.844 21.358-3.84 14.413c-.354 1.155.721 2.193 1.898 1.877l14.371-3.85c1.115-.3 1.527-1.735.705-2.575l-10.656-10.528c-.76-.857-2.185-.475-2.478.663Z" fill="#DADCE0"/><path d="m390.239 48.782-.002-.002-15.739-11.745h-.001c-.515-.387-.675-1.208-.265-1.814l11.732-15.723.001-.001c.387-.515 1.208-.675 1.814-.265l15.723 11.733h.001c.515.387.675 1.208.265 1.814L392.052 48.48c-.505.588-1.339.657-1.813.302Z" stroke="#DADCE0" stroke-width="2"/><path d="M251.164 185.09c-1.431.641-3.07-.286-3.305-1.801-.551-4.595 1.954-9.243 6.351-11.242 4.503-2.075 9.441-.808 12.41 2.738.962 1.233.521 3.056-.86 3.722l-14.596 6.583Z" fill="#34A853"/><path d="M298.579 176.403a7 7 0 0 1 6.508 2.58l7.301 9.222a7.004 7.004 0 0 1 1.019 6.926l-4.336 10.934a7 7 0 0 1-5.489 4.345l-11.637 1.712a7 7 0 0 1-6.507-2.581l-7.301-9.222a7 7 0 0 1-1.019-6.925l4.336-10.934a7 7 0 0 1 5.488-4.345l11.637-1.712Z" stroke="#FA7B17" stroke-width="2"/><circle cx="340" cy="113" r="28" fill="#4285F4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M281.962 78.33C299.466 69.176 319.379 64 340.5 64c40.663 0 76.845 19.186 99.987 49a127.076 127.076 0 0 1-39.595 33.681L281.962 78.33Z" fill="#F1F3F4"/><path fill-rule="evenodd" clip-rule="evenodd" d="m364.764 126.079-48.53-27.89C321.18 90.268 329.975 85 340 85c15.464 0 28 12.536 28 28a27.88 27.88 0 0 1-3.236 13.079Z" fill="#DADCE0"/><path d="m253.498 62.133 174 100" stroke="#4285F4" stroke-width="2" stroke-linecap="round"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h680v226H0z"/></clipPath></defs></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/images/tracking_protection_banner_dark.svg b/chrome/browser/resources/settings/images/tracking_protection_banner_dark.svg
new file mode 100644
index 0000000..fc85568
--- /dev/null
+++ b/chrome/browser/resources/settings/images/tracking_protection_banner_dark.svg
@@ -0,0 +1 @@
+<svg width="680" height="226" viewBox="0 0 680 226" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path d="M0 0h680v226H0V0Z" fill="#3C4043"/><circle cx="340.5" cy="190.5" r="126.5" fill="#5F6368"/><circle cx="340.5" cy="35.5" r="126.5" fill="#5F6368"/><path fill-rule="evenodd" clip-rule="evenodd" d="M240.512 113c23.143-29.814 59.325-49 99.988-49s76.845 19.186 99.988 49c-23.143 29.814-59.325 49-99.988 49s-76.845-19.186-99.988-49Z" fill="#174EA6"/><path d="M514.3 99.6c4 0 7.3-3.3 7.3-7.3s-3.3-7.3-7.3-7.3-7.3 3.3-7.3 7.3 3.3 7.3 7.3 7.3Z" fill="#F28B82"/><path d="m607.965 166.857.009.003 28.191 10.497.004.001c6.805 2.613 10.412 10.146 7.721 17.104l-.001.003c-2.606 6.795-10.335 10.322-17.108 7.724l-.009-.003-28.191-10.497-.004-.001c-6.793-2.609-10.318-10.335-7.72-17.107 2.606-6.795 10.335-10.322 17.108-7.724Z" fill="#81C995" stroke="#81C995" stroke-width="2"/><path d="M123.931 88.158c-1.7 2.1-5 2-6.6-.1-4.6-6.5-4.5-15.5.7-22 5.3-6.7 14-8.7 21.5-5.7 2.5 1.1 3.3 4.2 1.7 6.3l-17.3 21.5Z" fill="#FDD663"/><path d="M152 196c0 2.8-2.2 5-5 5-2.8.1-5-2.2-5-5s2.2-5 5-5c2.7 0 5 2.2 5 5Z" fill="#8AB4F8"/><path d="m569.823 61.523-19.7-14.7c-1.2-.9-1.5-2.7-.6-4l14.7-19.7c.9-1.2 2.7-1.5 4-.6l19.7 14.7c1.2.9 1.5 2.7.6 4l-14.7 19.7c-1 1.2-2.8 1.5-4 .6Z" fill="#FDD663"/><path d="m61.006 97.854-.002.023v.003l-2.497 26.072-.003.024v.005c-.06.819.533 1.539 1.32 1.627l.007.001.025.002 26.096 2.499.003.001c.824.073 1.555-.516 1.65-1.306l.002-.007.004-.037 2.5-26.096.001-.024v-.004c.06-.815-.526-1.532-1.307-1.626l-.007-.002-.037-.003-26.096-2.5-.024-.002h-.005c-.83-.06-1.556.548-1.63 1.35Zm1.711-2.347h.001l.038.004 26.096 2.5.023.002h.002c1.365.137 2.34 1.369 2.232 2.715v.002l-.003.026-2.5 26.096-.002.024v.002c-.137 1.36-1.362 2.334-2.704 2.232l-.001-.001-.038-.003-26.096-2.499-.024-.002h-.002c-1.373-.139-2.351-1.385-2.229-2.742l.002-.023v-.003l2.498-26.072.002-.024v-.001c.138-1.361 1.362-2.335 2.705-2.233Z" fill="#81C995" stroke="#81C995"/><path d="m422.844 21.358-3.84 14.413c-.354 1.155.721 2.193 1.898 1.877l14.371-3.85c1.115-.3 1.527-1.735.705-2.575l-10.656-10.528c-.76-.857-2.185-.475-2.478.663Z" fill="#80868B"/><path d="m385.239 48.782-.002-.002-15.739-11.745h-.001c-.515-.387-.675-1.208-.265-1.814l11.732-15.723.001-.001c.387-.515 1.208-.675 1.814-.265l15.723 11.733h.001c.515.387.675 1.208.265 1.814L387.052 48.48c-.505.588-1.339.657-1.813.302Z" stroke="#80868B" stroke-width="2"/><path d="m254.417 172.503.003-.001c4.29-1.978 8.983-.775 11.81 2.597.758.98.406 2.426-.682 2.955l-14.588 6.58h-.001c-1.121.501-2.414-.223-2.605-1.413-.52-4.38 1.87-8.813 6.063-10.718Z" fill="#81C995" stroke="#81C995"/><path d="M298.579 176.403a7 7 0 0 1 6.508 2.58l7.301 9.222a7.004 7.004 0 0 1 1.019 6.926l-4.336 10.934a7 7 0 0 1-5.489 4.345l-11.637 1.712a7 7 0 0 1-6.507-2.581l-7.301-9.222a7 7 0 0 1-1.019-6.925l4.336-10.934a7 7 0 0 1 5.488-4.345l11.637-1.712Z" stroke="#FCAD70" stroke-width="2"/><circle cx="340" cy="113" r="27.5" fill="#8AB4F8" stroke="#8AB4F8"/><path fill-rule="evenodd" clip-rule="evenodd" d="M281.815 78.407C299.354 69.206 319.319 64 340.5 64c40.663 0 76.845 19.186 99.987 49a127.083 127.083 0 0 1-39.739 33.759L281.815 78.407Z" fill="#3C4043"/><path fill-rule="evenodd" clip-rule="evenodd" d="m364.764 126.079-48.53-27.89C321.18 90.268 329.975 85 340 85c15.464 0 28 12.536 28 28a27.88 27.88 0 0 1-3.236 13.079Z" fill="#BDC1C6"/><path d="m253.498 62.133 174 100" stroke="#8AB4F8" stroke-width="2" stroke-linecap="round"/><path d="M548.6 145.7c12.205 0 22.1-9.895 22.1-22.1 0-12.205-9.895-22.1-22.1-22.1-12.205 0-22.1 9.895-22.1 22.1 0 12.205 9.895 22.1 22.1 22.1Zm23.1-22.1c0 12.758-10.342 23.1-23.1 23.1-12.758 0-23.1-10.342-23.1-23.1 0-12.758 10.342-23.1 23.1-23.1 12.758 0 23.1 10.342 23.1 23.1Z" fill="#80868B" stroke="#80868B"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h680v226H0z"/></clipPath></defs></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/privacy_page/cookies_page.html b/chrome/browser/resources/settings/privacy_page/cookies_page.html
index c0a87b5..07213a3 100644
--- a/chrome/browser/resources/settings/privacy_page/cookies_page.html
+++ b/chrome/browser/resources/settings/privacy_page/cookies_page.html
@@ -98,13 +98,21 @@
         min-height: var(--cr-section-two-line-min-height);
       }
     </style>
-    <picture>
+    <picture hidden="[[is3pcdRedesignEnabled_]]">
       <source
           srcset="chrome://settings/images/cookies_banner_dark.svg"
           media="(prefers-color-scheme: dark)">
       <img id="banner" alt=""
           src="chrome://settings/images/cookies_banner.svg">
     </picture>
+    <picture hidden="[[!is3pcdRedesignEnabled_]]">
+      <source
+            srcset="chrome://settings/images/tracking_protection_banner_dark.svg"
+            media="(prefers-color-scheme: dark)">
+        <img id="banner" alt=""
+            src="chrome://settings/images/tracking_protection_banner.svg">
+      </template>
+    </picture>
     <template is="dom-if" if="[[is3pcdRedesignEnabled_]]">
       <div id="explanationText" class="secondary">
         $i18n{trackingProtectionPageDescription}
diff --git a/chrome/browser/resources/side_panel/performance_controls/BUILD.gn b/chrome/browser/resources/side_panel/performance_controls/BUILD.gn
index 206cc28b..4378786 100644
--- a/chrome/browser/resources/side_panel/performance_controls/BUILD.gn
+++ b/chrome/browser/resources/side_panel/performance_controls/BUILD.gn
@@ -13,7 +13,7 @@
 
   web_component_files = [ "app.ts" ]
 
-  non_web_component_files = []
+  non_web_component_files = [ "performance_api_proxy.ts" ]
 
   mojo_files_deps = [ "//chrome/browser/ui/webui/side_panel/performance_controls:mojo_bindings_ts__generator" ]
   mojo_files = [ "$root_gen_dir/chrome/browser/ui/webui/side_panel/performance_controls/performance.mojom-webui.ts" ]
diff --git a/chrome/browser/resources/side_panel/performance_controls/app.ts b/chrome/browser/resources/side_panel/performance_controls/app.ts
index 2af1e33..c99cd21 100644
--- a/chrome/browser/resources/side_panel/performance_controls/app.ts
+++ b/chrome/browser/resources/side_panel/performance_controls/app.ts
@@ -5,6 +5,7 @@
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './app.html.js';
+import {PerformanceApiProxy, PerformanceApiProxyImpl} from './performance_api_proxy.js';
 
 export interface PerformanceAppElement {
   $: {};
@@ -22,6 +23,9 @@
   static get properties() {
     return {};
   }
+
+  private performanceApi_: PerformanceApiProxy =
+      PerformanceApiProxyImpl.getInstance();
 }
 declare global {
   interface HTMLElementTagNameMap {
diff --git a/chrome/browser/resources/side_panel/performance_controls/performance_api_proxy.ts b/chrome/browser/resources/side_panel/performance_controls/performance_api_proxy.ts
new file mode 100644
index 0000000..f6c80308
--- /dev/null
+++ b/chrome/browser/resources/side_panel/performance_controls/performance_api_proxy.ts
@@ -0,0 +1,37 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {PerformancePageCallbackRouter, PerformancePageHandlerFactory, PerformancePageHandlerRemote} from './performance.mojom-webui.js';
+
+let instance: PerformanceApiProxy|null = null;
+
+export interface PerformanceApiProxy {
+  getCallbackRouter(): PerformancePageCallbackRouter;
+}
+
+export class PerformanceApiProxyImpl implements PerformanceApiProxy {
+  private callbackRouter: PerformancePageCallbackRouter =
+      new PerformancePageCallbackRouter();
+  private handler: PerformancePageHandlerRemote =
+      new PerformancePageHandlerRemote();
+
+  constructor() {
+    const factory = PerformancePageHandlerFactory.getRemote();
+    factory.createPerformancePageHandler(
+        this.callbackRouter.$.bindNewPipeAndPassRemote(),
+        this.handler.$.bindNewPipeAndPassReceiver());
+  }
+
+  getCallbackRouter() {
+    return this.callbackRouter;
+  }
+
+  static getInstance(): PerformanceApiProxy {
+    return instance || (instance = new PerformanceApiProxyImpl());
+  }
+
+  static setInstance(obj: PerformanceApiProxy) {
+    instance = obj;
+  }
+}
diff --git a/chrome/browser/screen_ai/BUILD.gn b/chrome/browser/screen_ai/BUILD.gn
index 8c6693f..3dbca266 100644
--- a/chrome/browser/screen_ai/BUILD.gn
+++ b/chrome/browser/screen_ai/BUILD.gn
@@ -17,6 +17,8 @@
       "//chromeos/ash/components/dbus/dlcservice:dlcservice_proto",
       "//components/services/screen_ai/public/cpp:utilities",
     ]
+
+    configs += [ "//build/config/compiler:wexit_time_destructors" ]
   }
 
   source_set("unit_tests") {
@@ -49,6 +51,8 @@
     "//content/public/browser",
     "//ui/accessibility:ax_base",
   ]
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
 source_set("screen_ai_service_router_factory") {
@@ -66,6 +70,8 @@
     "//components/services/screen_ai/public/mojom",
     "//content/public/browser",
   ]
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
 source_set("prefs") {
@@ -75,4 +81,6 @@
   ]
 
   deps = [ "//components/prefs" ]
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
diff --git a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleUtilsUnitTest.java b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleUtilsUnitTest.java
index ca899b92..e32b9c48 100644
--- a/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleUtilsUnitTest.java
+++ b/chrome/browser/search_resumption/junit/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleUtilsUnitTest.java
@@ -23,7 +23,6 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.FeatureList;
-import org.chromium.base.UserDataHost;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -34,7 +33,6 @@
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.sync.SyncServiceFactory;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.components.search_engines.TemplateUrlService;
 import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.components.sync.SyncService;
@@ -65,8 +63,6 @@
     private GURL mGurl1;
     @Mock
     private GURL mGurl2;
-    @Mock
-    private CriticalPersistedTabData mCriticalPersistedTabData;
 
     private FeatureList.TestValues mFeatureListValues;
 
@@ -80,11 +76,6 @@
         mFeatureListValues.addFeatureFlagOverride(
                 ChromeFeatureList.SHOW_SCROLLABLE_MVT_ON_NTP_ANDROID, true);
 
-        UserDataHost tabDataHost = new UserDataHost();
-        when(mTab.getUserDataHost()).thenReturn(tabDataHost);
-        when(mTabToTrack.getUserDataHost()).thenReturn(tabDataHost);
-        tabDataHost.setUserData(CriticalPersistedTabData.class, mCriticalPersistedTabData);
-
         TemplateUrlServiceFactory.setInstanceForTesting(mTemplateUrlService);
         IdentityServicesProvider.setInstanceForTests(mIdentityServicesProvider);
         doReturn(mIdentityManager).when(mIdentityServicesProvider).getIdentityManager(any());
diff --git a/chrome/browser/segmentation_platform/segmentation_platform_service_factory_unittest.cc b/chrome/browser/segmentation_platform/segmentation_platform_service_factory_unittest.cc
index a77e5797..7bac0549 100644
--- a/chrome/browser/segmentation_platform/segmentation_platform_service_factory_unittest.cc
+++ b/chrome/browser/segmentation_platform/segmentation_platform_service_factory_unittest.cc
@@ -261,6 +261,18 @@
       std::vector<std::string>(1, kLegacyNegativeLabel));
 }
 
+TEST_F(SegmentationPlatformServiceFactoryTest, TestLowUserEngagementModel) {
+  InitServiceAndCacheResults(kChromeLowUserEngagementSegmentationKey);
+
+  PredictionOptions prediction_options;
+
+  ExpectGetClassificationResult(
+      kChromeLowUserEngagementSegmentationKey, prediction_options, nullptr,
+      /*expected_status=*/PredictionStatus::kSucceeded,
+      /*expected_labels=*/
+      std::vector<std::string>(1, kChromeLowUserEngagementUmaName));
+}
+
 TEST_F(SegmentationPlatformServiceFactoryTest, TestDeviceSwitcherModel) {
   InitService();
 
diff --git a/chrome/browser/segmentation_platform/service_browsertest.cc b/chrome/browser/segmentation_platform/service_browsertest.cc
index 3ae11b0..05a4276 100644
--- a/chrome/browser/segmentation_platform/service_browsertest.cc
+++ b/chrome/browser/segmentation_platform/service_browsertest.cc
@@ -95,36 +95,6 @@
     command_line->AppendSwitch("segmentation-platform-refresh-results");
   }
 
-  bool HasResultPref(base::StringPiece segmentation_key) {
-    const base::Value::Dict& dictionary =
-        chrome_test_utils::GetProfile(this)->GetPrefs()->GetDict(
-            kSegmentationResultPref);
-    return !!dictionary.FindByDottedPath(segmentation_key);
-  }
-
-  void OnResultPrefUpdated() {
-    if (!wait_for_pref_callback_.is_null() &&
-        HasResultPref(kChromeLowUserEngagementSegmentationKey)) {
-      std::move(wait_for_pref_callback_).Run();
-    }
-  }
-
-  void WaitForPrefUpdate() {
-    if (HasResultPref(kChromeLowUserEngagementSegmentationKey))
-      return;
-
-    base::RunLoop wait_for_pref;
-    wait_for_pref_callback_ = wait_for_pref.QuitClosure();
-    pref_registrar_.Init(chrome_test_utils::GetProfile(this)->GetPrefs());
-    pref_registrar_.Add(
-        kSegmentationResultPref,
-        base::BindRepeating(&SegmentationPlatformTest::OnResultPrefUpdated,
-                            weak_ptr_factory_.GetWeakPtr()));
-    wait_for_pref.Run();
-
-    pref_registrar_.RemoveAll();
-  }
-
   bool HasClientResultPref(const std::string& segmentation_key) {
     PrefService* pref_service = chrome_test_utils::GetProfile(this)->GetPrefs();
     std::unique_ptr<ClientResultPrefs> result_prefs_ =
@@ -181,23 +151,6 @@
     ASSERT_GE(success_count, 1);
   }
 
-  void ExpectSegmentSelectionResult(const std::string& segmentation_key,
-                                    bool result_expected) {
-    SegmentationPlatformService* service =
-        segmentation_platform::SegmentationPlatformServiceFactory::
-            GetForProfile(chrome_test_utils::GetProfile(this));
-    base::RunLoop wait_for_segment;
-    service->GetSelectedSegment(
-        segmentation_key, base::BindOnce(
-                              [](bool result_expected, base::OnceClosure quit,
-                                 const SegmentSelectionResult& result) {
-                                EXPECT_EQ(result_expected, result.is_ready);
-                                std::move(quit).Run();
-                              },
-                              result_expected, wait_for_segment.QuitClosure()));
-    wait_for_segment.Run();
-  }
-
   void ExpectClassificationResult(const std::string& segmentation_key,
                                   PredictionStatus expected_prediction_status) {
     SegmentationPlatformService* service =
@@ -290,18 +243,6 @@
   base::WeakPtrFactory<SegmentationPlatformTest> weak_ptr_factory_{this};
 };
 
-IN_PROC_BROWSER_TEST_F(SegmentationPlatformTest, RunDefaultModel) {
-  WaitForPlatformInit();
-  WaitForPrefUpdate();
-
-  // Result is available from previous session's selection.
-  ExpectSegmentSelectionResult(kChromeLowUserEngagementSegmentationKey,
-                               /*result_expected=*/true);
-
-  // This session runs default model and updates again.
-  WaitForPrefUpdate();
-}
-
 // https://crbug.com/1257820 -- Tests using "PRE_" don't work on Android.
 #if BUILDFLAG(IS_ANDROID)
 #define MAYBE_PRE_CachedClassificationModel \
@@ -583,7 +524,7 @@
   utils_.WaitForUkmObserverRegistration();
 
   // Wait for the default model to run and save results to prefs.
-  WaitForPrefUpdate();
+  WaitForClientResultPrefUpdate();
 
   // Record page load UKM that should be recorded in the database, persisted
   // across sessions.
@@ -609,11 +550,12 @@
   EXPECT_TRUE(utils_.IsUrlInDatabase(kUrl1));
 
   // Result is available from previous session's selection.
-  ExpectSegmentSelectionResult(kChromeLowUserEngagementSegmentationKey,
-                               /*result_expected=*/true);
+  ExpectClassificationResult(
+      kChromeLowUserEngagementSegmentationKey,
+      /*expected_prediction_status=*/PredictionStatus::kSucceeded);
 
   utils_.WaitForUkmObserverRegistration();
-  WaitForPrefUpdate();
+  WaitForClientResultPrefUpdate();
 
   // There are 2 UKM metrics written to the database, count = 2.
   EXPECT_EQ(ModelProvider::Request({2}), input_feature_in_last_execution_);
diff --git a/chrome/browser/segmentation_platform/ukm_data_manager_test_utils.cc b/chrome/browser/segmentation_platform/ukm_data_manager_test_utils.cc
index b0db6485..9443b72 100644
--- a/chrome/browser/segmentation_platform/ukm_data_manager_test_utils.cc
+++ b/chrome/browser/segmentation_platform/ukm_data_manager_test_utils.cc
@@ -12,6 +12,7 @@
 #include "components/segmentation_platform/internal/database/ukm_database.h"
 #include "components/segmentation_platform/internal/execution/mock_model_provider.h"
 #include "components/segmentation_platform/internal/execution/model_manager_impl.h"
+#include "components/segmentation_platform/internal/metadata/metadata_writer.h"
 #include "components/segmentation_platform/internal/segmentation_platform_service_impl.h"
 #include "components/segmentation_platform/internal/signals/ukm_observer.h"
 #include "components/segmentation_platform/internal/ukm_data_manager.h"
@@ -103,8 +104,14 @@
 proto::SegmentationModelMetadata
 UkmDataManagerTestUtils::GetSamplePageLoadMetadata(const std::string& query) {
   proto::SegmentationModelMetadata metadata;
+  MetadataWriter writer(&metadata);
+  writer.AddOutputConfigForBinaryClassifier(
+      /*threshold=*/0.5f,
+      /*positive_label=*/"Show",
+      /*negative_label=*/"NotShow");
   metadata.set_time_unit(proto::TimeUnit::DAY);
   metadata.set_bucket_duration(42u);
+
   auto* feature = metadata.add_input_features();
   auto* sql_feature = feature->mutable_sql_feature();
   sql_feature->set_sql(query);
diff --git a/chrome/browser/signin/chrome_signin_helper_unittest.cc b/chrome/browser/signin/chrome_signin_helper_unittest.cc
index 549f93a..bfeb2f0 100644
--- a/chrome/browser/signin/chrome_signin_helper_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_helper_unittest.cc
@@ -12,6 +12,7 @@
 #include "build/buildflag.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_buildflags.h"
@@ -170,6 +171,7 @@
   sync_preferences::TestingPrefServiceSyncable prefs;
   content_settings::CookieSettings::RegisterProfilePrefs(prefs.registry());
   HostContentSettingsMap::RegisterProfilePrefs(prefs.registry());
+  privacy_sandbox::RegisterProfilePrefs(prefs.registry());
   scoped_refptr<HostContentSettingsMap> settings_map =
       new HostContentSettingsMap(&prefs, /*is_off_the_record=*/false,
                                  /*store_last_modified=*/false,
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index abeac59..75c5c37 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -872,7 +872,7 @@
 
     Profile* profile = browser()->profile();
 
-    web_app::AppId app_id =
+    webapps::AppId app_id =
         web_app::test::InstallWebApp(profile, std::move(web_app_info));
 
     Browser* app_browser = web_app::LaunchWebAppBrowserAndWait(profile, app_id);
diff --git a/chrome/browser/ssl/ssl_fenced_frame_browsertest.cc b/chrome/browser/ssl/ssl_fenced_frame_browsertest.cc
index 5323c6a1..4635bb9e 100644
--- a/chrome/browser/ssl/ssl_fenced_frame_browsertest.cc
+++ b/chrome/browser/ssl/ssl_fenced_frame_browsertest.cc
@@ -61,7 +61,7 @@
 
     Profile* profile = browser()->profile();
 
-    web_app::AppId app_id =
+    webapps::AppId app_id =
         web_app::test::InstallWebApp(profile, std::move(web_app_info));
 
     Browser* app_browser = web_app::LaunchWebAppBrowserAndWait(profile, app_id);
diff --git a/chrome/browser/sync/test/integration/apps_helper.cc b/chrome/browser/sync/test/integration/apps_helper.cc
index 059dd13..00fd9e8 100644
--- a/chrome/browser/sync/test/integration/apps_helper.cc
+++ b/chrome/browser/sync/test/integration/apps_helper.cc
@@ -22,12 +22,12 @@
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
@@ -49,7 +49,7 @@
 
     // First, wait for all installations to complete.
 
-    base::flat_set<web_app::AppId> apps_to_be_installed =
+    base::flat_set<webapps::AppId> apps_to_be_installed =
         web_app::WebAppProvider::GetForTest(profile)
             ->registrar_unsafe()
             .GetAppsFromSyncAndPendingInstallation();
@@ -59,7 +59,7 @@
       // are waiting for installation with hooks, wait on either.
       base::RunLoop loop;
       auto install_listener_callback =
-          base::BindLambdaForTesting([&](const web_app::AppId& app_id) {
+          base::BindLambdaForTesting([&](const webapps::AppId& app_id) {
             apps_to_be_installed.erase(app_id);
             if (apps_to_be_installed.empty())
               loop.Quit();
@@ -220,7 +220,7 @@
     // some installs might not have OS hooks installed but they will be in the
     // registry.
     auto* provider = web_app::WebAppProvider::GetForTest(profile);
-    std::vector<web_app::AppId> sync_apps_pending_install =
+    std::vector<webapps::AppId> sync_apps_pending_install =
         provider->registrar_unsafe().GetAppsFromSyncAndPendingInstallation();
     if (!sync_apps_pending_install.empty()) {
       LOG(ERROR) << "Apps from sync are still pending installation: "
@@ -228,7 +228,7 @@
       return false;
     }
 
-    std::vector<web_app::AppId> apps_in_uninstall =
+    std::vector<webapps::AppId> apps_in_uninstall =
         provider->registrar_unsafe().GetAppsPendingUninstall();
     if (!apps_in_uninstall.empty()) {
       LOG(ERROR) << "App uninstalls are still pending: "
@@ -239,18 +239,18 @@
   return true;
 }
 
-web_app::AppId InstallWebApp(Profile* profile,
+webapps::AppId InstallWebApp(Profile* profile,
                              const web_app::WebAppInstallInfo& info) {
   DCHECK(info.start_url.is_valid());
   base::RunLoop run_loop;
-  web_app::AppId app_id;
+  webapps::AppId app_id;
   auto* provider = web_app::WebAppProvider::GetForTest(profile);
   provider->scheduler().InstallFromInfo(
       std::make_unique<web_app::WebAppInstallInfo>(info.Clone()),
       /*overwrite_existing_manifest_fields=*/true,
       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
       base::BindLambdaForTesting(
-          [&run_loop, &app_id](const web_app::AppId& new_app_id,
+          [&run_loop, &app_id](const webapps::AppId& new_app_id,
                                webapps::InstallResultCode code) {
             DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             app_id = new_app_id;
diff --git a/chrome/browser/sync/test/integration/apps_helper.h b/chrome/browser/sync/test/integration/apps_helper.h
index 9517dbaa..c30f4ac 100644
--- a/chrome/browser/sync/test/integration/apps_helper.h
+++ b/chrome/browser/sync/test/integration/apps_helper.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/sync/model/string_ordinal.h"
+#include "components/webapps/common/web_app_id.h"
 #include "extensions/browser/extension_prefs_observer.h"
 #include "extensions/browser/extension_registry_observer.h"
 
@@ -48,7 +49,7 @@
 
 // Installs the web app for the given WebAppInstallInfo and profile. This does
 // not download icons or run OS integration installs.
-web_app::AppId InstallWebApp(Profile* profile,
+webapps::AppId InstallWebApp(Profile* profile,
                              const web_app::WebAppInstallInfo& info);
 
 // Uninstalls the app for the given index from |profile|. Assumes that it was
diff --git a/chrome/browser/sync/test/integration/local_sync_test.cc b/chrome/browser/sync/test/integration/local_sync_test.cc
index 802de9f..72c91d53 100644
--- a/chrome/browser/sync/test/integration/local_sync_test.cc
+++ b/chrome/browser/sync/test/integration/local_sync_test.cc
@@ -89,6 +89,10 @@
   EXPECT_FALSE(service->IsSyncFeatureEnabled());
   EXPECT_FALSE(service->IsSyncFeatureActive());
 
+  // It is not clear if IsInitialSyncFeatureSetupComplete() should be returning
+  // true, but let's document the current behavior.
+  EXPECT_TRUE(service->GetUserSettings()->IsInitialSyncFeatureSetupComplete());
+
   // Verify that the expected set of data types successfully started up.
   // If this test fails after adding a new data type, carefully consider whether
   // the type should be enabled in Local Sync mode, i.e. for roaming profiles on
diff --git a/chrome/browser/sync/test/integration/single_client_offer_sync_test.cc b/chrome/browser/sync/test/integration/single_client_offer_sync_test.cc
index f67445acf..f3a45a1 100644
--- a/chrome/browser/sync/test/integration/single_client_offer_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_offer_sync_test.cc
@@ -34,9 +34,6 @@
   loop->Quit();
 }
 
-const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
-    syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
-
 }  // namespace
 
 class SingleClientOfferSyncTest : public SyncTest {
@@ -102,10 +99,14 @@
 
   // Turn sync on again, the data should come back.
   GetSyncService(0)->SetSyncFeatureRequested();
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // StopAndClear() also clears the "first setup complete" flag, so set it
   // again.
   GetSyncService(0)->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-      kSetSourceFromTest);
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+
   // Wait until Sync restores the card and it arrives at PDM.
   WaitForNumberOfOffers(1, pdm);
   EXPECT_EQ(1uL, pdm->GetAutofillOffers().size());
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
index f0b4839..3ecb1d6 100644
--- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -89,8 +89,6 @@
 const char kLocalGuidA[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44A";
 const char kDifferentBillingAddressId[] = "another address entity ID";
 const base::Time kArbitraryDefaultTime = base::Time::FromDoubleT(25);
-const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
-    syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
 
 template <class T>
 class AutofillWebDataServiceConsumer : public WebDataServiceConsumer {
@@ -412,10 +410,14 @@
 
   // Turn sync on again, the data should come back.
   GetSyncService(0)->SetSyncFeatureRequested();
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // StopAndClear() also clears the "first setup complete" flag, so set it
   // again.
   GetSyncService(0)->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-      kSetSourceFromTest);
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+
   // Wait until Sync restores the card and it arrives at PDM.
   WaitForNumberOfCards(1, pdm);
 
@@ -1247,8 +1249,10 @@
   // complete.
   secondary_account_helper::GrantSyncConsent(profile(), "user@email.com");
   GetSyncService(0)->SetSyncFeatureRequested();
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   GetSyncService(0)->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-      kSetSourceFromTest);
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Wait for Sync to get reconfigured into feature mode.
   ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
@@ -1333,8 +1337,10 @@
   ASSERT_EQ(syncer::SyncService::TransportState::CONFIGURING,
             GetSyncService(0)->GetTransportState());
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   GetSyncService(0)->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
-      kSetSourceFromTest);
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Wait for Sync to get reconfigured into feature mode.
   ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
diff --git a/chrome/browser/sync/test/integration/single_client_web_apps_sync_generated_icon_fix_sync_test.cc b/chrome/browser/sync/test/integration/single_client_web_apps_sync_generated_icon_fix_sync_test.cc
index dc26b268..45b93ac 100644
--- a/chrome/browser/sync/test/integration/single_client_web_apps_sync_generated_icon_fix_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_web_apps_sync_generated_icon_fix_sync_test.cc
@@ -107,7 +107,8 @@
   // Insert web app into sync profile.
   // Fields copied from chrome/test/data/web_apps/basic.json.
   GURL start_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   sync_pb::EntitySpecifics specifics;
   sync_pb::WebAppSpecifics& web_app_specifics = *specifics.mutable_web_app();
   web_app_specifics.set_start_url(start_url.spec());
diff --git a/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc b/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc
index 0a5a5558..28fd9062 100644
--- a/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc
@@ -177,7 +177,7 @@
   info.start_url = url;
   info.scope = url;
   info.manifest_id = GenerateManifestId(relative_manifest_id, url);
-  const AppId installed_app_id =
+  const webapps::AppId installed_app_id =
       apps_helper::InstallWebApp(GetProfile(0), info);
 
   const std::string expected_app_id = GenerateAppId(
@@ -207,7 +207,7 @@
   info.start_url = url;
   info.scope = url;
   info.manifest_id = GenerateManifestId(relative_manifest_id, url);
-  const AppId installed_app_id =
+  const webapps::AppId installed_app_id =
       apps_helper::InstallWebApp(GetProfile(0), info);
 
   const std::string expected_app_id = GenerateAppId(
diff --git a/chrome/browser/sync/test/integration/sync_disabled_checker.cc b/chrome/browser/sync/test/integration/sync_disabled_checker.cc
index c9053be..295d40d 100644
--- a/chrome/browser/sync/test/integration/sync_disabled_checker.cc
+++ b/chrome/browser/sync/test/integration/sync_disabled_checker.cc
@@ -4,18 +4,27 @@
 
 #include "chrome/browser/sync/test/integration/sync_disabled_checker.h"
 
+#include "build/build_config.h"
+
 SyncDisabledChecker::SyncDisabledChecker(syncer::SyncServiceImpl* service)
     : SingleClientStatusChangeChecker(service) {}
 
 SyncDisabledChecker::~SyncDisabledChecker() = default;
 
 bool SyncDisabledChecker::IsExitConditionSatisfied(std::ostream* os) {
+  // TODO(crbug.com/1445931): Revisit condition below to simplify and/or unify
+  // across platforms.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  *os << "Waiting until sync is disabled via dashboard.";
+  return service()->IsSyncFeatureDisabledViaDashboard();
+#else   // BUILDFLAG(IS_CHROMEOS_ASH)
   *os << "Waiting until sync is disabled."
       << " IsSetupInProgress:" << service()->IsSetupInProgress()
       << " IsInitialSyncFeatureSetupComplete:"
       << service()->GetUserSettings()->IsInitialSyncFeatureSetupComplete();
   return !service()->IsSetupInProgress() &&
          !service()->GetUserSettings()->IsInitialSyncFeatureSetupComplete();
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void SyncDisabledChecker::WaitDone() {
diff --git a/chrome/browser/sync/test/integration/sync_service_impl_harness.cc b/chrome/browser/sync/test/integration/sync_service_impl_harness.cc
index 0a9ae5c..61ec27c 100644
--- a/chrome/browser/sync/test/integration/sync_service_impl_harness.cc
+++ b/chrome/browser/sync/test/integration/sync_service_impl_harness.cc
@@ -323,8 +323,10 @@
 
 void SyncServiceImplHarness::FinishSyncSetup() {
   sync_blocker_.reset();
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   service()->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
       syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void SyncServiceImplHarness::StopSyncServiceAndClearData() {
@@ -345,8 +347,11 @@
   DVLOG(1) << "Engine Initialized successfully.";
 
   blocker.reset();
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   service()->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
       syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   if (!AwaitSyncSetupCompletion()) {
     LOG(FATAL) << "AwaitSyncSetupCompletion failed.";
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc b/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
index 1a584a1..c68ec91 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
@@ -95,7 +95,7 @@
     return embedded_test_server()->GetURL("/web_apps/no_service_worker.html");
   }
 
-  AppId InstallAppAsUserInitiated(
+  webapps::AppId InstallAppAsUserInitiated(
       Profile* profile,
       webapps::WebappInstallSource source =
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
@@ -106,7 +106,7 @@
     }
     EXPECT_TRUE(ui_test_utils::NavigateToURL(browser, start_url));
 
-    AppId app_id;
+    webapps::AppId app_id;
     base::RunLoop run_loop;
     auto* provider = WebAppProvider::GetForTest(profile);
     provider->scheduler().FetchManifestAndInstall(
@@ -114,35 +114,36 @@
         browser->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
         /*bypass_service_worker_check=*/false,
         base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting(
-            [&](const AppId& new_app_id, webapps::InstallResultCode code) {
-              EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
-              app_id = new_app_id;
-              run_loop.Quit();
-            }),
+        base::BindLambdaForTesting([&](const webapps::AppId& new_app_id,
+                                       webapps::InstallResultCode code) {
+          EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
+          app_id = new_app_id;
+          run_loop.Quit();
+        }),
         /*use_fallback=*/true);
     run_loop.Run();
     return app_id;
   }
 
-  AppId InstallApp(const web_app::WebAppInstallInfo& info, Profile* profile) {
+  webapps::AppId InstallApp(const web_app::WebAppInstallInfo& info,
+                            Profile* profile) {
     return InstallApp(info, profile,
                       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
   }
 
-  AppId InstallApp(const web_app::WebAppInstallInfo& info,
-                   Profile* profile,
-                   webapps::WebappInstallSource source) {
+  webapps::AppId InstallApp(const web_app::WebAppInstallInfo& info,
+                            Profile* profile,
+                            webapps::WebappInstallSource source) {
     DCHECK(info.start_url.is_valid());
 
     base::RunLoop run_loop;
-    AppId app_id;
+    webapps::AppId app_id;
     auto* provider = WebAppProvider::GetForTest(profile);
     provider->scheduler().InstallFromInfo(
         std::make_unique<web_app::WebAppInstallInfo>(info.Clone()),
         /*overwrite_existing_manifest_fields=*/true, source,
         base::BindLambdaForTesting(
-            [&run_loop, &app_id](const AppId& new_app_id,
+            [&run_loop, &app_id](const webapps::AppId& new_app_id,
                                  webapps::InstallResultCode code) {
               DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
               app_id = new_app_id;
@@ -171,7 +172,7 @@
     return extensions::ExtensionSystem::Get(profile)->app_sorting();
   }
 
-  std::vector<AppId> GetAllAppIdsForProfile(Profile* profile) {
+  std::vector<webapps::AppId> GetAllAppIdsForProfile(Profile* profile) {
     return GetRegistrar(profile).GetAppIds();
   }
 
@@ -188,8 +189,8 @@
               ElementsAreArray(GetAllAppIdsForProfile(GetProfile(1))));
 
   // Install web app to both profiles.
-  AppId app_id = InstallAppAsUserInitiated(GetProfile(0));
-  AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1));
+  webapps::AppId app_id = InstallAppAsUserInitiated(GetProfile(0));
+  webapps::AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1));
 
   EXPECT_EQ(app_id, app_id2);
 
@@ -209,10 +210,10 @@
   info.start_url = GURL("http://www.chromium.org/path");
 
   // Install web app to both profiles.
-  AppId app_id = InstallApp(info, GetProfile(0));
+  webapps::AppId app_id = InstallApp(info, GetProfile(0));
   // The web app has a different title on the second profile.
   info.title = u"Test name 2";
-  AppId app_id2 = InstallApp(info, GetProfile(1));
+  webapps::AppId app_id2 = InstallApp(info, GetProfile(1));
 
   EXPECT_EQ(app_id, app_id2);
 
@@ -248,10 +249,10 @@
   info.user_display_mode = mojom::UserDisplayMode::kStandalone;
 
   // Install web app to both profiles.
-  AppId app_id = InstallApp(info, GetProfile(0));
+  webapps::AppId app_id = InstallApp(info, GetProfile(0));
   // The web app has a different open on the second profile.
   info.user_display_mode = mojom::UserDisplayMode::kBrowser;
-  AppId app_id2 = InstallApp(info, GetProfile(1));
+  webapps::AppId app_id2 = InstallApp(info, GetProfile(1));
 
   EXPECT_EQ(app_id, app_id2);
 
@@ -280,7 +281,7 @@
   install_observer.BeginListening();
   install_observer_with_os_hooks.BeginListening();
   // Install web app to profile 0 and wait for it to sync to profile 1.
-  AppId app_id = InstallAppAsUserInitiated(GetProfile(0));
+  webapps::AppId app_id = InstallAppAsUserInitiated(GetProfile(0));
   if (AreAppsLocallyInstalledBySync()) {
     EXPECT_EQ(install_observer_with_os_hooks.Wait(), app_id);
   } else {
@@ -320,8 +321,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   // Install web app to both profiles.
-  AppId app_id = InstallAppAsUserInitiated(GetProfile(0));
-  AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1));
+  webapps::AppId app_id = InstallAppAsUserInitiated(GetProfile(0));
+  webapps::AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1));
   EXPECT_EQ(app_id, app_id2);
 
   ASSERT_TRUE(SetupSync());
@@ -344,7 +345,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   // Install a non-syncing web app.
-  AppId app_id = InstallAppAsUserInitiated(
+  webapps::AppId app_id = InstallAppAsUserInitiated(
       GetProfile(0), webapps::WebappInstallSource::EXTERNAL_DEFAULT);
 
   ASSERT_TRUE(AwaitWebAppQuiescence());
@@ -363,11 +364,11 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   // Install a non-syncing web app.
-  AppId app_id = InstallAppAsUserInitiated(
+  webapps::AppId app_id = InstallAppAsUserInitiated(
       GetProfile(0), webapps::WebappInstallSource::EXTERNAL_DEFAULT);
 
   // Install the same app as a syncing app on profile 1.
-  AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1));
+  webapps::AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1));
   EXPECT_EQ(app_id, app_id2);
 
   ASSERT_TRUE(AwaitWebAppQuiescence());
@@ -402,11 +403,11 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   // Install a non-syncing web app.
-  AppId app_id = InstallAppAsUserInitiated(
+  webapps::AppId app_id = InstallAppAsUserInitiated(
       GetProfile(0), webapps::WebappInstallSource::EXTERNAL_POLICY);
 
   // Install the same app as a syncing app on profile 1.
-  AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1));
+  webapps::AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1));
   EXPECT_EQ(app_id, app_id2);
 
   ASSERT_TRUE(AwaitWebAppQuiescence());
@@ -439,7 +440,7 @@
               ElementsAreArray(GetAllAppIdsForProfile(GetProfile(1))));
   ASSERT_TRUE(embedded_test_server()->Start());
 
-  AppId app_id = InstallAppAsUserInitiated(GetProfile(0));
+  webapps::AppId app_id = InstallAppAsUserInitiated(GetProfile(0));
 
   syncer::StringOrdinal page_ordinal =
       GetAppSorting(GetProfile(0))->GetNaturalAppPageOrdinal();
@@ -467,8 +468,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   // Install two different apps.
-  AppId app_id1 = InstallAppAsUserInitiated(GetProfile(0));
-  AppId app_id2 = InstallAppAsUserInitiated(
+  webapps::AppId app_id1 = InstallAppAsUserInitiated(GetProfile(0));
+  webapps::AppId app_id2 = InstallAppAsUserInitiated(
       GetProfile(0), webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
       GetUserInitiatedAppURL2());
   ASSERT_NE(app_id1, app_id2);
@@ -522,7 +523,7 @@
               ElementsAreArray(GetAllAppIdsForProfile(GetProfile(1))));
   ASSERT_TRUE(embedded_test_server()->Start());
 
-  AppId app_id;
+  webapps::AppId app_id;
   // Install & uninstall on profile 0, and validate profile 1 sees it.
   {
     WebAppTestInstallObserver app_listener(GetProfile(1));
@@ -570,7 +571,7 @@
               ElementsAreArray(GetAllAppIdsForProfile(GetProfile(1))));
   ASSERT_TRUE(embedded_test_server()->Start());
 
-  AppId app_id;
+  webapps::AppId app_id;
   // Install & uninstall on profile 0, and validate profile 1 sees it.
   {
     WebAppTestInstallObserver app_listener(GetProfile(1));
@@ -641,17 +642,17 @@
   // Install & uninstall on profile 0, and validate profile 1 sees it.
   {
     base::RunLoop loop;
-    base::RepeatingCallback<void(const AppId&)> on_installed_closure;
-    base::RepeatingCallback<void(const AppId&)> on_hooks_closure;
+    base::RepeatingCallback<void(const webapps::AppId&)> on_installed_closure;
+    base::RepeatingCallback<void(const webapps::AppId&)> on_hooks_closure;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     on_installed_closure = base::DoNothing();
     on_hooks_closure = base::BindLambdaForTesting(
-        [&](const AppId& installed_app_id) { loop.Quit(); });
+        [&](const webapps::AppId& installed_app_id) { loop.Quit(); });
 #else
     on_installed_closure = base::BindLambdaForTesting(
-        [&](const AppId& installed_app_id) { loop.Quit(); });
+        [&](const webapps::AppId& installed_app_id) { loop.Quit(); });
     on_hooks_closure = base::BindLambdaForTesting(
-        [](const AppId& installed_app_id) { FAIL(); });
+        [](const webapps::AppId& installed_app_id) { FAIL(); });
 #endif
     WebAppInstallManagerObserverAdapter app_listener(GetProfile(1));
     app_listener.SetWebAppInstalledDelegate(on_installed_closure);
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_generated_icon_fix_test.cc b/chrome/browser/sync/test/integration/two_client_web_apps_generated_icon_fix_test.cc
index 6576d981..6f577b1a 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_generated_icon_fix_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_generated_icon_fix_test.cc
@@ -23,9 +23,10 @@
 namespace {
 
 struct GeneratedIconFixFutures {
-  base::test::TestFuture<const AppId&, GeneratedIconFixScheduleDecision>
+  base::test::TestFuture<const webapps::AppId&,
+                         GeneratedIconFixScheduleDecision>
       schedule;
-  base::test::TestFuture<const AppId&, GeneratedIconFixResult> fix;
+  base::test::TestFuture<const webapps::AppId&, GeneratedIconFixResult> fix;
 
   explicit GeneratedIconFixFutures(FakeWebAppProvider& provider) {
     GeneratedIconFixManager& generated_icon_fix_manager =
@@ -55,7 +56,7 @@
     WebAppsSyncTestBase::TearDownOnMainThread();
   }
 
-  AppId SyncBrokenIcon(Profile* source, Profile* destination) {
+  webapps::AppId SyncBrokenIcon(Profile* source, Profile* destination) {
     WebAppTestInstallObserver install_observer{destination};
 
     // Install on source profile.
@@ -65,7 +66,7 @@
     info->start_url = GURL("https://example.com");
     info->manifest_icons.emplace_back(
         apps::IconInfo(GURL("https://example.com/icon.png"), 256));
-    AppId app_id = test::InstallWebApp(source, std::move(info));
+    webapps::AppId app_id = test::InstallWebApp(source, std::move(info));
 
     // Wait for sync install on destination profile.
     install_observer.BeginListening({app_id});
@@ -90,7 +91,7 @@
              is_correct_color == other.is_correct_color;
     }
   };
-  IconState CheckIconState(Profile* profile, const AppId& app_id) {
+  IconState CheckIconState(Profile* profile, const webapps::AppId& app_id) {
     base::test::TestFuture<std::map<SquareSizePx, SkBitmap>> icons_future;
     fake_providers_[profile]->icon_manager().ReadIcons(
         app_id, IconPurpose::ANY, {256}, icons_future.GetCallback());
@@ -139,7 +140,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(TwoClientGeneratedIconFixSyncTest, Fix) {
-  AppId app_id = SyncBrokenIcon(GetProfile(0), GetProfile(1));
+  webapps::AppId app_id = SyncBrokenIcon(GetProfile(0), GetProfile(1));
 
   EXPECT_EQ(CheckIconState(GetProfile(1), app_id),
             (IconState{.is_generated = true, .is_correct_color = false}));
@@ -153,10 +154,10 @@
   // time for a real restart).
   provider1.generated_icon_fix_manager().Start();
 
-  EXPECT_EQ(futures.schedule.Get<AppId>(), app_id);
+  EXPECT_EQ(futures.schedule.Get<webapps::AppId>(), app_id);
   EXPECT_EQ(futures.schedule.Get<GeneratedIconFixScheduleDecision>(),
             GeneratedIconFixScheduleDecision::kSchedule);
-  EXPECT_EQ(futures.fix.Get<AppId>(), app_id);
+  EXPECT_EQ(futures.fix.Get<webapps::AppId>(), app_id);
   EXPECT_EQ(futures.fix.Get<GeneratedIconFixResult>(),
             GeneratedIconFixResult::kSuccess);
 
@@ -165,7 +166,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(TwoClientGeneratedIconFixSyncTest, TimeWindowExpired) {
-  AppId app_id = SyncBrokenIcon(GetProfile(0), GetProfile(1));
+  webapps::AppId app_id = SyncBrokenIcon(GetProfile(0), GetProfile(1));
 
   EXPECT_EQ(CheckIconState(GetProfile(1), app_id),
             (IconState{.is_generated = true, .is_correct_color = false}));
@@ -182,7 +183,7 @@
   // time for a real restart).
   provider1.generated_icon_fix_manager().Start();
 
-  EXPECT_EQ(futures.schedule.Get<AppId>(), app_id);
+  EXPECT_EQ(futures.schedule.Get<webapps::AppId>(), app_id);
   EXPECT_EQ(futures.schedule.Get<GeneratedIconFixScheduleDecision>(),
             GeneratedIconFixScheduleDecision::kTimeWindowExpired);
   EXPECT_FALSE(provider1.generated_icon_fix_manager()
@@ -196,7 +197,7 @@
 IN_PROC_BROWSER_TEST_F(TwoClientGeneratedIconFixSyncTest, NotRequired) {
   EnableIconServing(GetProfile(1));
 
-  AppId app_id = SyncBrokenIcon(GetProfile(0), GetProfile(1));
+  webapps::AppId app_id = SyncBrokenIcon(GetProfile(0), GetProfile(1));
 
   EXPECT_EQ(CheckIconState(GetProfile(1), app_id),
             (IconState{.is_generated = false, .is_correct_color = true}));
@@ -208,7 +209,7 @@
   // time for a real restart).
   provider1.generated_icon_fix_manager().Start();
 
-  EXPECT_EQ(futures.schedule.Get<AppId>(), app_id);
+  EXPECT_EQ(futures.schedule.Get<webapps::AppId>(), app_id);
   EXPECT_EQ(futures.schedule.Get<GeneratedIconFixScheduleDecision>(),
             GeneratedIconFixScheduleDecision::kNotRequired);
   EXPECT_FALSE(provider1.generated_icon_fix_manager()
@@ -217,7 +218,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(TwoClientGeneratedIconFixSyncTest, AppUninstalled) {
-  AppId app_id = SyncBrokenIcon(GetProfile(0), GetProfile(1));
+  webapps::AppId app_id = SyncBrokenIcon(GetProfile(0), GetProfile(1));
 
   EXPECT_EQ(CheckIconState(GetProfile(1), app_id),
             (IconState{.is_generated = true, .is_correct_color = false}));
@@ -229,7 +230,7 @@
   // for a real restart).
   provider1.generated_icon_fix_manager().Start();
 
-  EXPECT_EQ(futures.schedule.Get<AppId>(), app_id);
+  EXPECT_EQ(futures.schedule.Get<webapps::AppId>(), app_id);
   EXPECT_EQ(futures.schedule.Get<GeneratedIconFixScheduleDecision>(),
             GeneratedIconFixScheduleDecision::kSchedule);
 
@@ -238,7 +239,7 @@
   // command queue is difficult.
   provider1.sync_bridge_unsafe().BeginUpdate()->DeleteApp(app_id);
 
-  EXPECT_EQ(futures.fix.Get<AppId>(), app_id);
+  EXPECT_EQ(futures.fix.Get<webapps::AppId>(), app_id);
   EXPECT_EQ(futures.fix.Get<GeneratedIconFixResult>(),
             GeneratedIconFixResult::kAppUninstalled);
 }
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_web_apps_sync_test.cc
index b6140ae..3680c88 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_sync_test.cc
@@ -44,7 +44,7 @@
   }
 
   void OnWebAppUserDisplayModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       mojom::UserDisplayMode user_display_mode) override {
     run_loop_.Quit();
   }
@@ -82,9 +82,10 @@
   }
 
   bool AllProfilesHaveSameWebAppIds() {
-    absl::optional<base::flat_set<AppId>> app_ids;
+    absl::optional<base::flat_set<webapps::AppId>> app_ids;
     for (Profile* profile : GetAllProfiles()) {
-      base::flat_set<AppId> profile_app_ids(GetRegistrar(profile).GetAppIds());
+      base::flat_set<webapps::AppId> profile_app_ids(
+          GetRegistrar(profile).GetAppIds());
       if (!app_ids) {
         app_ids = profile_app_ids;
       } else {
@@ -109,7 +110,7 @@
   info.description = u"Test description";
   info.start_url = GURL("http://www.chromium.org/path");
   info.scope = GURL("http://www.chromium.org/");
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
 
   EXPECT_EQ(install_observer.Wait(), app_id);
   const WebAppRegistrar& registrar = GetRegistrar(GetProfile(1));
@@ -127,7 +128,7 @@
   WebAppInstallInfo info;
   info.title = u"Test name";
   info.start_url = GURL("http://www.chromium.org/");
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
 
   EXPECT_EQ(install_observer.Wait(), app_id);
   const WebAppRegistrar& registrar = GetRegistrar(GetProfile(1));
@@ -145,7 +146,7 @@
   info.title = u"Test name";
   info.start_url = GURL("http://www.chromium.org/");
   info.theme_color = SK_ColorBLUE;
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
   EXPECT_EQ(GetRegistrar(GetProfile(0)).GetAppThemeColor(app_id),
             info.theme_color);
 
@@ -165,7 +166,7 @@
   WebAppInstallInfo info;
   info.title = u"Test name";
   info.start_url = GURL("http://www.chromium.org/");
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
   EXPECT_TRUE(GetRegistrar(GetProfile(0)).IsLocallyInstalled(app_id));
 
   EXPECT_EQ(install_observer.Wait(), app_id);
@@ -186,7 +187,7 @@
   info_a.start_url = GURL("http://www.chromium.org/path/to/start_url");
   info_a.scope = GURL("http://www.chromium.org/path/to/");
   info_a.theme_color = SK_ColorBLUE;
-  AppId app_id_a = apps_helper::InstallWebApp(GetProfile(0), info_a);
+  webapps::AppId app_id_a = apps_helper::InstallWebApp(GetProfile(0), info_a);
 
   EXPECT_EQ(WebAppTestInstallObserver(GetProfile(1)).BeginListeningAndWait(),
             app_id_a);
@@ -206,7 +207,7 @@
   info_b.start_url = GURL("http://www.chromium.org/path/to/start_url");
   info_b.scope = GURL("http://www.chromium.org/path/to/");
   info_b.theme_color = SK_ColorRED;
-  AppId app_id_b = apps_helper::InstallWebApp(GetProfile(0), info_b);
+  webapps::AppId app_id_b = apps_helper::InstallWebApp(GetProfile(0), info_b);
   EXPECT_EQ(app_id_a, app_id_b);
   EXPECT_EQ(base::UTF8ToUTF16(registrar0.GetAppShortName(app_id_a)),
             info_b.title);
@@ -220,7 +221,7 @@
   WebAppInstallInfo infoC;
   infoC.title = u"Different test name";
   infoC.start_url = GURL("http://www.notchromium.org/");
-  AppId app_id_c = apps_helper::InstallWebApp(GetProfile(0), infoC);
+  webapps::AppId app_id_c = apps_helper::InstallWebApp(GetProfile(0), infoC);
   EXPECT_NE(app_id_a, app_id_c);
   EXPECT_EQ(WebAppTestInstallObserver(GetProfile(1)).BeginListeningAndWait(),
             app_id_c);
@@ -247,7 +248,7 @@
   destInstallObserver.BeginListening();
 
   // Install favicon only page as web app.
-  AppId app_id;
+  webapps::AppId app_id;
   {
     Browser* browser = CreateBrowser(sourceProfile);
     ASSERT_TRUE(ui_test_utils::NavigateToURL(
@@ -269,7 +270,7 @@
   EXPECT_FALSE(manifest_icons[0].square_size_px.has_value());
 
   // Wait for app to sync across.
-  AppId synced_app_id = destInstallObserver.Wait();
+  webapps::AppId synced_app_id = destInstallObserver.Wait();
   EXPECT_EQ(synced_app_id, app_id);
   EXPECT_EQ(GetRegistrar(destProfile).GetAppShortName(app_id), "Favicon only");
   manifest_icons = GetRegistrar(destProfile).GetAppIconInfos(app_id);
@@ -293,13 +294,13 @@
   info.title = u"Test app";
   info.start_url =
       embedded_test_server()->GetURL("/web_apps/different_start_url.html");
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
   EXPECT_EQ(GetRegistrar(source_profile).GetAppShortName(app_id), "Test app");
   EXPECT_EQ(GetRegistrar(source_profile).GetAppStartUrl(app_id),
             info.start_url);
 
   // Wait for app to sync across.
-  AppId synced_app_id = dest_install_observer.Wait();
+  webapps::AppId synced_app_id = dest_install_observer.Wait();
   ASSERT_EQ(synced_app_id, app_id);
   EXPECT_EQ(GetRegistrar(dest_profile).GetAppShortName(app_id), "Test app");
   EXPECT_EQ(GetRegistrar(dest_profile).GetAppStartUrl(app_id), info.start_url);
@@ -323,12 +324,12 @@
   info.title = u"Correct App Name";
   info.start_url =
       embedded_test_server()->GetURL("/web_apps/bad_title_only.html");
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
   EXPECT_EQ(GetRegistrar(source_profile).GetAppShortName(app_id),
             "Correct App Name");
 
   // Wait for app to sync across.
-  AppId synced_app_id = dest_install_observer.Wait();
+  webapps::AppId synced_app_id = dest_install_observer.Wait();
   EXPECT_EQ(synced_app_id, app_id);
   EXPECT_EQ(GetRegistrar(dest_profile).GetAppShortName(app_id),
             "Correct App Name");
@@ -349,12 +350,12 @@
   WebAppInstallInfo info;
   info.title = u"Incorrect App Name";
   info.start_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
   EXPECT_EQ(GetRegistrar(source_profile).GetAppShortName(app_id),
             "Incorrect App Name");
 
   // Wait for app to sync across.
-  AppId synced_app_id = dest_install_observer.Wait();
+  webapps::AppId synced_app_id = dest_install_observer.Wait();
   EXPECT_EQ(synced_app_id, app_id);
   EXPECT_EQ(GetRegistrar(dest_profile).GetAppShortName(app_id),
             "Basic web app");
@@ -380,11 +381,11 @@
   icon_info.url = embedded_test_server()->GetURL("/web_apps/blue-192.png");
   icon_info.purpose = apps::IconInfo::Purpose::kAny;
   info.manifest_icons.push_back(icon_info);
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
   EXPECT_EQ(GetRegistrar(source_profile).GetAppShortName(app_id), "Blue icon");
 
   // Wait for app to sync across.
-  AppId synced_app_id = dest_install_observer.Wait();
+  webapps::AppId synced_app_id = dest_install_observer.Wait();
   EXPECT_EQ(synced_app_id, app_id);
   EXPECT_EQ(GetRegistrar(dest_profile).GetAppShortName(app_id), "Blue icon");
 
@@ -420,7 +421,7 @@
   info.start_url = GURL("http://www.chromium.org/path");
   info.scope = GURL("http://www.chromium.org/");
   info.user_display_mode = mojom::UserDisplayMode::kStandalone;
-  AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
+  webapps::AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
 
   EXPECT_EQ(install_observer.Wait(), app_id);
   EXPECT_TRUE(AllProfilesHaveSameWebAppIds());
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn
index 3f8f557..b4cb3d9 100644
--- a/chrome/browser/tab/BUILD.gn
+++ b/chrome/browser/tab/BUILD.gn
@@ -36,10 +36,7 @@
     "java/src/org/chromium/chrome/browser/tab/TrustedCdn.java",
     "java/src/org/chromium/chrome/browser/tab/WebContentsState.java",
     "java/src/org/chromium/chrome/browser/tab/WebContentsStateBridge.java",
-    "java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java",
     "java/src/org/chromium/chrome/browser/tab/state/EmptyByteBufferPersistedTabDataStorage.java",
-    "java/src/org/chromium/chrome/browser/tab/state/EncryptedFilePersistedTabDataStorage.java",
-    "java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java",
     "java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedDataStorage.java",
     "java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java",
     "java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageFactory.java",
@@ -54,7 +51,6 @@
     "java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataStorage.java",
     "java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataStorageFactory.java",
     "java/src/org/chromium/chrome/browser/tab/state/PriceDropMetricsLogger.java",
-    "java/src/org/chromium/chrome/browser/tab/state/SerializedCriticalPersistedTabData.java",
     "java/src/org/chromium/chrome/browser/tab/state/Serializer.java",
     "java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java",
   ]
@@ -70,7 +66,6 @@
   ]
 
   deps = [
-    ":critical_persisted_tab_data_flatbuffer_java",
     ":critical_persisted_tab_data_proto_java",
     ":java_resources",
     "//base:base_java",
@@ -142,11 +137,6 @@
   sources = [ "$proto_path/shopping_persisted_tab_data.proto" ]
 }
 
-flatbuffer_java_library("critical_persisted_tab_data_flatbuffer_java") {
-  root_dir = "java/src/org/chromium/chrome/browser/tab/state/flatbuffer"
-  sources = [ "$root_dir/critical_persisted_tab_data.fbs" ]
-}
-
 robolectric_library("junit") {
   sources = [
     "java/src/org/chromium/chrome/browser/tab/CurrentTabObserverTest.java",
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Tab.java
index 4b12128..eabb631 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -28,6 +28,7 @@
  */
 public interface Tab extends TabLifecycle {
     public static final int INVALID_TAB_ID = -1;
+    public static final long INVALID_TIMESTAMP = -1;
 
     @IntDef({TabLoadStatus.PAGE_LOAD_FAILED, TabLoadStatus.DEFAULT_PAGE_LOAD})
     @Retention(RetentionPolicy.SOURCE)
@@ -279,13 +280,6 @@
     void goForward();
 
     /**
-     * Set whether {@link Tab} metadata (specifically all {@link PersistedTabData})
-     * will be saved. Not all Tabs need to be persisted across restarts.
-     * The default value when a Tab is initialized is false.
-     */
-    void setIsTabSaveEnabled(boolean isSaveEnabled);
-
-    /**
      * @return true if the {@link Tab} is a custom tab.
      */
     boolean isCustomTab();
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabStateAttributes.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabStateAttributes.java
index a81f254..8c8454b6 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabStateAttributes.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabStateAttributes.java
@@ -13,7 +13,6 @@
 import org.chromium.base.UserDataHost;
 import org.chromium.base.task.PostTask;
 import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
@@ -213,9 +212,6 @@
             return;
         }
         mDirtinessState = dirtiness;
-        if (mDirtinessState == DirtinessState.DIRTY) {
-            CriticalPersistedTabData.from(mTab).setShouldSave();
-        }
         for (Observer observer : mObservers) {
             observer.onTabStateDirtinessChanged(mTab, mDirtinessState);
         }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabStateAttributesTest.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabStateAttributesTest.java
index 5b4fe90a..5c9d313 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabStateAttributesTest.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabStateAttributesTest.java
@@ -30,7 +30,6 @@
 import org.chromium.base.task.test.ShadowPostTask;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Features;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
@@ -117,34 +116,6 @@
     }
 
     @Test
-    public void testDefaultShouldSave() {
-        TabStateAttributes.createForTab(mTab, null);
-        Assert.assertTrue(CriticalPersistedTabData.from(mTab).getShouldSaveForTesting());
-        mTab.getUserDataHost().removeUserData(TabStateAttributes.class);
-        mTab.getUserDataHost().removeUserData(CriticalPersistedTabData.class);
-
-        TabStateAttributes.createForTab(mTab, TabCreationState.FROZEN_FOR_LAZY_LOAD);
-        Assert.assertTrue(CriticalPersistedTabData.from(mTab).getShouldSaveForTesting());
-        mTab.getUserDataHost().removeUserData(TabStateAttributes.class);
-        mTab.getUserDataHost().removeUserData(CriticalPersistedTabData.class);
-
-        TabStateAttributes.createForTab(mTab, TabCreationState.FROZEN_ON_RESTORE);
-        Assert.assertFalse(CriticalPersistedTabData.from(mTab).getShouldSaveForTesting());
-        mTab.getUserDataHost().removeUserData(TabStateAttributes.class);
-        mTab.getUserDataHost().removeUserData(CriticalPersistedTabData.class);
-
-        TabStateAttributes.createForTab(mTab, TabCreationState.LIVE_IN_BACKGROUND);
-        Assert.assertFalse(CriticalPersistedTabData.from(mTab).getShouldSaveForTesting());
-        mTab.getUserDataHost().removeUserData(TabStateAttributes.class);
-        mTab.getUserDataHost().removeUserData(CriticalPersistedTabData.class);
-
-        TabStateAttributes.createForTab(mTab, TabCreationState.LIVE_IN_FOREGROUND);
-        Assert.assertFalse(CriticalPersistedTabData.from(mTab).getShouldSaveForTesting());
-        mTab.getUserDataHost().removeUserData(TabStateAttributes.class);
-        mTab.getUserDataHost().removeUserData(CriticalPersistedTabData.class);
-    }
-
-    @Test
     public void testTitleUpdate() {
         TabStateAttributes.createForTab(mTab, TabCreationState.FROZEN_ON_RESTORE);
         TabStateAttributes.from(mTab).addObserver(mAttributesObserver);
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
deleted file mode 100644
index 71e9523c..0000000
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
+++ /dev/null
@@ -1,588 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// 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.tab.state;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.google.flatbuffers.FlatBufferBuilder;
-
-import org.chromium.base.Callback;
-import org.chromium.base.Log;
-import org.chromium.base.ResettersForTesting;
-import org.chromium.base.TraceEvent;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.build.annotations.DoNotClassMerge;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabLaunchType;
-import org.chromium.chrome.browser.tab.TabState;
-import org.chromium.chrome.browser.tab.TabUserAgent;
-import org.chromium.chrome.browser.tab.WebContentsState;
-import org.chromium.chrome.browser.tab.WebContentsStateBridge;
-import org.chromium.chrome.browser.tab.flatbuffer.CriticalPersistedTabDataFlatBuffer;
-import org.chromium.chrome.browser.tab.flatbuffer.LaunchTypeAtCreation;
-import org.chromium.chrome.browser.tab.flatbuffer.UserAgentType;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.common.Referrer;
-
-import java.nio.ByteBuffer;
-
-/**
- * Data which is core to the app and must be retrieved as quickly as possible on startup.
- *
- * This class should not be merged because it is being used as a key in a Map
- * in PersistedTabDataConfiguration.java.
- */
-@DoNotClassMerge
-public class CriticalPersistedTabData extends PersistedTabData {
-    private static final String TAG = "CriticalPTD";
-    private static final Class<CriticalPersistedTabData> USER_DATA_KEY =
-            CriticalPersistedTabData.class;
-
-    private static final String NULL_OPENER_APP_ID = " ";
-    private static final PersistedTabDataMapper<SerializedCriticalPersistedTabData> sMapper =
-            new PersistedTabDataMapper<SerializedCriticalPersistedTabData>() {
-                @Override
-                public SerializedCriticalPersistedTabData map(ByteBuffer byteBuffer) {
-                    if (byteBuffer == null || byteBuffer.limit() == 0) {
-                        return null;
-                    }
-                    SerializedCriticalPersistedTabData res = null;
-                    try {
-                        CriticalPersistedTabDataFlatBuffer flatBuffer =
-                                CriticalPersistedTabDataFlatBuffer
-                                        .getRootAsCriticalPersistedTabDataFlatBuffer(byteBuffer);
-                        ByteBuffer webContentsStateByteBuffer =
-                                flatBuffer.webContentsStateBytesAsByteBuffer();
-                        WebContentsState webContentsState =
-                                new WebContentsState(webContentsStateByteBuffer == null
-                                                ? ByteBuffer.allocateDirect(0)
-                                                : webContentsStateByteBuffer.slice());
-                        webContentsState.setVersion(
-                                WebContentsState.CONTENTS_STATE_CURRENT_VERSION);
-                        res = new SerializedCriticalPersistedTabData(flatBuffer.parentId(),
-                                flatBuffer.rootId(), flatBuffer.timestampMillis(), webContentsState,
-                                NULL_OPENER_APP_ID.equals(flatBuffer.openerAppId())
-                                        ? null
-                                        : flatBuffer.openerAppId(),
-                                flatBuffer.contentStateVersion(), flatBuffer.themeColor(),
-                                getLaunchType(flatBuffer.launchTypeAtCreation()),
-                                getTabUserAgentType(flatBuffer.userAgent()),
-                                flatBuffer.lastNavigationCommittedTimestampMillis());
-                    } catch (Exception e) {
-                        // TODO(crbug.com/1294613) Add in some metrics recording how often this
-                        // happens.
-                        Log.e(TAG,
-                                "Failed to deserialize CriticalPersistedTabDataFlatBuffer. "
-                                        + "Details: " + e.getMessage());
-                    }
-                    RecordHistogram.recordBooleanHistogram(
-                            "Tabs.PersistedTabData.Critical.Map.Success", res != null);
-                    return res;
-                }
-            };
-    public static final long INVALID_TIMESTAMP = -1;
-
-    private int mContentStateVersion;
-    private String mOpenerAppId;
-
-    private boolean mShouldSaveForTesting;
-    /** Tab level Request Desktop Site setting. */
-    private boolean mShouldSave;
-
-    @VisibleForTesting
-    public CriticalPersistedTabData(Tab tab) {
-        super(tab,
-                PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, tab.isIncognito())
-                        .getStorage(),
-                PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, tab.isIncognito())
-                        .getId());
-    }
-
-    /**
-     * @param tab {@link Tab} {@link CriticalPersistedTabData} is being stored for
-     * @param rootId root identifier for the {@link Tab}
-     * @param openerAppId identifier for app opener
-     * @param launchTypeAtCreation launch type at creation
-     * @param userAgent user agent for the {@link Tab}
-     */
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    CriticalPersistedTabData(Tab tab, String url, String title, int rootId, String openerAppId,
-            @Nullable @TabLaunchType Integer launchTypeAtCreation, @TabUserAgent int userAgent,
-            long lastNavigationCommittedTimestampMillis) {
-        this(tab);
-        mOpenerAppId = openerAppId;
-    }
-
-    /**
-     * @param tab {@link Tab} {@link CriticalPersistedTabData} is being stored for
-     * @param data serialized {@link CriticalPersistedTabData}
-     * @param storage {@link PersistedTabDataStorage} for {@link PersistedTabData}
-     * @param persistedTabDataId unique identifier for {@link PersistedTabData} in
-     * storage
-     * This constructor is public because that is needed for the reflection
-     * used in PersistedTabData.java
-     */
-    @VisibleForTesting
-    protected CriticalPersistedTabData(
-            Tab tab, ByteBuffer data, PersistedTabDataStorage storage, String persistedTabDataId) {
-        super(tab, storage, persistedTabDataId);
-        deserializeAndLog(data);
-    }
-
-    @VisibleForTesting
-    protected CriticalPersistedTabData(
-            Tab tab, PersistedTabDataStorage storage, String persistedTabDataId) {
-        super(tab, storage, persistedTabDataId);
-    }
-
-    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
-    public CriticalPersistedTabData(Tab tab, SerializedCriticalPersistedTabData serialized) {
-        this(tab, serialized.getUrl(), serialized.getTitle(), serialized.getRootId(),
-
-                serialized.getOpenerAppId(), serialized.getLaunchType(), serialized.getUserAgent(),
-                serialized.getLastNavigationCommittedTimestampMillis());
-    }
-
-    /**
-     * TODO(crbug.com/1096142) asynchronous from can be removed
-     * Acquire {@link CriticalPersistedTabData} from storage
-     * @param tab {@link Tab} {@link CriticalPersistedTabData} is being stored for.
-     *        At a minimum this needs to be a frozen {@link Tab} with an identifier
-     *        and isIncognito values set.
-     * @param callback callback to pass {@link PersistedTabData} back in
-     */
-    public static void from(Tab tab, Callback<CriticalPersistedTabData> callback) {
-        PersistedTabData.from(tab,
-                (data, storage, id, factoryCallback)
-                        -> {
-                    factoryCallback.onResult(new CriticalPersistedTabData(tab, data, storage, id));
-                },
-                (supplierCallback)
-                        -> supplierCallback.onResult(
-                                tab.isInitialized() ? CriticalPersistedTabData.build(tab) : null),
-                CriticalPersistedTabData.class, callback);
-    }
-
-    /**
-     * Acquire {@link CriticalPersistedTabData} from a {@link Tab} or create if it doesn't exist
-     * @param  tab corresponding {@link Tab} for which {@link CriticalPersistedTabData} is sought
-     * @return acquired or created {@link CriticalPersistedTabData}
-     */
-    public static CriticalPersistedTabData from(Tab tab) {
-        return PersistedTabData.from(
-                tab, CriticalPersistedTabData.class, () -> { return build(tab); });
-    }
-
-    /**
-     * Synchronously restore serialized {@link CriticalPersistedTabData}
-     * @param tabId identifier for the {@link Tab}
-     * @param isIncognito true if the {@link Tab} is incognito
-     * @return serialized {@link CriticalPersistedTabData}
-     * TODO(crbug.com/1119452) rethink CriticalPersistedTabData contract
-     */
-    public static SerializedCriticalPersistedTabData restore(int tabId, boolean isIncognito) {
-        PersistedTabDataConfiguration config =
-                PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, isIncognito);
-        return config.getStorage().restore(tabId, config.getId(), sMapper);
-    }
-
-    /**
-     * Asynchronously restore serialized {@link CriticalPersistedTabData}
-     * @param tabId identifier for the {@link Tab}
-     * @param isIncognito true if the {@link Tab} is incognito
-     * @param callback the serialized {@link CriticalPersistedTabData} is passed back in
-     */
-    public static void restore(
-            int tabId, boolean isIncognito, Callback<SerializedCriticalPersistedTabData> callback) {
-        PersistedTabDataConfiguration config =
-                PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, isIncognito);
-        config.getStorage().restore(tabId, config.getId(), callback, sMapper);
-    }
-
-    /**
-     * @param tab {@link Tab} associated with the {@link CriticalPersistedTabData}
-     * @param serialized {@link CriticalPersistedTabData} in serialized form
-     * @param isCriticalPersistedTabDataEnabled true if CriticalPersistedData is enabled
-     * as the storage/retrieval method
-     */
-    public static void build(Tab tab, SerializedCriticalPersistedTabData serialized) {
-        PersistedTabData.from(
-                tab, USER_DATA_KEY, () -> new CriticalPersistedTabData(tab, serialized));
-    }
-
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    public static CriticalPersistedTabData build(Tab tab) {
-        // CriticalPersistedTabData is initialized with default values
-        CriticalPersistedTabData criticalPersistedTabData = new CriticalPersistedTabData(
-                tab, "", "", tab.getId(), "", null, TabUserAgent.DEFAULT, INVALID_TIMESTAMP);
-        criticalPersistedTabData.save();
-        return criticalPersistedTabData;
-    }
-
-    // We are currently using the constructor
-    // CriticalPersistedTabData(Tab tab, SerializedCriticalPersistedTabData serialized) rather than
-    // deserialize as part of deserializing straight after the file read. Assuming this approach
-    // is successful, deserialize on CriticalPersistedTabData will be deprecated.
-    @Override
-    boolean deserialize(@Nullable ByteBuffer bytes) {
-        try (TraceEvent e = TraceEvent.scoped("CriticalPersistedTabData.Deserialize")) {
-            CriticalPersistedTabDataFlatBuffer deserialized =
-                    CriticalPersistedTabDataFlatBuffer.getRootAsCriticalPersistedTabDataFlatBuffer(
-                            bytes);
-            mContentStateVersion = deserialized.contentStateVersion();
-            mOpenerAppId = NULL_OPENER_APP_ID.equals(deserialized.openerAppId())
-                    ? null
-                    : deserialized.openerAppId();
-            return true;
-        }
-    }
-
-    @Override
-    public String getUmaTag() {
-        return "Critical";
-    }
-
-    @VisibleForTesting
-    static @Nullable @TabLaunchType Integer getLaunchType(int flatBufferLaunchType) {
-        switch (flatBufferLaunchType) {
-            case LaunchTypeAtCreation.FROM_LINK:
-                return TabLaunchType.FROM_LINK;
-            case LaunchTypeAtCreation.FROM_EXTERNAL_APP:
-                return TabLaunchType.FROM_EXTERNAL_APP;
-            case LaunchTypeAtCreation.FROM_CHROME_UI:
-                return TabLaunchType.FROM_CHROME_UI;
-            case LaunchTypeAtCreation.FROM_RESTORE:
-                return TabLaunchType.FROM_RESTORE;
-            case LaunchTypeAtCreation.FROM_LONGPRESS_FOREGROUND:
-                return TabLaunchType.FROM_LONGPRESS_FOREGROUND;
-            case LaunchTypeAtCreation.FROM_LONGPRESS_INCOGNITO:
-                return TabLaunchType.FROM_LONGPRESS_INCOGNITO;
-            case LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND:
-                return TabLaunchType.FROM_LONGPRESS_BACKGROUND;
-            case LaunchTypeAtCreation.FROM_REPARENTING:
-                return TabLaunchType.FROM_REPARENTING;
-            case LaunchTypeAtCreation.FROM_LAUNCHER_SHORTCUT:
-                return TabLaunchType.FROM_LAUNCHER_SHORTCUT;
-            case LaunchTypeAtCreation.FROM_SPECULATIVE_BACKGROUND_CREATION:
-                return TabLaunchType.FROM_SPECULATIVE_BACKGROUND_CREATION;
-            case LaunchTypeAtCreation.FROM_BROWSER_ACTIONS:
-                return TabLaunchType.FROM_BROWSER_ACTIONS;
-            case LaunchTypeAtCreation.FROM_LAUNCH_NEW_INCOGNITO_TAB:
-                return TabLaunchType.FROM_LAUNCH_NEW_INCOGNITO_TAB;
-            case LaunchTypeAtCreation.FROM_STARTUP:
-                return TabLaunchType.FROM_STARTUP;
-            case LaunchTypeAtCreation.FROM_START_SURFACE:
-                return TabLaunchType.FROM_START_SURFACE;
-            case LaunchTypeAtCreation.FROM_TAB_GROUP_UI:
-                return TabLaunchType.FROM_TAB_GROUP_UI;
-            case LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI:
-                return TabLaunchType.FROM_TAB_SWITCHER_UI;
-            case LaunchTypeAtCreation.FROM_RESTORE_TABS_UI:
-                return TabLaunchType.FROM_RESTORE_TABS_UI;
-            case LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND_IN_GROUP:
-                return TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP;
-            case LaunchTypeAtCreation.FROM_APP_WIDGET:
-                return TabLaunchType.FROM_APP_WIDGET;
-            case LaunchTypeAtCreation.FROM_RECENT_TABS:
-                return TabLaunchType.FROM_RECENT_TABS;
-            case LaunchTypeAtCreation.FROM_READING_LIST:
-                return TabLaunchType.FROM_READING_LIST;
-            case LaunchTypeAtCreation.FROM_OMNIBOX:
-                return TabLaunchType.FROM_OMNIBOX;
-            case LaunchTypeAtCreation.SIZE:
-                return TabLaunchType.SIZE;
-            case LaunchTypeAtCreation.UNKNOWN:
-                return null;
-            default:
-                assert false : "Unexpected deserialization of LaunchAtCreationType: "
-                               + flatBufferLaunchType;
-                // shouldn't happen
-                return null;
-        }
-    }
-
-    @VisibleForTesting
-    static int getLaunchType(@Nullable @TabLaunchType Integer tabLaunchType) {
-        if (tabLaunchType == null) {
-            return LaunchTypeAtCreation.UNKNOWN;
-        }
-        switch (tabLaunchType) {
-            case TabLaunchType.FROM_LINK:
-                return LaunchTypeAtCreation.FROM_LINK;
-            case TabLaunchType.FROM_EXTERNAL_APP:
-                return LaunchTypeAtCreation.FROM_EXTERNAL_APP;
-            case TabLaunchType.FROM_CHROME_UI:
-                return LaunchTypeAtCreation.FROM_CHROME_UI;
-            case TabLaunchType.FROM_RESTORE:
-                return LaunchTypeAtCreation.FROM_RESTORE;
-            case TabLaunchType.FROM_LONGPRESS_FOREGROUND:
-                return LaunchTypeAtCreation.FROM_LONGPRESS_FOREGROUND;
-            case LaunchTypeAtCreation.FROM_LONGPRESS_INCOGNITO:
-                return TabLaunchType.FROM_LONGPRESS_INCOGNITO;
-            case TabLaunchType.FROM_LONGPRESS_BACKGROUND:
-                return LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND;
-            case TabLaunchType.FROM_REPARENTING:
-                return LaunchTypeAtCreation.FROM_REPARENTING;
-            case TabLaunchType.FROM_LAUNCHER_SHORTCUT:
-                return LaunchTypeAtCreation.FROM_LAUNCHER_SHORTCUT;
-            case TabLaunchType.FROM_SPECULATIVE_BACKGROUND_CREATION:
-                return LaunchTypeAtCreation.FROM_SPECULATIVE_BACKGROUND_CREATION;
-            case TabLaunchType.FROM_BROWSER_ACTIONS:
-                return LaunchTypeAtCreation.FROM_BROWSER_ACTIONS;
-            case TabLaunchType.FROM_LAUNCH_NEW_INCOGNITO_TAB:
-                return LaunchTypeAtCreation.FROM_LAUNCH_NEW_INCOGNITO_TAB;
-            case TabLaunchType.FROM_STARTUP:
-                return LaunchTypeAtCreation.FROM_STARTUP;
-            case TabLaunchType.FROM_START_SURFACE:
-                return LaunchTypeAtCreation.FROM_START_SURFACE;
-            case TabLaunchType.FROM_TAB_GROUP_UI:
-                return LaunchTypeAtCreation.FROM_TAB_GROUP_UI;
-            case TabLaunchType.FROM_TAB_SWITCHER_UI:
-                return LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI;
-            case TabLaunchType.FROM_RESTORE_TABS_UI:
-                return LaunchTypeAtCreation.FROM_RESTORE_TABS_UI;
-            case TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP:
-                return LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND_IN_GROUP;
-            case TabLaunchType.FROM_APP_WIDGET:
-                return LaunchTypeAtCreation.FROM_APP_WIDGET;
-            case LaunchTypeAtCreation.FROM_RECENT_TABS:
-                return TabLaunchType.FROM_RECENT_TABS;
-            case LaunchTypeAtCreation.FROM_READING_LIST:
-                return TabLaunchType.FROM_READING_LIST;
-            case LaunchTypeAtCreation.FROM_OMNIBOX:
-                return TabLaunchType.FROM_OMNIBOX;
-            case TabLaunchType.SIZE:
-                return LaunchTypeAtCreation.SIZE;
-            default:
-                assert false : "Unexpected serialization of LaunchAtCreationType: " + tabLaunchType;
-                // shouldn't happen
-                return LaunchTypeAtCreation.UNKNOWN;
-        }
-    }
-
-    @VisibleForTesting
-    static @TabUserAgent int getTabUserAgentType(int flatbufferUserAgentType) {
-        switch (flatbufferUserAgentType) {
-            case UserAgentType.DEFAULT:
-                return TabUserAgent.DEFAULT;
-            case UserAgentType.MOBILE:
-                return TabUserAgent.MOBILE;
-            case UserAgentType.DESKTOP:
-                return TabUserAgent.DESKTOP;
-            case UserAgentType.UNSET:
-                return TabUserAgent.UNSET;
-            case UserAgentType.USER_AGENT_SIZE:
-                return TabUserAgent.SIZE;
-            default:
-                assert false : "Unexpected deserialization of UserAgentType: "
-                               + flatbufferUserAgentType;
-                // shouldn't happen
-                return TabUserAgent.DEFAULT;
-        }
-    }
-
-    @VisibleForTesting
-    static int getUserAgentType(@TabUserAgent int userAgent) {
-        switch (userAgent) {
-            case TabUserAgent.DEFAULT:
-                return UserAgentType.DEFAULT;
-            case TabUserAgent.MOBILE:
-                return UserAgentType.MOBILE;
-            case TabUserAgent.DESKTOP:
-                return UserAgentType.DESKTOP;
-            case TabUserAgent.UNSET:
-                return UserAgentType.UNSET;
-            case TabUserAgent.SIZE:
-                return UserAgentType.USER_AGENT_SIZE;
-            default:
-                assert false : "Unexpected serialization of UserAgentType: " + userAgent;
-                // shouldn't happen
-                return UserAgentType.USER_AGENT_UNKNOWN;
-        }
-    }
-
-    private static WebContentsState getWebContentsStateFromTab(Tab tab) {
-        // Native call returns null when buffer allocation needed to serialize the state failed.
-        ByteBuffer buffer = getWebContentsStateAsByteBuffer(tab);
-        if (buffer == null) return null;
-
-        WebContentsState state = new WebContentsState(buffer);
-        state.setVersion(WebContentsState.CONTENTS_STATE_CURRENT_VERSION);
-        return state;
-    }
-
-    /** Returns an ByteBuffer representing the state of the Tab's WebContents. */
-    private static ByteBuffer getWebContentsStateAsByteBuffer(Tab tab) {
-        LoadUrlParams pendingLoadParams = tab.getPendingLoadParams();
-        if (pendingLoadParams == null) {
-            return WebContentsStateBridge.getContentsStateAsByteBuffer(tab.getWebContents());
-        } else {
-            Referrer referrer = pendingLoadParams.getReferrer();
-            return WebContentsStateBridge.createSingleNavigationStateAsByteBuffer(
-                    pendingLoadParams.getUrl(), referrer != null ? referrer.getUrl() : null,
-                    // Policy will be ignored for null referrer url, 0 is just a placeholder.
-                    referrer != null ? referrer.getPolicy() : 0,
-                    pendingLoadParams.getInitiatorOrigin(), tab.isIncognito());
-        }
-    }
-
-    // TODO(crbug.com/1220678) Change PersistedTabData saves to use ByteBuffer instead of byte[]
-    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
-    @Override
-    public Serializer<ByteBuffer> getSerializer() {
-        return new Serializer<ByteBuffer>() {
-            private ByteBuffer mByteBufferSnapshot;
-            private String mOpenerAppIdSnapshot;
-            private int mLaunchTypeSnapshot;
-            private boolean mPreSerialized;
-
-            @Override
-            public ByteBuffer get() {
-                assert mPreSerialized
-                    : "Must call preSerialize before get() on CriticalPersistedTabData Serializer";
-                try (TraceEvent e = TraceEvent.scoped("CriticalPersistedTabData.Serialize")) {
-                    FlatBufferBuilder fbb = new FlatBufferBuilder();
-                    int wcs = CriticalPersistedTabDataFlatBuffer.createWebContentsStateBytesVector(
-                            fbb, ByteBuffer.allocate(0).put(new byte[] {}));
-                    int oaid =
-                            fbb.createString(mOpenerAppIdSnapshot == null ? NULL_OPENER_APP_ID
-                                                                          : mOpenerAppIdSnapshot);
-                    CriticalPersistedTabDataFlatBuffer.startCriticalPersistedTabDataFlatBuffer(fbb);
-                    // Use Placeholder values while CriticalPersistedTabData is being deprecated.
-                    // e.g. INVALID_TAB_ID and INVALID_TIMESTAMP.
-                    // This code path is currently unused as the experiment is turned off,
-                    // so there are no negative consequences to setting timestampMillis to a
-                    // placeholder value.
-                    CriticalPersistedTabDataFlatBuffer.addParentId(fbb, Tab.INVALID_TAB_ID);
-                    CriticalPersistedTabDataFlatBuffer.addRootId(fbb, Tab.INVALID_TAB_ID);
-                    CriticalPersistedTabDataFlatBuffer.addTimestampMillis(fbb, INVALID_TIMESTAMP);
-                    CriticalPersistedTabDataFlatBuffer.addWebContentsStateBytes(fbb, wcs);
-                    CriticalPersistedTabDataFlatBuffer.addContentStateVersion(
-                            fbb, -1 /** unused */);
-                    CriticalPersistedTabDataFlatBuffer.addOpenerAppId(fbb, oaid);
-                    CriticalPersistedTabDataFlatBuffer.addThemeColor(
-                            fbb, TabState.UNSPECIFIED_THEME_COLOR);
-                    CriticalPersistedTabDataFlatBuffer.addLaunchTypeAtCreation(
-                            fbb, mLaunchTypeSnapshot);
-                    CriticalPersistedTabDataFlatBuffer.addUserAgent(fbb, 1 /* unused*/);
-                    CriticalPersistedTabDataFlatBuffer.addLastNavigationCommittedTimestampMillis(
-                            fbb, -1 /** unused */);
-                    int r = CriticalPersistedTabDataFlatBuffer
-                                    .endCriticalPersistedTabDataFlatBuffer(fbb);
-                    fbb.finish(r);
-
-                    return fbb.dataBuffer();
-                }
-            }
-
-            @Override
-            public void preSerialize() {
-                // preSerialize on a {@link Serializer} is only expected to be called once.
-                // There is no need to acquire a snapshot of {@link Tab} attributes more than
-                // once.
-                if (mPreSerialized) return;
-                try (TraceEvent e = TraceEvent.scoped("CriticalPersistedTabData.PreSerialize")) {
-                    mOpenerAppIdSnapshot = mOpenerAppId;
-                }
-                mPreSerialized = true;
-            }
-        };
-    }
-
-    protected static byte[] getContentStateByteArray(ByteBuffer buffer) {
-        byte[] contentsStateBytes = new byte[buffer.limit()];
-        buffer.rewind();
-        buffer.get(contentsStateBytes);
-        return contentsStateBytes;
-    }
-
-    @Override
-    public void save() {
-        if (shouldSave()) {
-            super.save((res) -> { mShouldSave = false; });
-        }
-    }
-
-    @Override
-    public void delete() {
-        super.delete();
-    }
-
-    /**
-     * Encapsulates use cases where saving is disabled - as taken from TabPersistentStore.java to
-     * ensure feature parity.
-     * @return
-     */
-    @VisibleForTesting
-    protected boolean shouldSave() {
-        // This function is currently unused since CriticalPersistedTabData is turned off and
-        // will be removed.
-        if (mShouldSaveForTesting) {
-            return true;
-        }
-        if (!mShouldSave) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * @return identifier for the {@link Tab}
-     */
-    public int getTabId() {
-        return mTab.getId();
-    }
-
-    /**
-     * @return content state version for the {@link Tab}
-     */
-    public int getContentStateVersion() {
-        return mContentStateVersion;
-    }
-
-    /**
-     * @return opener app id
-     */
-    public String getOpenerAppId() {
-        return mOpenerAppId;
-    }
-
-    public void setShouldSaveForTesting(boolean shouldSaveForTesting) {
-        mShouldSaveForTesting = shouldSaveForTesting;
-        ResettersForTesting.register(() -> mShouldSaveForTesting = false);
-    }
-
-    /**
-     * Indicates to {@link CriticalPersistedTabData} that a CriticalPersistedTabData
-     * file should be saved upon a persisted Tab attribute change. Will be reset
-     * when the save is complete. Not every time a Tab attribute changes, should the
-     * file be saved - for example, WebContents changes multiple times during
-     * a navigation and if a new save were initiated on every change, the UI thread
-     * would be filled with too many saves.
-     */
-    public void setShouldSave() {
-        mShouldSave = true;
-    }
-
-    public boolean getShouldSaveForTesting() {
-        return mShouldSave;
-    }
-
-    /**
-     * @return true if the serialized {@link CriticalPersistedTabData} is empty.
-     */
-    public static boolean isEmptySerialization(
-            SerializedCriticalPersistedTabData serializedCriticalPersistedTabData) {
-        return serializedCriticalPersistedTabData == null;
-    }
-
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    protected static PersistedTabDataMapper<SerializedCriticalPersistedTabData>
-    getMapperForTesting() {
-        return sMapper;
-    }
-
-}
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/EncryptedFilePersistedTabDataStorage.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/EncryptedFilePersistedTabDataStorage.java
deleted file mode 100644
index 5de87964..0000000
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/EncryptedFilePersistedTabDataStorage.java
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// 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.tab.state;
-
-import android.os.SystemClock;
-
-import androidx.annotation.MainThread;
-import androidx.core.util.AtomicFile;
-
-import org.chromium.base.Callback;
-import org.chromium.base.Log;
-import org.chromium.base.StreamUtil;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.browser.crypto.CipherFactory;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.WritableByteChannel;
-import java.util.Locale;
-
-import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
-import javax.crypto.CipherOutputStream;
-
-/**
- * Implements {@link PersistedTabDataStorage} but encrypts and decrypts
- * as data is stored and retrieved respectively.
- */
-public class EncryptedFilePersistedTabDataStorage extends FilePersistedTabDataStorage {
-    private static final String TAG = "EFPTDS";
-    // As described in {@link CipherFactory} not all incognito Tabs are restored - only
-    // if the Cipher parameters are saved (which occurs when the Activity is killed in
-    // the background and doesn't occur if the user explicitly closes the app).
-    // In the event that the cipher parameters were saved, KEY_CHECKER will be as expected
-    // when it is read. Otherwise we don't attempt to read the encrypted file (since we
-    // don't have the cipher parameters).
-    // 0 (as a long) is a reasonable value to use here. The likelihood of an encrypted 0L
-    // for one set of cipher parameters being decrypted as 0L for another set of cipher
-    // parameters is very low (1 / (2 ^ 63 - 1)).
-    private static final long KEY_CHECKER = 0;
-
-    @MainThread
-    @Override
-    public void save(int tabId, String dataId, Serializer<ByteBuffer> serializer) {
-        save(tabId, dataId, serializer, NO_OP_CALLBACK);
-    }
-
-    @MainThread
-    @Override
-    public void save(
-            int tabId, String dataId, Serializer<ByteBuffer> data, Callback<Integer> callback) {
-        addStorageRequestAndProcessNext(
-                new EncryptedFileSaveRequest(tabId, dataId, data, callback));
-    }
-
-    @MainThread
-    @Override
-    public void restore(int tabId, String dataId, Callback<ByteBuffer> callback) {
-        addStorageRequestAndProcessNext(new EncryptedFileRestoreRequest(tabId, dataId, callback));
-    }
-
-    @MainThread
-    @Override
-    public ByteBuffer restore(int tabId, String dataId) {
-        return new EncryptedFileRestoreRequest(tabId, dataId, null).executeSyncTask();
-    }
-
-    @MainThread
-    @Override
-    public <U extends PersistedTabDataResult> U restore(
-            int tabId, String dataId, PersistedTabDataMapper<U> mapper) {
-        return new EncryptedFileRestoreAndMapRequest<U>(tabId, dataId, null, mapper)
-                .executeSyncTask();
-    }
-
-    @MainThread
-    @Override
-    public <U extends PersistedTabDataResult> void restore(
-            int tabId, String dataId, Callback<U> callback, PersistedTabDataMapper<U> mapper) {
-        addStorageRequestAndProcessNext(
-                new EncryptedFileRestoreAndMapRequest<U>(tabId, dataId, callback, mapper));
-    }
-
-    /**
-     * Request to save encrypted file based {@link PersistedTabData}
-     */
-    private class EncryptedFileSaveRequest extends FileSaveRequest {
-        /**
-         * @param tabId identifier for the {@link Tab}
-         * @param dataId identifier for the {@link PersistedTabData}
-         * @param serializer {@link Serializer} containing data to be saved
-         */
-        EncryptedFileSaveRequest(int tabId, String dataId, Serializer<ByteBuffer> serializer,
-                Callback<Integer> callback) {
-            super(tabId, dataId, serializer, callback);
-        }
-
-        @Override
-        public Void executeSyncTask() {
-            ByteBuffer data = mSerializer.get();
-            if (data == null) {
-                mSerializer = null;
-                return null;
-            }
-            boolean success = false;
-            Cipher cipher = CipherFactory.getInstance().getCipher(Cipher.ENCRYPT_MODE);
-            if (cipher == null) {
-                Log.e(TAG, "Cipher is null so cannot save encrypted file based PersistedTabData");
-                return null;
-            }
-            FileOutputStream fileOutputStream = null;
-            CipherOutputStream cipherOutputStream = null;
-            DataOutputStream dataOutputStream = null;
-            AtomicFile atomicFile = null;
-            File file = getFile();
-            try {
-                long startTime = SystemClock.elapsedRealtime();
-                atomicFile = new AtomicFile(file);
-                fileOutputStream = atomicFile.startWrite();
-                cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher);
-                dataOutputStream = new DataOutputStream(cipherOutputStream);
-                dataOutputStream.writeLong(KEY_CHECKER);
-                dataOutputStream.writeInt(data.remaining());
-                WritableByteChannel channel = Channels.newChannel(dataOutputStream);
-                channel.write(data);
-                success = true;
-                RecordHistogram.recordTimesHistogram(
-                        String.format(Locale.US, "Tabs.PersistedTabData.Storage.SaveTime.%s",
-                                getUmaTag()),
-                        SystemClock.elapsedRealtime() - startTime);
-            } catch (FileNotFoundException e) {
-                Log.e(TAG,
-                        String.format(Locale.ENGLISH,
-                                "FileNotFoundException while attempting to save file %s "
-                                        + "Details: %s",
-                                file, e.getMessage()));
-                return null;
-            } catch (IOException e) {
-                Log.e(TAG,
-                        String.format(Locale.ENGLISH,
-                                "IOException while attempting to save file %s. "
-                                        + " Details: %s",
-                                file, e.getMessage()));
-            } finally {
-                StreamUtil.closeQuietly(dataOutputStream);
-                StreamUtil.closeQuietly(cipherOutputStream);
-                StreamUtil.closeQuietly(fileOutputStream);
-                if (atomicFile != null) {
-                    if (success) {
-                        atomicFile.finishWrite(fileOutputStream);
-                    } else {
-                        atomicFile.failWrite(fileOutputStream);
-                    }
-                }
-            }
-            RecordHistogram.recordBooleanHistogram(
-                    "Tabs.PersistedTabData.Storage.Save." + getUmaTag(), success);
-            return null;
-        }
-    }
-
-    /**
-     * Request to restore an encrypted {@link PersistedTabData}
-     */
-    private class EncryptedFileRestoreRequest extends FileRestoreRequest {
-        /**
-         * @param tabId identifier for the {@link Tab}
-         * @param dataId identifier for the {@link PersistedTabData}
-         * @param callback - callback to return the retrieved serialized
-         * {@link PersistedTabData} in
-         */
-        EncryptedFileRestoreRequest(int tabId, String dataId, Callback<ByteBuffer> callback) {
-            super(tabId, dataId, callback);
-        }
-
-        @Override
-        public ByteBuffer executeSyncTask() {
-            Cipher cipher = CipherFactory.getInstance().getCipher(Cipher.DECRYPT_MODE);
-            if (cipher == null) {
-                Log.e(TAG,
-                        "Cipher is null so cannot restore encrypted file based PersistedTabData");
-                return null;
-            }
-            boolean success = false;
-            byte[] res = null;
-            FileInputStream fileInputStream = null;
-            CipherInputStream cipherInputStream = null;
-            DataInputStream dataInputStream = null;
-            long startTime = SystemClock.elapsedRealtime();
-            File file = getFile();
-            try {
-                AtomicFile atomicFile = new AtomicFile(file);
-                fileInputStream = atomicFile.openRead();
-                cipherInputStream = new CipherInputStream(fileInputStream, cipher);
-                dataInputStream = new DataInputStream(cipherInputStream);
-                if (dataInputStream.readLong() != KEY_CHECKER) {
-                    // Cipher parameters were not saved if KEY_CHECKER is not as expected.
-                    // No need to attempt reading/decrypting the byte array, since we know
-                    // it will fail.
-                    return null;
-                }
-                res = new byte[dataInputStream.readInt()];
-                dataInputStream.readFully(res);
-                success = true;
-            } catch (FileNotFoundException e) {
-                Log.e(TAG,
-                        String.format(Locale.ENGLISH,
-                                "FileNotFoundException while attempting to restore "
-                                        + " %s. Details: %s",
-                                file, e.getMessage()));
-            } catch (IOException e) {
-                Log.e(TAG,
-                        String.format(Locale.ENGLISH,
-                                "IOException while attempting to restore "
-                                        + "%s. Details: %s",
-                                file, e.getMessage()));
-            } finally {
-                StreamUtil.closeQuietly(dataInputStream);
-                StreamUtil.closeQuietly(cipherInputStream);
-                StreamUtil.closeQuietly(fileInputStream);
-                // TODO(crbug.com/1204889) Create separate histograms for encrypted file based
-                // {@link PersistedTabData}
-                RecordHistogram.recordTimesHistogram(
-                        String.format(Locale.US, "Tabs.PersistedTabData.Storage.LoadTime.%s",
-                                getUmaTag()),
-                        SystemClock.elapsedRealtime() - startTime);
-            }
-            RecordHistogram.recordBooleanHistogram(
-                    "Tabs.PersistedTabData.Storage.Restore." + getUmaTag(), success);
-            return res == null ? null : ByteBuffer.wrap(res);
-        }
-    }
-
-    private class EncryptedFileRestoreAndMapRequest<U extends PersistedTabDataResult>
-            extends FileRestoreAndMapRequest<U> {
-        /**
-         * @param tabId identifier for the {@link Tab}
-         * @param dataId identifier for the {@link PersistedTabData}
-         * @param callback - callback to return the retrieved serialized
-         * {@link PersistedTabData} in
-         */
-        EncryptedFileRestoreAndMapRequest(
-                int tabId, String dataId, Callback<U> callback, PersistedTabDataMapper<U> mapper) {
-            super(tabId, dataId, callback, mapper);
-        }
-
-        @Override
-        public U executeSyncTask() {
-            return mMapper.map(
-                    new EncryptedFileRestoreRequest(mTabId, mDataId, null).executeSyncTask());
-        }
-    }
-}
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java
deleted file mode 100644
index 71545eb..0000000
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java
+++ /dev/null
@@ -1,690 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// 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.tab.state;
-
-import android.content.Context;
-import android.os.StrictMode;
-import android.os.SystemClock;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.MainThread;
-import androidx.annotation.VisibleForTesting;
-import androidx.core.util.AtomicFile;
-
-import org.chromium.base.Callback;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.ResettersForTesting;
-import org.chromium.base.StreamUtil;
-import org.chromium.base.StrictModeContext;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.base.task.AsyncTask;
-import org.chromium.base.task.PostTask;
-import org.chromium.base.task.SequencedTaskRunner;
-import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.browser.flags.BooleanCachedFieldTrialParameter;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileChannel.MapMode;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * {@link PersistedTabDataStorage} which uses a file for the storage
- */
-public class FilePersistedTabDataStorage implements PersistedTabDataStorage {
-    private static final String TAG = "FilePTDS";
-    protected static final Callback<Integer> NO_OP_CALLBACK = new Callback<Integer>() {
-        @Override
-        public void onResult(Integer result) {}
-    };
-    protected static final int DECREMENT_SEMAPHORE_VAL = 1;
-
-    private static final String sBaseDirName = "persisted_tab_data_storage";
-    private static class BaseStorageDirectoryHolder {
-        private static File sDirectory;
-
-        static {
-            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
-            try {
-                sDirectory =
-                ContextUtils.getApplicationContext().getDir(sBaseDirName, Context.MODE_PRIVATE);
-            } finally {
-                StrictMode.setThreadPolicy(oldPolicy);
-            }
-        }
-    }
-    private static final String DELAY_SAVES_UNTIL_DEFERRED_STARTUP =
-            "delay_saves_until_deferred_startup";
-    public static final BooleanCachedFieldTrialParameter DELAY_SAVES_UNTIL_DEFERRED_STARTUP_PARAM =
-            new BooleanCachedFieldTrialParameter(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA,
-                    DELAY_SAVES_UNTIL_DEFERRED_STARTUP, false);
-
-    private SequencedTaskRunner mSequencedTaskRunner;
-    private boolean mFirstOperationRecorded;
-
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    protected LinkedList<StorageRequest> mQueue = new LinkedList<>();
-    private LinkedList<FileSaveRequest> mDelayedSaveRequests = new LinkedList<>();
-    private FileSaveRequest mExecutingSaveRequest;
-
-    protected FilePersistedTabDataStorage() {
-        mSequencedTaskRunner =
-                PostTask.createSequencedTaskRunner(TaskTraits.USER_BLOCKING_MAY_BLOCK);
-    }
-
-    @MainThread
-    @Override
-    public void save(int tabId, String dataId, Serializer<ByteBuffer> serializer) {
-        save(tabId, dataId, serializer, NO_OP_CALLBACK);
-    }
-
-    // Callback used for test synchronization between save, restore and delete operations
-    @MainThread
-    @Override
-    public void save(int tabId, String dataId, Serializer<ByteBuffer> serializer,
-            Callback<Integer> callback) {
-        // TODO(crbug.com/1059637) we should introduce a retry mechanisms
-        addSaveRequest(new FileSaveRequest(tabId, dataId, serializer, callback));
-        processNextItemOnQueue();
-    }
-
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    protected void addSaveRequest(FileSaveRequest fileSaveRequest) {
-        // FileSaveRequest for the same tabid/data id will get overwritten
-        // by new FileSaveRequest so remove if it exists in the queue.
-        mQueue.remove(fileSaveRequest);
-        mQueue.add(fileSaveRequest);
-    }
-
-    @MainThread
-    @Override
-    public void restore(int tabId, String dataId, Callback<ByteBuffer> callback) {
-        addStorageRequestAndProcessNext(new FileRestoreRequest(tabId, dataId, callback));
-    }
-
-    @MainThread
-    @Override
-    public ByteBuffer restore(int tabId, String dataId) {
-        return new FileRestoreRequest(tabId, dataId, null).executeSyncTask();
-    }
-
-    @MainThread
-    @Override
-    public <U extends PersistedTabDataResult> U restore(
-            int tabId, String dataId, PersistedTabDataMapper<U> mapper) {
-        return new FileRestoreAndMapRequest<U>(tabId, dataId, null, mapper).executeSyncTask();
-    }
-
-    @MainThread
-    @Override
-    public <U extends PersistedTabDataResult> void restore(
-            int tabId, String dataId, Callback<U> callback, PersistedTabDataMapper<U> mapper) {
-        addStorageRequestAndProcessNext(
-                new FileRestoreAndMapRequest<U>(tabId, dataId, callback, mapper));
-    }
-
-    @MainThread
-    @Override
-    public void delete(int tabId, String dataId) {
-        delete(tabId, dataId, NO_OP_CALLBACK);
-    }
-
-    public List<StorageRequest> getStorageRequestQueueForTesting() {
-        return mQueue;
-    }
-
-    // Callback used for test synchronization between save, restore and delete operations
-    @MainThread
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    protected void delete(int tabId, String dataId, Callback<Integer> callback) {
-        addStorageRequestAndProcessNext(new FileDeleteRequest(tabId, dataId, callback));
-    }
-
-    protected void addStorageRequestAndProcessNext(StorageRequest storageRequest) {
-        mQueue.add(storageRequest);
-        processNextItemOnQueue();
-    }
-
-    protected void setExecutingSaveRequestForTesting(FileSaveRequest fileSaveRequest) {
-        var oldValue = mExecutingSaveRequest;
-        mExecutingSaveRequest = fileSaveRequest;
-        ResettersForTesting.register(() -> mExecutingSaveRequest = oldValue);
-    }
-
-    /**
-     * @return {@link File} serialized {@link CriticalPersistedTabData} is stored in
-     * @param tabId tab identifier
-     * @param dataId type of data stored for the {@link Tab}
-     */
-    protected static File getFile(int tabId, String dataId) {
-        return new File(getOrCreateBaseStorageDirectory(),
-                String.format(Locale.ENGLISH, "%d%s", tabId, dataId));
-    }
-
-    public static File getOrCreateBaseStorageDirectory() {
-        return BaseStorageDirectoryHolder.sDirectory;
-    }
-
-    /**
-     * Request for saving, restoring and deleting {@link PersistedTabData}
-     */
-    protected abstract class StorageRequest<T> {
-        protected final int mTabId;
-        protected final String mDataId;
-
-        /**
-         * @param tabId identifier for the {@link Tab}
-         * @param dataId identifier for the {@link PersistedTabData}
-         */
-        StorageRequest(int tabId, String dataId) {
-            mTabId = tabId;
-            mDataId = dataId;
-        }
-
-        /**
-         * @return unique identifier for the StorageRequest
-         */
-        String getRequestId() {
-            return String.format(Locale.ENGLISH, "%d_%s", mTabId, mDataId);
-        }
-
-        /**
-         * AsyncTask to execute the StorageRequest
-         */
-        abstract AsyncTask getAsyncTask();
-
-        /**
-         * Execute the task synchronously
-         */
-        abstract T executeSyncTask();
-
-        @Override
-        public boolean equals(Object other) {
-            if (this == other) return true;
-            if (other == null) return false;
-            if (!(other instanceof StorageRequest)) return false;
-            StorageRequest otherStorageRequest = (StorageRequest) other;
-            return mTabId == otherStorageRequest.mTabId
-                    && mDataId.equals(otherStorageRequest.mDataId);
-        }
-
-        @Override
-        public int hashCode() {
-            int result = 17;
-            result = 31 * result + mTabId;
-            result = 31 * result + mDataId.hashCode();
-            return result;
-        }
-
-        /**
-         * @return type of storage request (save, restore or delete)
-         */
-        abstract @StorageRequestType int getStorageRequestType();
-
-        protected File getFile() {
-            return FilePersistedTabDataStorage.getFile(mTabId, mDataId);
-        }
-    }
-
-    /**
-     * Request to save {@link PersistedTabData}
-     */
-    protected class FileSaveRequest extends StorageRequest<Void> {
-        protected Serializer<ByteBuffer> mSerializer;
-        protected Callback<Integer> mCallback;
-        private boolean mFinished;
-
-        /**
-         * @param tabId identifier for the {@link Tab}
-         * @param dataId identifier for the {@link PersistedTabData}
-         * @param serializer {@link Serializer} containing data to be saved
-         */
-        FileSaveRequest(int tabId, String dataId, Serializer<ByteBuffer> serializer,
-                Callback<Integer> callback) {
-            super(tabId, dataId);
-            mSerializer = serializer;
-            mCallback = callback;
-        }
-
-        @Override
-        public Void executeSyncTask() {
-            ByteBuffer data = null;
-            try {
-                data = mSerializer.get();
-            } catch (OutOfMemoryError e) {
-                // Log and exit FileSaveRequest early on OutOfMemoryError.
-                // Not saving a Tab is better than crashing the app.
-                Log.e(TAG, "OutOfMemoryError. Details: " + e.getMessage());
-            }
-            if (data == null) {
-                mSerializer = null;
-                return null;
-            }
-            FileOutputStream outputStream = null;
-            AtomicFile atomicFile = null;
-            boolean success = false;
-            File file = getFile();
-            try {
-                long startTime = SystemClock.elapsedRealtime();
-                atomicFile = new AtomicFile(file);
-                outputStream = atomicFile.startWrite();
-                FileChannel fileChannel = outputStream.getChannel();
-                fileChannel.write(data);
-                success = true;
-                RecordHistogram.recordTimesHistogram(
-                        String.format(Locale.US, "Tabs.PersistedTabData.Storage.SaveTime.%s",
-                                getUmaTag()),
-                        SystemClock.elapsedRealtime() - startTime);
-            } catch (FileNotFoundException e) {
-                Log.e(TAG,
-                        String.format(Locale.ENGLISH,
-                                "FileNotFoundException while attempting to save file %s "
-                                        + "Details: %s",
-                                file, e.getMessage()));
-            } catch (IOException e) {
-                Log.e(TAG,
-                        String.format(Locale.ENGLISH,
-                                "IOException while attempting to save for file %s. "
-                                        + " Details: %s",
-                                file, e.getMessage()));
-            } finally {
-                StreamUtil.closeQuietly(outputStream);
-                if (atomicFile != null) {
-                    if (success) {
-                        atomicFile.finishWrite(outputStream);
-                    } else {
-                        atomicFile.failWrite(outputStream);
-                    }
-                }
-            }
-            RecordHistogram.recordBooleanHistogram(
-                    "Tabs.PersistedTabData.Storage.Save." + getUmaTag(), success);
-            mFinished = true;
-            return null;
-        }
-
-        @Override
-        public AsyncTask getAsyncTask() {
-            return new AsyncTask<Void>() {
-                @Override
-                protected void onPreExecute() {
-                    mSerializer.preSerialize();
-                }
-
-                @Override
-                protected Void doInBackground() {
-                    return executeSyncTask();
-                }
-
-                @Override
-                protected void onPostExecute(Void result) {
-                    mExecutingSaveRequest = null;
-                    PostTask.postTask(TaskTraits.UI_DEFAULT,
-                            () -> { mCallback.onResult(DECREMENT_SEMAPHORE_VAL); });
-                    processNextItemOnQueue();
-                }
-            };
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof FileSaveRequest)) return false;
-            return super.equals(other);
-        }
-
-        @Override
-        @StorageRequestType
-        int getStorageRequestType() {
-            return StorageRequestType.SAVE;
-        }
-
-        public void preSerialize() {
-            mSerializer.preSerialize();
-        }
-
-        public boolean isFinished() {
-            return mFinished;
-        }
-    }
-
-    /**
-     * Request to delete a saved {@link PersistedTabData}
-     */
-    private class FileDeleteRequest extends StorageRequest<Void> {
-        private byte[] mData;
-        private Callback<Integer> mCallback;
-
-        /**
-         * @param tabId identifier for the {@link Tab}
-         * @param dataId identifier for the {@link PersistedTabData}
-         */
-        FileDeleteRequest(int tabId, String dataId, Callback<Integer> callback) {
-            super(tabId, dataId);
-            mCallback = callback;
-        }
-
-        @Override
-        public Void executeSyncTask() {
-            File file = getFile();
-            boolean exists = file.exists();
-            RecordHistogram.recordBooleanHistogram(
-                    "Tabs.PersistedTabData.Storage.Exists." + getUmaTag(), exists);
-            if (!exists) {
-                return null;
-            }
-            boolean success = file.delete();
-            RecordHistogram.recordBooleanHistogram(
-                    "Tabs.PersistedTabData.Storage.Delete." + getUmaTag(), success);
-            if (!success) {
-                Log.e(TAG, String.format(Locale.ENGLISH, "Error deleting file %s", file));
-            }
-            return null;
-        }
-
-        @Override
-        public AsyncTask getAsyncTask() {
-            return new AsyncTask<Void>() {
-                @Override
-                protected Void doInBackground() {
-                    return executeSyncTask();
-                }
-
-                @Override
-                protected void onPostExecute(Void result) {
-                    PostTask.postTask(TaskTraits.UI_DEFAULT,
-                            () -> { mCallback.onResult(DECREMENT_SEMAPHORE_VAL); });
-                    processNextItemOnQueue();
-                }
-            };
-        }
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof FileDeleteRequest)) return false;
-            return super.equals(other);
-        }
-
-        @Override
-        @StorageRequestType
-        int getStorageRequestType() {
-            return StorageRequestType.DELETE;
-        }
-    }
-
-    /**
-     * Request to restore saved serialized {@link PersistedTabData}
-     */
-    protected class FileRestoreRequest extends StorageRequest<ByteBuffer> {
-        protected Callback<ByteBuffer> mCallback;
-
-        /**
-         * @param tabId identifier for the {@link Tab}
-         * @param dataId identifier for the {@link PersistedTabData}
-         * @param callback - callback to return the retrieved serialized
-         * {@link PersistedTabData} in
-         */
-        FileRestoreRequest(int tabId, String dataId, Callback<ByteBuffer> callback) {
-            super(tabId, dataId);
-            mCallback = callback;
-        }
-
-        @Override
-        public ByteBuffer executeSyncTask() {
-            boolean success = false;
-            ByteBuffer res = null;
-            FileInputStream fileInputStream = null;
-            File file = getFile();
-            try {
-                long startTime = SystemClock.elapsedRealtime();
-                AtomicFile atomicFile = new AtomicFile(file);
-                fileInputStream = atomicFile.openRead();
-                FileChannel channel = fileInputStream.getChannel();
-                res = channel.map(MapMode.READ_ONLY, channel.position(), channel.size());
-                success = true;
-                RecordHistogram.recordTimesHistogram(
-                        String.format(Locale.US, "Tabs.PersistedTabData.Storage.LoadTime.%s",
-                                getUmaTag()),
-                        SystemClock.elapsedRealtime() - startTime);
-            } catch (FileNotFoundException e) {
-                Log.e(TAG,
-                        String.format(Locale.ENGLISH,
-                                "FileNotFoundException while attempting to restore "
-                                        + " %s. Details: %s",
-                                file, e.getMessage()));
-            } catch (IOException e) {
-                Log.e(TAG,
-                        String.format(Locale.ENGLISH,
-                                "IOException while attempting to restore "
-                                        + "%s. Details: %s",
-                                file, e.getMessage()));
-            } finally {
-                StreamUtil.closeQuietly(fileInputStream);
-            }
-            RecordHistogram.recordBooleanHistogram(
-                    "Tabs.PersistedTabData.Storage.Restore." + getUmaTag(), success);
-            return success ? res : null;
-        }
-
-        @Override
-        public AsyncTask getAsyncTask() {
-            return new AsyncTask<ByteBuffer>() {
-                @Override
-                protected ByteBuffer doInBackground() {
-                    return executeSyncTask();
-                }
-
-                @Override
-                protected void onPostExecute(ByteBuffer res) {
-                    PostTask.runOrPostTask(
-                            TaskTraits.UI_DEFAULT, () -> { mCallback.onResult(res); });
-                    processNextItemOnQueue();
-                }
-            };
-        }
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof FileRestoreRequest)) return false;
-            return super.equals(other);
-        }
-
-        @Override
-        @StorageRequestType
-        int getStorageRequestType() {
-            return StorageRequestType.RESTORE;
-        }
-    }
-
-    protected class FileRestoreAndMapRequest<U extends PersistedTabDataResult>
-            extends StorageRequest<U> {
-        protected Callback<U> mCallback;
-        protected PersistedTabDataMapper<U> mMapper;
-
-        /**
-         * @param tabId identifier for the {@link Tab}
-         * @param dataId identifier for the {@link PersistedTabData}
-         * @param callback - callback to return the retrieved serialized
-         * {@link PersistedTabData} in
-         */
-        FileRestoreAndMapRequest(
-                int tabId, String dataId, Callback<U> callback, PersistedTabDataMapper<U> mapper) {
-            super(tabId, dataId);
-            mCallback = callback;
-            mMapper = mapper;
-        }
-
-        @Override
-        public U executeSyncTask() {
-            long startTime = SystemClock.elapsedRealtime();
-            ByteBuffer restoredData =
-                    new FileRestoreRequest(mTabId, mDataId, null).executeSyncTask();
-            long mapStartTime = SystemClock.elapsedRealtime();
-            U mappedResult = mMapper.map(restoredData);
-            long finishTime = SystemClock.elapsedRealtime();
-            // Only loading and mapping a non-empty ByteBuffer should be recorded in
-            // the metrics. Adding in a empty ByteBuffer will skew the metrics.
-            if (restoredData != null && restoredData.limit() > 0) {
-                RecordHistogram.recordTimesHistogram(
-                        "Tabs.PersistedTabData.Storage.LoadAndMapTime.File",
-                        finishTime - startTime);
-                RecordHistogram.recordTimesHistogram(
-                        "Tabs.PersistedTabData.Storage.MapTime.File", finishTime - mapStartTime);
-            }
-            return mappedResult;
-        }
-
-        @Override
-        public AsyncTask getAsyncTask() {
-            return new AsyncTask<U>() {
-                @Override
-                protected U doInBackground() {
-                    return executeSyncTask();
-                }
-
-                @Override
-                protected void onPostExecute(U res) {
-                    PostTask.postTask(TaskTraits.UI_DEFAULT, () -> { mCallback.onResult(res); });
-                    processNextItemOnQueue();
-                }
-            };
-        }
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof FileRestoreAndMapRequest)) return false;
-            return super.equals(other);
-        }
-
-        @Override
-        @StorageRequestType
-        int getStorageRequestType() {
-            return StorageRequestType.RESTORE;
-        }
-    }
-
-    // These values are persisted to logs. Entries should not be renumbered and
-    // numeric values should never be reused.
-    @IntDef({StorageRequestType.SAVE, StorageRequestType.RESTORE, StorageRequestType.DELETE})
-    @Retention(RetentionPolicy.SOURCE)
-    @interface StorageRequestType {
-        int SAVE = 0;
-        int RESTORE = 1;
-        int DELETE = 2;
-        int NUM_ENTRIES = 3;
-    }
-
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    protected void processNextItemOnQueue() {
-        if (mQueue.isEmpty()) return;
-        StorageRequest storageRequest = mQueue.poll();
-        // First operation should be a restore (to restore the active tab) - any other
-        // operations coming in before the restore will block restoration of the active
-        // tab and hurt startup latency.
-        if (!mFirstOperationRecorded) {
-            RecordHistogram.recordEnumeratedHistogram("Tabs.PersistedTabData.Storage.Save."
-                            + getUmaTag() + ".FirstStorageRequestType",
-                    storageRequest.getStorageRequestType(), StorageRequestType.NUM_ENTRIES);
-            mFirstOperationRecorded = true;
-        }
-        if (storageRequest instanceof FileSaveRequest) {
-            mExecutingSaveRequest = (FileSaveRequest) storageRequest;
-        }
-        storageRequest.getAsyncTask().executeOnTaskRunner(mSequencedTaskRunner);
-    }
-
-    @Override
-    public String getUmaTag() {
-        return "File";
-    }
-
-    @Override
-    public void performMaintenance(List<Integer> tabIds, String dataId) {
-        assert false : "Maintenance is not available in FilePersistedTabDataStorage";
-    }
-
-    /**
-     * Determines if a {@link Tab} is incognito or not based on the existence of the
-     * corresponding {@link CriticalPersistedTabData} file. This involves a disk access
-     * and will be slow. This method can be called from the UI thread.
-     * @param tabId identifier for the {@link Tab}
-     * @return true/false if the {@link Tab} is incognito based on the existence of the
-     *         CriticalPersistedTabData file and null if it is not known if the
-     *         {@link Tab} is incognito or not.
-     */
-    public static Boolean isIncognito(int tabId) {
-        try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
-            String regularId =
-                    PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, false)
-                            .getId();
-            File regularFile = FilePersistedTabDataStorage.getFile(tabId, regularId);
-            if (regularFile.exists()) {
-                return false;
-            }
-            String incognitoId =
-                    PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, true).getId();
-            File incognitoFile = FilePersistedTabDataStorage.getFile(tabId, incognitoId);
-            if (incognitoFile.exists()) {
-                return true;
-            }
-            return null;
-        }
-    }
-
-    /**
-     * @param tabId {@link Tab} identifier
-     * @param isIncognito if the {@link Tab} is incognito
-     * @return true if a file exists for this {@link Tab}
-     */
-    @VisibleForTesting
-    public static boolean exists(int tabId, boolean isIncognito) {
-        try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
-            String dataId =
-                    PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, isIncognito)
-                            .getId();
-            File file = FilePersistedTabDataStorage.getFile(tabId, dataId);
-            return file != null && file.exists();
-        }
-    }
-
-    /**
-     * Used for cleaning up files between batched tests.
-     */
-    protected static void deleteFilesForTesting() {
-        for (File file : getOrCreateBaseStorageDirectory().listFiles()) {
-            file.delete();
-        }
-    }
-
-    /**
-     * System is shutting down - finish any pending saves.
-     */
-    public void onShutdown() {
-        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
-            // Cancel existing request on background thread and finish
-            // all saves.
-            if (mExecutingSaveRequest != null) {
-                mExecutingSaveRequest.getAsyncTask().cancel(false);
-                if (!mExecutingSaveRequest.isFinished()) {
-                    mQueue.addFirst(mExecutingSaveRequest);
-                }
-            }
-            for (StorageRequest storageRequest : mQueue) {
-                if (storageRequest instanceof FileSaveRequest) {
-                    ((FileSaveRequest) storageRequest).preSerialize();
-                    storageRequest.executeSyncTask();
-                }
-            }
-            mQueue.clear();
-        }
-    }
-}
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java
index e9fa452..c2a864c 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java
@@ -406,7 +406,6 @@
      * Delete all {@link PersistedTabData} when a {@link Tab} is closed.
      */
     public static void onTabClose(Tab tab) {
-        tab.setIsTabSaveEnabled(false);
         // TODO(crbug.com/1223965) ensure we cleanup ShoppingPersistedTabData on startup
         ShoppingPersistedTabData shoppingPersistedTabData =
                 tab.getUserDataHost().getUserData(ShoppingPersistedTabData.class);
@@ -455,16 +454,6 @@
         PersistedTabDataJni.get().onDeferredStartup();
     }
 
-    /**
-     * Signal to {@link PersistedTabData} that the system is shutting down and to finish
-     * any pending saves.
-     * TODO(b/298057345) deprecate PersistedTabData.onShutdown()
-     */
-    public static void onShutdown() {
-        PersistedTabDataConfiguration.getFilePersistedTabDataStorage().onShutdown();
-        PersistedTabDataConfiguration.getEncryptedFilePersistedTabDataStorage().onShutdown();
-    }
-
     @VisibleForTesting
     public void existsInStorage(Callback<Boolean> callback) {
         mPersistedTabDataStorage.restore(mTab.getId(), mPersistedTabDataId,
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataConfiguration.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataConfiguration.java
index f9ce8e9b..d89bcf9 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataConfiguration.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataConfiguration.java
@@ -16,8 +16,6 @@
 public enum PersistedTabDataConfiguration {
     // TODO(crbug.com/1059650) investigate should this go in the app code?
     // Also investigate if the storage instance should be shared.
-    CRITICAL_PERSISTED_TAB_DATA("CPTDFB"),
-    ENCRYPTED_CRITICAL_PERSISTED_TAB_DATA("ECPTDFB"),
     MOCK_PERSISTED_TAB_DATA("MPTD"),
     ENCRYPTED_MOCK_PERSISTED_TAB_DATA("EMPTD"),
     SHOPPING_PERSISTED_TAB_DATA("SPTD"),
@@ -33,8 +31,6 @@
     /**
      * Ensure lazy initialization of singleton storage
      */
-    private static FilePersistedTabDataStorage sFilePersistedTabDataStorage;
-    private static EncryptedFilePersistedTabDataStorage sEncrpytedFilePersistedTabDataStorage;
     private static MockPersistedTabDataStorage sMockPersistedTabDataStorage;
     private static EmptyByteBufferPersistedTabDataStorage sEmptyByteBufferPersistedTabDataStorage;
     private static boolean sUseEmptyByteBufferTestConfig;
@@ -47,20 +43,6 @@
         return sEmptyByteBufferPersistedTabDataStorage;
     }
 
-    static FilePersistedTabDataStorage getFilePersistedTabDataStorage() {
-        if (sFilePersistedTabDataStorage == null) {
-            sFilePersistedTabDataStorage = new FilePersistedTabDataStorage();
-        }
-        return sFilePersistedTabDataStorage;
-    }
-
-    static EncryptedFilePersistedTabDataStorage getEncryptedFilePersistedTabDataStorage() {
-        if (sEncrpytedFilePersistedTabDataStorage == null) {
-            sEncrpytedFilePersistedTabDataStorage = new EncryptedFilePersistedTabDataStorage();
-        }
-        return sEncrpytedFilePersistedTabDataStorage;
-    }
-
     private static MockPersistedTabDataStorage getMockPersistedTabDataStorage() {
         if (sMockPersistedTabDataStorage == null) {
             sMockPersistedTabDataStorage = new MockPersistedTabDataStorage();
@@ -72,24 +54,15 @@
 
     static {
         // TODO(crbug.com/1060187) remove static initializer and initialization lazy
-        sLookup.put(CriticalPersistedTabData.class, CRITICAL_PERSISTED_TAB_DATA);
-        sEncryptedLookup.put(CriticalPersistedTabData.class, ENCRYPTED_CRITICAL_PERSISTED_TAB_DATA);
         sLookup.put(MockPersistedTabData.class, MOCK_PERSISTED_TAB_DATA);
         sEncryptedLookup.put(MockPersistedTabData.class, ENCRYPTED_MOCK_PERSISTED_TAB_DATA);
         sLookup.put(ShoppingPersistedTabData.class, SHOPPING_PERSISTED_TAB_DATA);
         sEncryptedLookup.put(ShoppingPersistedTabData.class, SHOPPING_PERSISTED_TAB_DATA);
-
-        CRITICAL_PERSISTED_TAB_DATA.mStorageFactory = () -> {
-            return getFilePersistedTabDataStorage();
-        };
-        ENCRYPTED_CRITICAL_PERSISTED_TAB_DATA.mStorageFactory = () -> {
-            return getEncryptedFilePersistedTabDataStorage();
-        };
         MOCK_PERSISTED_TAB_DATA.mStorageFactory = () -> {
-            return getFilePersistedTabDataStorage();
+            return getMockPersistedTabDataStorage();
         };
         ENCRYPTED_MOCK_PERSISTED_TAB_DATA.mStorageFactory = () -> {
-            return getEncryptedFilePersistedTabDataStorage();
+            return getMockPersistedTabDataStorage();
         };
         SHOPPING_PERSISTED_TAB_DATA.mStorageFactory = new LevelDBPersistedTabDataStorageFactory();
 
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/SerializedCriticalPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/SerializedCriticalPersistedTabData.java
deleted file mode 100644
index 2b2f0c5..0000000
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/SerializedCriticalPersistedTabData.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// 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.tab.state;
-
-import androidx.annotation.Nullable;
-
-import org.chromium.chrome.browser.tab.TabLaunchType;
-import org.chromium.chrome.browser.tab.TabUserAgent;
-import org.chromium.chrome.browser.tab.WebContentsState;
-
-/**
- * Contains serialized {@link CriticalPersistedTabData}
- * TODO(crbug.com/1294620) rename to CriticalPersistedTabDataResult
- */
-public class SerializedCriticalPersistedTabData implements PersistedTabDataResult {
-    private final int mParentId;
-    private final int mRootId;
-    private final long mTimestampMillis;
-    private final WebContentsState mWebContentsState;
-    private final String mOpenerAppId;
-    private final int mWebContentsStateVersion;
-    private final int mThemeColor;
-    private final @Nullable @TabLaunchType Integer mLaunchTypeAtCreation;
-    private final @TabUserAgent int mUserAgent;
-    private final long mLastNavigationCommittedTimestampMillis;
-
-    /**
-     * @param parentId parent identifier for a {@link Tab}
-     * @param rootId root identifier for a {@link Tab}
-     * @param timestampMillis time {@link Tab} was last accessed
-     * @param webContentsState {@link WebContentsState} for the {@link Tab}
-     * @param url url the {@link Tab} is currently visiting
-     * @param title title of the {@link Tab}
-     * @param openerAppId opener app id for the {@link Tab}
-     * @param webContentsStateVersion version of the {@link WebContentsState}
-     * @param themeColor theme color of the {@link Tab}
-     * @param launchTypeAtCreation the way the {@link Tab} was launched
-     * @param userAgent user agent for the {@link Tab}
-     * @param lastNavigationCommittedTimestampMillis time of the last committed navigation in the
-     *         {@link Tab}
-     */
-    protected SerializedCriticalPersistedTabData(int parentId, int rootId, long timestampMillis,
-            WebContentsState webContentsState, String openerAppId, int webContentsStateVersion,
-            int themeColor, @Nullable @TabLaunchType Integer launchTypeAtCreation,
-            @TabUserAgent int userAgent, long lastNavigationCommittedTimestampMillis) {
-        mParentId = parentId;
-        mRootId = rootId;
-        mTimestampMillis = timestampMillis;
-        mWebContentsState = webContentsState;
-        mOpenerAppId = openerAppId;
-        mWebContentsStateVersion = webContentsStateVersion;
-        mThemeColor = themeColor;
-        mLaunchTypeAtCreation = launchTypeAtCreation;
-        mUserAgent = userAgent;
-        mLastNavigationCommittedTimestampMillis = lastNavigationCommittedTimestampMillis;
-    }
-
-    protected int getParentId() {
-        return mParentId;
-    }
-
-    protected int getRootId() {
-        return mRootId;
-    }
-
-    protected long getTimestampMillis() {
-        return mTimestampMillis;
-    }
-
-    protected WebContentsState getWebContentsState() {
-        return mWebContentsState;
-    }
-
-    protected String getUrl() {
-        return mWebContentsState.getVirtualUrlFromState();
-    }
-
-    protected String getTitle() {
-        return mWebContentsState.getDisplayTitleFromState();
-    }
-
-    protected String getOpenerAppId() {
-        return mOpenerAppId;
-    }
-
-    protected int getWebContentsStateVersion() {
-        return mWebContentsStateVersion;
-    }
-
-    protected int getThemeColor() {
-        return mThemeColor;
-    }
-
-    protected @Nullable @TabLaunchType Integer getLaunchType() {
-        return mLaunchTypeAtCreation;
-    }
-
-    protected @TabUserAgent int getUserAgent() {
-        return mUserAgent;
-    }
-
-    protected long getLastNavigationCommittedTimestampMillis() {
-        return mLastNavigationCommittedTimestampMillis;
-    }
-}
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
deleted file mode 100644
index cdfc0e9..0000000
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-namespace org.chromium.chrome.browser.tab.flatbuffer;
-
-enum LaunchTypeAtCreation:int {
-    // SIZE is typically not used for anything other than bound
-    // checking but is included for completeness. It is added
-    // at the start rather than the end to enable other TabLaunchTypes
-    // to be added. It is not a problem that SIZE is not the same
-    // enum value as TabLaunchType.SIZE because the FlatBuffer persisted
-    // enum is mapped directly onto the TabLaunchType value in
-    // CriticalPersistedTabData. An alternative is to set SIZE to a large
-    // value but this is not possible as the enum values need to be sequential.
-    SIZE = -2,
-    // UNKNOWN indicates the TabLaunchType is null/not known.
-    UNKNOWN = -1,
-    FROM_LINK = 0,
-    FROM_EXTERNAL_APP = 1,
-    FROM_CHROME_UI = 2,
-    FROM_RESTORE = 3,
-    FROM_LONGPRESS_FOREGROUND = 4,
-    FROM_LONGPRESS_BACKGROUND = 5,
-    FROM_REPARENTING = 6,
-    FROM_LAUNCHER_SHORTCUT = 7,
-    FROM_SPECULATIVE_BACKGROUND_CREATION = 8,
-    FROM_BROWSER_ACTIONS = 9,
-    FROM_LAUNCH_NEW_INCOGNITO_TAB = 10,
-    FROM_STARTUP = 11,
-    FROM_START_SURFACE = 12,
-    FROM_TAB_GROUP_UI = 13,
-    FROM_LONGPRESS_BACKGROUND_IN_GROUP = 14,
-    FROM_APP_WIDGET = 15,
-    // Deprecated. Use `FROM_LONGPRESS_FOREGROUND` in new code.
-    FROM_LONGPRESS_INCOGNITO = 16,
-    FROM_RECENT_TABS = 17,
-    FROM_READING_LIST = 18,
-    FROM_TAB_SWITCHER_UI = 19,
-    FROM_RESTORE_TABS_UI = 20,
-    FROM_OMNIBOX = 21,
-    // Add new values here and don't change existing values
-    // as they are persisted across restarts. Changing existing
-    // values will lead to backwards compatibility issues crbug.com/1286984.
-}
-
-enum UserAgentType:int {
-    DEFAULT = 0,
-    MOBILE = 1,
-    DESKTOP = 2,
-    UNSET = 3,
-    USER_AGENT_SIZE = 4,
-    USER_AGENT_UNKNOWN = 5,
-}
-
-// Before making any modification here, make a copy of this file and save it to |critical_persisted_tab_tab_test_vi| where vi is the newer version and write a test to verify backwards compatability of that table with the new change.
-table CriticalPersistedTabDataFlatBuffer {
-    // Parent Tab identifier.
-    parent_id:int;
-
-    // Root Tab identifier.
-    root_id:int;
-
-    // Timestamp when Tab was last accessed.
-    timestamp_millis:long;
-
-    // WebContentsState.
-    web_contents_state_bytes:[byte];
-
-    // Content State version.
-    content_state_version:int;
-
-    // Identifier for app which opened the Tab.
-    opener_app_id:string;
-
-    // Theme color.
-    theme_color:int;
-
-    // Launch type at creation.
-    launch_type_at_creation:LaunchTypeAtCreation;
-
-    // User Agent.
-    user_agent:UserAgentType=DEFAULT;
-
-    // Timestamp of the last committed navigation done in the Tab.
-    last_navigation_committed_timestamp_millis:long;
-}
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java
index 3b4d1a2..23f1e7e 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java
@@ -6,7 +6,6 @@
 
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabSelectionType;
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.content_public.browser.WebContents;
 
 import java.util.ArrayList;
@@ -213,8 +212,9 @@
             if (currentTab.getId() == tabId || currentTab.isClosing()) continue;
 
             final long currentTime = currentTab.getTimestampMillis();
-            if (currentTime != CriticalPersistedTabData.INVALID_TIMESTAMP
-                    && mostRecentTabTime < currentTime) {
+            // TODO(b/301642179) Consider using Optional on Tab interface for getTimestampMillis()
+            // to signal that the timestamp is unknown.
+            if (currentTime != Tab.INVALID_TIMESTAMP && mostRecentTabTime < currentTime) {
                 mostRecentTabTime = currentTime;
                 mostRecentTab = currentTab;
             }
diff --git a/chrome/browser/task_manager/providers/web_contents/web_app_tag.cc b/chrome/browser/task_manager/providers/web_contents/web_app_tag.cc
index 0387e89..a23fd49 100644
--- a/chrome/browser/task_manager/providers/web_contents/web_app_tag.cc
+++ b/chrome/browser/task_manager/providers/web_contents/web_app_tag.cc
@@ -9,10 +9,10 @@
 #include "chrome/browser/task_manager/providers/web_contents/isolated_web_app_task.h"
 #include "chrome/browser/task_manager/providers/web_contents/tab_contents_task.h"
 #include "chrome/browser/task_manager/providers/web_contents/web_app_task.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_tab_helper.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 
 namespace task_manager {
@@ -27,7 +27,7 @@
 }
 
 WebAppTag::WebAppTag(content::WebContents* web_contents,
-                     const web_app::AppId& app_id,
+                     const webapps::AppId& app_id,
                      const bool is_isolated_web_app)
     : WebContentsTag(web_contents),
       app_id_(app_id),
diff --git a/chrome/browser/task_manager/providers/web_contents/web_app_tag.h b/chrome/browser/task_manager/providers/web_contents/web_app_tag.h
index 6ed5a70..338e1a2 100644
--- a/chrome/browser/task_manager/providers/web_contents/web_app_tag.h
+++ b/chrome/browser/task_manager/providers/web_contents/web_app_tag.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_TASK_MANAGER_PROVIDERS_WEB_CONTENTS_WEB_APP_TAG_H_
 
 #include "chrome/browser/task_manager/providers/web_contents/web_contents_tag.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace task_manager {
 
@@ -25,10 +25,10 @@
   friend class WebContentsTags;
 
   WebAppTag(content::WebContents* web_contents,
-            const web_app::AppId& app_id,
+            const webapps::AppId& app_id,
             const bool is_isolated_web_app);
 
-  const web_app::AppId app_id_;
+  const webapps::AppId app_id_;
   const bool is_isolated_web_app_;
 };
 
diff --git a/chrome/browser/task_manager/providers/web_contents/web_app_tag_browsertest.cc b/chrome/browser/task_manager/providers/web_contents/web_app_tag_browsertest.cc
index 009205a..aa7ed89 100644
--- a/chrome/browser/task_manager/providers/web_contents/web_app_tag_browsertest.cc
+++ b/chrome/browser/task_manager/providers/web_contents/web_app_tag_browsertest.cc
@@ -13,9 +13,9 @@
 #include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h"
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -30,7 +30,7 @@
 
 class WebAppTagWebAppTest : public web_app::WebAppControllerBrowserTest {
  protected:
-  Browser* LaunchBrowserForWebAppInTabAndWait(const web_app::AppId& app_id,
+  Browser* LaunchBrowserForWebAppInTabAndWait(const webapps::AppId& app_id,
                                               const GURL& observe_url) {
     ui_test_utils::UrlLoadObserver url_observer(
         observe_url, content::NotificationService::AllSources());
@@ -61,7 +61,7 @@
 
   const GURL start_url =
       https_server()->GetURL("app.com", "/google/google.html");
-  const web_app::AppId app_id = InstallPWA(start_url);
+  const webapps::AppId app_id = InstallPWA(start_url);
 
   MockWebContentsTaskManager task_manager;
   EXPECT_TRUE(task_manager.tasks().empty());
@@ -90,7 +90,7 @@
 
   const GURL start_url =
       https_server()->GetURL("app.com", "/google/google.html");
-  const web_app::AppId app_id = InstallPWA(start_url);
+  const webapps::AppId app_id = InstallPWA(start_url);
 
   MockWebContentsTaskManager task_manager;
   EXPECT_TRUE(task_manager.tasks().empty());
@@ -119,7 +119,7 @@
 
   const GURL start_url =
       https_server()->GetURL("app.com", "/google/google.html");
-  const web_app::AppId app_id = InstallPWA(start_url);
+  const webapps::AppId app_id = InstallPWA(start_url);
 
   MockWebContentsTaskManager task_manager;
   EXPECT_TRUE(task_manager.tasks().empty());
@@ -156,7 +156,7 @@
 class WebAppTagIsolatedWebAppTest
     : public web_app::IsolatedWebAppBrowserTestHarness {
  protected:
-  web_app::AppId InstallIsolatedWebApp() {
+  webapps::AppId InstallIsolatedWebApp() {
     server_ =
         CreateAndStartServer(FILE_PATH_LITERAL("web_apps/simple_isolated_app"));
     web_app::IsolatedWebAppUrlInfo url_info =
@@ -189,7 +189,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTagIsolatedWebAppTest, IsolatedWebAppTaskCreated) {
   EXPECT_EQ(1U, tracked_tags().size());
 
-  web_app::AppId app_id = InstallIsolatedWebApp();
+  webapps::AppId app_id = InstallIsolatedWebApp();
   MockWebContentsTaskManager task_manager;
   EXPECT_TRUE(task_manager.tasks().empty());
 
@@ -217,7 +217,7 @@
                        IsolatedWebAppTaskTitleFallbackToAppName) {
   EXPECT_EQ(1U, tracked_tags().size());
 
-  web_app::AppId app_id = InstallIsolatedWebApp();
+  webapps::AppId app_id = InstallIsolatedWebApp();
   MockWebContentsTaskManager task_manager;
   EXPECT_TRUE(task_manager.tasks().empty());
 
diff --git a/chrome/browser/task_manager/web_contents_tags.cc b/chrome/browser/task_manager/web_contents_tags.cc
index 46bf798..dbe4840d2 100644
--- a/chrome/browser/task_manager/web_contents_tags.cc
+++ b/chrome/browser/task_manager/web_contents_tags.cc
@@ -23,7 +23,7 @@
 #include "chrome/browser/task_manager/providers/web_contents/tool_tag.h"
 #include "chrome/browser/task_manager/providers/web_contents/web_app_tag.h"
 #include "chrome/browser/task_manager/providers/web_contents/web_contents_tags_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -164,7 +164,7 @@
 #if !BUILDFLAG(IS_ANDROID)
 // static
 void WebContentsTags::CreateForWebApp(content::WebContents* web_contents,
-                                      const web_app::AppId& app_id,
+                                      const webapps::AppId& app_id,
                                       const bool is_isolated_web_app) {
   if (!WebContentsTag::FromWebContents(web_contents)) {
     TagWebContents(web_contents,
diff --git a/chrome/browser/task_manager/web_contents_tags.h b/chrome/browser/task_manager/web_contents_tags.h
index 1d47dfd..1c5b61f 100644
--- a/chrome/browser/task_manager/web_contents_tags.h
+++ b/chrome/browser/task_manager/web_contents_tags.h
@@ -13,7 +13,7 @@
 #endif
 
 #if !BUILDFLAG(IS_ANDROID)
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 class BackgroundContents;
@@ -116,7 +116,7 @@
   // not have to be cleaned up by the caller, as it is owned by |web_contents|.
   // |app_id| is the string ID of the web app.
   static void CreateForWebApp(content::WebContents* web_contents,
-                              const web_app::AppId& app_id,
+                              const webapps::AppId& app_id,
                               const bool is_isolated_web_app);
 #endif  // !BUILDFLAG(IS_ANDROID)
 
diff --git a/chrome/browser/tpcd/heuristics/opener_heuristic_browsertest.cc b/chrome/browser/tpcd/heuristics/opener_heuristic_browsertest.cc
index 0883f01..4bd89dde 100644
--- a/chrome/browser/tpcd/heuristics/opener_heuristic_browsertest.cc
+++ b/chrome/browser/tpcd/heuristics/opener_heuristic_browsertest.cc
@@ -552,8 +552,17 @@
   EXPECT_EQ(entries[0].metrics["UrlIndex"], 1);
 }
 
-IN_PROC_BROWSER_TEST_F(OpenerHeuristicBrowserTest,
-                       PopupInteraction_IsFollowedByPostPopupCookieAccess) {
+#if BUILDFLAG(IS_MAC)
+// Very flaky on macOS 11 Tests: https://crbug.com/1486448
+#define MAYBE_PopupInteraction_IsFollowedByPostPopupCookieAccess \
+  DISABLED_PopupInteraction_IsFollowedByPostPopupCookieAccess
+#else
+#define MAYBE_PopupInteraction_IsFollowedByPostPopupCookieAccess \
+  PopupInteraction_IsFollowedByPostPopupCookieAccess
+#endif
+IN_PROC_BROWSER_TEST_F(
+    OpenerHeuristicBrowserTest,
+    MAYBE_PopupInteraction_IsFollowedByPostPopupCookieAccess) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
   GURL opener_url = embedded_test_server()->GetURL("a.test", "/title1.html");
   GURL popup_url_1 = embedded_test_server()->GetURL("c.test", "/title1.html");
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 0b2f443..ea7db3f 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3062,6 +3062,8 @@
       "webui/ash/login/network_state_informer.h",
       "webui/ash/login/offline_login_screen_handler.cc",
       "webui/ash/login/offline_login_screen_handler.h",
+      "webui/ash/login/online_authentication_screen_handler.cc",
+      "webui/ash/login/online_authentication_screen_handler.h",
       "webui/ash/login/online_login_utils.cc",
       "webui/ash/login/online_login_utils.h",
       "webui/ash/login/oobe_display_chooser.cc",
diff --git a/chrome/browser/ui/ash/user_education/chrome_user_education_delegate_unittest.cc b/chrome/browser/ui/ash/user_education/chrome_user_education_delegate_unittest.cc
index d607593..cbe24c5 100644
--- a/chrome/browser/ui/ash/user_education/chrome_user_education_delegate_unittest.cc
+++ b/chrome/browser/ui/ash/user_education/chrome_user_education_delegate_unittest.cc
@@ -174,7 +174,7 @@
   using AppIdWithElementIdentifier =
       std::pair<const char*, absl::optional<ui::ElementIdentifier>>;
 
-  constexpr std::array<AppIdWithElementIdentifier, 4u> kAppIdsWithElementIds = {
+  const std::array<AppIdWithElementIdentifier, 4u> kAppIdsWithElementIds = {
       {{web_app::kHelpAppId, ash::kExploreAppElementId},
        {web_app::kOsSettingsAppId, ash::kSettingsAppElementId},
        {"unknown", absl::nullopt},
diff --git a/chrome/browser/ui/browser_element_identifiers.cc b/chrome/browser/ui/browser_element_identifiers.cc
index e401c27b..a495b58 100644
--- a/chrome/browser/ui/browser_element_identifiers.cc
+++ b/chrome/browser/ui/browser_element_identifiers.cc
@@ -70,6 +70,7 @@
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kToolbarForwardButtonElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kToolbarHomeButtonElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kToolbarMediaButtonElementId);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kToolbarOverflowButtonElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kToolbarSidePanelButtonElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kToolbarSidePanelContainerElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kToolbarTabCounterButtonElementId);
diff --git a/chrome/browser/ui/browser_element_identifiers.h b/chrome/browser/ui/browser_element_identifiers.h
index 88cc0dc3..e0ff22a 100644
--- a/chrome/browser/ui/browser_element_identifiers.h
+++ b/chrome/browser/ui/browser_element_identifiers.h
@@ -79,6 +79,7 @@
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kToolbarForwardButtonElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kToolbarHomeButtonElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kToolbarMediaButtonElementId);
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kToolbarOverflowButtonElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kToolbarSidePanelButtonElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kToolbarSidePanelContainerElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kToolbarTabCounterButtonElementId);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc
index 4a77a1c..697ff2d 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -53,7 +53,6 @@
 #include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
 #include "chrome/browser/ui/web_applications/web_app_tabbed_utils.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_tab_helper.h"
 #include "chrome/common/webui_url_constants.h"
@@ -64,6 +63,7 @@
 #include "components/tab_groups/tab_group_id.h"
 #include "components/tab_groups/tab_group_visual_data.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_observer.h"
@@ -2663,7 +2663,7 @@
   web_app::WebAppProvider* provider =
       web_app::WebAppProvider::GetForWebContents(contents);
   // Can be null if there is no tab helper or app id.
-  const web_app::AppId* app_id = web_app::WebAppTabHelper::GetAppId(contents);
+  const webapps::AppId* app_id = web_app::WebAppTabHelper::GetAppId(contents);
   if (!app_id) {
     return true;
   }
diff --git a/chrome/browser/ui/tabs/tab_strip_model_browsertest.cc b/chrome/browser/ui/tabs/tab_strip_model_browsertest.cc
index 043dd3b..6dbe040d 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_browsertest.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model_browsertest.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/ui/prevent_close_test_base.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/common/chrome_features.h"
@@ -22,6 +21,7 @@
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/policy_constants.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "ui/base/window_open_disposition.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/ui/user_education/show_promo_in_page_browsertest.cc b/chrome/browser/ui/user_education/show_promo_in_page_browsertest.cc
index 1bdf873..1d0a01b8 100644
--- a/chrome/browser/ui/user_education/show_promo_in_page_browsertest.cc
+++ b/chrome/browser/ui/user_education/show_promo_in_page_browsertest.cc
@@ -31,8 +31,6 @@
 constexpr char kPageWithAnchorURL[] = "chrome://internals/user-education";
 constexpr char kPageWithoutAnchorURL[] = "chrome://settings";
 constexpr char16_t kBubbleBodyText[] = u"bubble body";
-constexpr ui::ElementIdentifier kHelpBubbleAnchorId =
-    kWebUIIPHDemoElementIdentifier;
 
 // This should be short enough that tests that *expect* the operation to time
 // out should fail. Standard test timeout will be used for tests expected to
@@ -43,7 +41,7 @@
 // need to specify `target_url` and `callback`.
 ShowPromoInPage::Params GetDefaultParams() {
   ShowPromoInPage::Params params;
-  params.bubble_anchor_id = kHelpBubbleAnchorId;
+  params.bubble_anchor_id = kWebUIIPHDemoElementIdentifier;
   params.bubble_arrow = user_education::HelpBubbleArrow::kBottomLeft;
   params.bubble_text = kBubbleBodyText;
   return params;
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
index cf47f04..61b20f4 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
@@ -268,11 +268,14 @@
 }
 
 void DownloadBubbleSecurityView::BackButtonPressed() {
-  delegate_->AddSecuritySubpageWarningActionEvent(
-      content_id_, DownloadItemWarningData::WarningAction::BACK);
-  did_log_action_ = true;
-  base::UmaHistogramEnumeration(
-      kSubpageActionHistogram, DownloadBubbleSubpageAction::kPressedBackButton);
+  if (IsInitialized()) {
+    delegate_->AddSecuritySubpageWarningActionEvent(
+        content_id_, DownloadItemWarningData::WarningAction::BACK);
+    did_log_action_ = true;
+    base::UmaHistogramEnumeration(
+        kSubpageActionHistogram,
+        DownloadBubbleSubpageAction::kPressedBackButton);
+  }
   Reset();
   navigation_handler_->OpenPrimaryDialog();
 }
@@ -284,9 +287,11 @@
 }
 
 void DownloadBubbleSecurityView::CloseBubble() {
-  delegate_->AddSecuritySubpageWarningActionEvent(
-      content_id_, DownloadItemWarningData::WarningAction::CLOSE);
-  did_log_action_ = true;
+  if (IsInitialized()) {
+    delegate_->AddSecuritySubpageWarningActionEvent(
+        content_id_, DownloadItemWarningData::WarningAction::CLOSE);
+    did_log_action_ = true;
+  }
   // CloseDialog will delete the object. Do not access any members below.
   navigation_handler_->CloseDialog(
       views::Widget::ClosedReason::kCloseButtonClicked);
@@ -687,6 +692,9 @@
 }
 
 void DownloadBubbleSecurityView::UpdatePasswordPrompt() {
+  if (!IsInitialized()) {
+    return;
+  }
   if (!base::FeatureList::IsEnabled(
           safe_browsing::kDeepScanningEncryptedArchives)) {
     return;
@@ -908,6 +916,9 @@
 
 bool DownloadBubbleSecurityView::ProcessDeepScanClick() {
   absl::optional<std::string> password;
+  if (!IsInitialized()) {
+    return true;
+  }
   if (base::FeatureList::IsEnabled(
           safe_browsing::kDeepScanningEncryptedArchives)) {
     password = base::UTF16ToUTF8(password_prompt_->GetText());
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view.cc b/chrome/browser/ui/views/page_action/pwa_install_view.cc
index fbd97c0..34aa5d6 100644
--- a/chrome/browser/ui/views/page_action/pwa_install_view.cc
+++ b/chrome/browser/ui/views/page_action/pwa_install_view.cc
@@ -218,7 +218,7 @@
       !manager->manifest().id.is_valid()) {
     return false;
   }
-  web_app::AppId app_id =
+  webapps::AppId app_id =
       web_app::GenerateAppIdFromManifest(manager->manifest());
 
   Profile* profile =
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
index 25eaed4..ea67bd4c 100644
--- a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
@@ -233,13 +233,13 @@
     app_banner_manager_->WaitForInstallableCheckTearDown();
   }
 
-  web_app::AppId ExecutePwaInstallIcon() {
+  webapps::AppId ExecutePwaInstallIcon() {
     chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true);
 
-    web_app::AppId app_id;
+    webapps::AppId app_id;
     base::RunLoop run_loop;
     web_app::SetInstalledCallbackForTesting(base::BindLambdaForTesting(
-        [&app_id, &run_loop](const web_app::AppId& installed_app_id,
+        [&app_id, &run_loop](const webapps::AppId& installed_app_id,
                              webapps::InstallResultCode code) {
           app_id = installed_app_id;
           run_loop.Quit();
@@ -254,7 +254,7 @@
     return app_id;
   }
 
-  void UninstallWebApp(const web_app::AppId& app_id) {
+  void UninstallWebApp(const webapps::AppId& app_id) {
     base::RunLoop run_loop;
     web_app::WebAppProvider::GetForTest(browser()->profile())
         ->scheduler()
@@ -279,7 +279,7 @@
 
     web_app::SetInstallBounceMetricTimeForTesting(test_time);
 
-    const web_app::AppId app_id = ExecutePwaInstallIcon();
+    const webapps::AppId app_id = ExecutePwaInstallIcon();
 
     web_app::SetInstallBounceMetricTimeForTesting(test_time + install_duration);
 
@@ -382,7 +382,7 @@
                        PwaSetToOpenInTabIsInstallable) {
   bool installable = OpenTab(GetInstallableAppURL()).installable;
   ASSERT_TRUE(installable);
-  web_app::AppId app_id = ExecutePwaInstallIcon();
+  webapps::AppId app_id = ExecutePwaInstallIcon();
 
   // Change launch container to open in tab.
   web_app::WebAppProvider::GetForTest(browser()->profile())
@@ -588,7 +588,7 @@
   GURL app_url = GetInstallableAppURL();
   bool installable = OpenTab(app_url).installable;
   ASSERT_TRUE(installable);
-  const web_app::AppId app_id = ExecutePwaInstallIcon();
+  const webapps::AppId app_id = ExecutePwaInstallIcon();
 
   // Use a new tab because installed app may have opened in new window.
   OpenTabResult result = OpenTab(app_url);
diff --git a/chrome/browser/ui/views/site_data/page_specific_site_data_dialog.cc b/chrome/browser/ui/views/site_data/page_specific_site_data_dialog.cc
index ae26f27..686cf63b 100644
--- a/chrome/browser/ui/views/site_data/page_specific_site_data_dialog.cc
+++ b/chrome/browser/ui/views/site_data/page_specific_site_data_dialog.cc
@@ -395,13 +395,7 @@
 
   bool IsBrowsingDataEntryViewFullyPartitioned(
       const BrowsingDataModel::BrowsingDataEntryView& entry) {
-    // We consider the browsing data entry view to be fully partitioned if the
-    // storage is backed by a StorageKey and the StorageKey is third-party.
-    // Unlike for cookies, we can be sure that given context is partitioned if
-    // its storage keys are as that determines the scope of access.
-    const blink::StorageKey* storage_key =
-        absl::get_if<blink::StorageKey>(&entry.data_key.get());
-    return storage_key != nullptr && storage_key->IsThirdPartyContext();
+    return entry.GetThirdPartyPartitioningSite().has_value();
   }
 
   bool IsCookieTreeNodeFullyPartitioned(CookieTreeNode* node) {
diff --git a/chrome/browser/ui/views/toolbar/overflow_button.cc b/chrome/browser/ui/views/toolbar/overflow_button.cc
index b5b876f78..2e117fb7 100644
--- a/chrome/browser/ui/views/toolbar/overflow_button.cc
+++ b/chrome/browser/ui/views/toolbar/overflow_button.cc
@@ -5,15 +5,44 @@
 #include "chrome/browser/ui/views/toolbar/overflow_button.h"
 
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/browser_element_identifiers.h"
+#include "chrome/browser/ui/layout_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/menu_source_utils.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/controls/menu/menu_model_adapter.h"
+#include "ui/views/controls/menu/menu_runner.h"
+#include "ui/views/view_class_properties.h"
 
 OverflowButton::OverflowButton() {
+  auto menu_button_controller = std::make_unique<views::MenuButtonController>(
+      this,
+      base::BindRepeating(&OverflowButton::RunMenu, base::Unretained(this)),
+      std::make_unique<views::Button::DefaultButtonControllerDelegate>(this));
+  menu_button_controller_ = menu_button_controller.get();
+  SetProperty(views::kElementIdentifierKey, kToolbarOverflowButtonElementId);
+  SetButtonController(std::move(menu_button_controller));
   SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_OVERFLOW_BUTTON));
   SetVectorIcon(kOverflowChevronIcon);
 }
 
+void OverflowButton::RunMenu() {
+  CHECK(GetVisible());
+  CHECK(create_menu_model_callback_);
+  if (menu_model_) {
+    menu_model_->Clear();
+  }
+  menu_model_ = create_menu_model_callback_.Run();
+  CHECK(menu_model_);
+  menu_runner_ = std::make_unique<views::MenuRunner>(
+      menu_model_.get(), views::MenuRunner::HAS_MNEMONICS);
+  menu_runner_->RunMenuAt(
+      menu_button_controller_->button()->GetWidget(), menu_button_controller_,
+      menu_button_controller_->button()->GetAnchorBoundsInScreen(),
+      views::MenuAnchorPosition::kTopRight, ui::MENU_SOURCE_NONE);
+}
+
 OverflowButton::~OverflowButton() = default;
 
 BEGIN_METADATA(OverflowButton, ToolbarButton)
diff --git a/chrome/browser/ui/views/toolbar/overflow_button.h b/chrome/browser/ui/views/toolbar/overflow_button.h
index 5ac0585..afdf1bd 100644
--- a/chrome/browser/ui/views/toolbar/overflow_button.h
+++ b/chrome/browser/ui/views/toolbar/overflow_button.h
@@ -7,6 +7,8 @@
 
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
 #include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/controls/button/menu_button_controller.h"
+#include "ui/views/controls/menu/menu_runner.h"
 
 // A chevron button that indicates some toolbar elements have overflowed due to
 // browser window being smaller than usual. Left press on it displays a drop
@@ -14,11 +16,34 @@
 class OverflowButton : public ToolbarButton {
  public:
   METADATA_HEADER(OverflowButton);
+  using CreateMenuModelCallback =
+      base::RepeatingCallback<std::unique_ptr<ui::SimpleMenuModel>()>;
 
   OverflowButton();
   OverflowButton(const OverflowButton&) = delete;
   OverflowButton& operator=(const OverflowButton&) = delete;
   ~OverflowButton() override;
+
+  // Triggered by left press.
+  void RunMenu();
+
+  void set_create_menu_model_callback(CreateMenuModelCallback callback) {
+    create_menu_model_callback_ = std::move(callback);
+  }
+
+  const ui::SimpleMenuModel* menu_model_for_testing() const {
+    return menu_model_.get();
+  }
+
+ private:
+  base::RepeatingCallback<std::unique_ptr<ui::SimpleMenuModel>()>
+      create_menu_model_callback_;
+
+  // The menu of overflowed elements.
+  std::unique_ptr<ui::SimpleMenuModel> menu_model_;
+
+  std::unique_ptr<views::MenuRunner> menu_runner_;
+  raw_ptr<views::MenuButtonController> menu_button_controller_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_OVERFLOW_BUTTON_H_
diff --git a/chrome/browser/ui/views/toolbar/toolbar_controller.cc b/chrome/browser/ui/views/toolbar/toolbar_controller.cc
index dfcbc38..b86979f 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_controller.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_controller.cc
@@ -6,10 +6,40 @@
 
 #include "chrome/browser/ui/views/toolbar/overflow_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/views/controls/menu/menu_item_view.h"
 #include "ui/views/layout/flex_layout.h"
 #include "ui/views/layout/flex_layout_types.h"
 #include "ui/views/view_class_properties.h"
 
+namespace {
+
+std::u16string GenerateMenuText(const views::View* element) {
+  // TODO(crbug.com/1481273): Menu items might deserve their own text
+  // instead of using accessible name.
+  std::u16string accessible_name = element->GetAccessibleName();
+  if (!accessible_name.empty()) {
+    return accessible_name;
+  }
+
+  ui::ElementIdentifier id = element->GetProperty(views::kElementIdentifierKey);
+  CHECK(id);
+
+  // Containers have no accessible names. Hard code their texts here.
+  // TODO(crbug.com/1481273): Explore a more maintainable way to map container
+  // id to text.
+  if (id == kToolbarExtensionsContainerElementId) {
+    return u"Extensions";
+  } else if (id == kToolbarSidePanelContainerElementId) {
+    return u"Side panel";
+  }
+
+  // Buttons with an empty accessible name should raise an error.
+  NOTREACHED_NORETURN();
+}
+
+}  // namespace
+
 ToolbarController::ToolbarController(
     std::vector<ui::ElementIdentifier> element_ids,
     int element_flex_order_start,
@@ -41,18 +71,7 @@
 bool ToolbarController::ShouldShowOverflowButton() {
   // Once at least one button has been dropped by layout manager show overflow
   // button.
-  const views::FlexLayout* flex_layout = static_cast<views::FlexLayout*>(
-      toolbar_container_view_->GetLayoutManager());
-  bool show_button = false;
-  for (ui::ElementIdentifier id : element_ids_) {
-    const views::View* toolbar_element = FindToolbarElementWithId(id);
-    if (flex_layout->CanBeVisible(toolbar_element) &&
-        !toolbar_element->GetVisible()) {
-      show_button = true;
-      break;
-    }
-  }
-  return show_button;
+  return GetOverflowedElements().size() > 0;
 }
 
 const views::View* ToolbarController::FindToolbarElementWithId(
@@ -67,4 +86,31 @@
   return nullptr;
 }
 
+std::vector<const views::View*> ToolbarController::GetOverflowedElements() {
+  std::vector<const views::View*> overflowed_buttons;
+  const views::FlexLayout* flex_layout = static_cast<views::FlexLayout*>(
+      toolbar_container_view_->GetLayoutManager());
+  for (ui::ElementIdentifier id : element_ids_) {
+    const views::View* toolbar_element = FindToolbarElementWithId(id);
+    if (flex_layout->CanBeVisible(toolbar_element) &&
+        !toolbar_element->GetVisible()) {
+      overflowed_buttons.push_back(toolbar_element);
+    }
+  }
+  return overflowed_buttons;
+}
+
+std::unique_ptr<ui::SimpleMenuModel>
+ToolbarController::CreateOverflowMenuModel() {
+  CHECK(overflow_button_->GetVisible());
+  auto menu_model = std::make_unique<ui::SimpleMenuModel>(this);
+  int menu_id_start = 0;
+  for (auto* toolbar_element : GetOverflowedElements()) {
+    menu_model->AddItem(menu_id_start++, GenerateMenuText(toolbar_element));
+  }
+  return menu_model;
+}
+
+void ToolbarController::ExecuteCommand(int command_id, int event_flags) {}
+
 ToolbarController::~ToolbarController() = default;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_controller.h b/chrome/browser/ui/views/toolbar/toolbar_controller.h
index 19f54df..dacc539 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_controller.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_controller.h
@@ -14,7 +14,7 @@
 #include "ui/views/view.h"
 
 // Manages toolbar elements' visibility using flex rules.
-class ToolbarController {
+class ToolbarController : public ui::SimpleMenuModel::Delegate {
  public:
   ToolbarController(std::vector<ui::ElementIdentifier> element_ids,
                     int element_flex_order_start,
@@ -22,7 +22,7 @@
                     views::View* overflow_button);
   ToolbarController(const ToolbarController&) = delete;
   ToolbarController& operator=(const ToolbarController&) = delete;
-  ~ToolbarController();
+  ~ToolbarController() override;
 
   // Returns true if layout manager of `toolbar_container_view_` hides any
   // toolbar elements.
@@ -32,8 +32,12 @@
     overflow_button_->SetVisible(should_show);
   }
 
+  // Create the overflow menu model for hidden buttons.
+  std::unique_ptr<ui::SimpleMenuModel> CreateOverflowMenuModel();
+
  private:
-  friend class ToolbarControllerTest;
+  friend class ToolbarControllerInteractiveTest;
+  friend class ToolbarControllerUnitTest;
 
   // Searches for a toolbar element from `toolbar_container_view_` with `id`.
   views::View* FindToolbarElementWithId(ui::ElementIdentifier id) {
@@ -42,6 +46,12 @@
   }
   const views::View* FindToolbarElementWithId(ui::ElementIdentifier id) const;
 
+  // Returns currently hidden elements.
+  std::vector<const views::View*> GetOverflowedElements();
+
+  // ui::SimpleMenuModel::Delegate:
+  void ExecuteCommand(int command_id, int event_flags) override;
+
   // The toolbar elements managed by this controller.
   // Order matters as each will be assigned with a flex order that increments by
   // 1 starting from `element_flex_order_start_`. So the last element drops out
diff --git a/chrome/browser/ui/views/toolbar/toolbar_controller_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_controller_interactive_uitest.cc
index 7f70f87e..be1698f 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_controller_interactive_uitest.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_controller.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chrome/test/interaction/interactive_browser_test.h"
 #include "content/public/test/browser_test.h"
@@ -19,14 +20,14 @@
     BrowserViewLayout::kMainBrowserContentsMinimumWidth;
 }  // namespace
 
-class ToolbarControllerTest : public InteractiveBrowserTest {
+class ToolbarControllerInteractiveTest : public InteractiveBrowserTest {
  public:
-  ToolbarControllerTest() {
+  ToolbarControllerInteractiveTest() {
     scoped_feature_list_.InitWithFeatures({features::kResponsiveToolbar}, {});
   }
 
   void SetUpOnMainThread() override {
-    InProcessBrowserTest::SetUpOnMainThread();
+    InteractiveBrowserTest::SetUpOnMainThread();
     browser_view_ = BrowserView::GetBrowserViewForBrowser(browser());
     toolbar_controller_ = const_cast<ToolbarController*>(
         browser_view_->toolbar()->toolbar_controller());
@@ -45,7 +46,7 @@
     overflow_button_ = nullptr;
     toolbar_controller_ = nullptr;
     browser_view_ = nullptr;
-    InProcessBrowserTest::TearDownOnMainThread();
+    InteractiveBrowserTest::TearDownOnMainThread();
   }
 
   // Returns the minimum width the toolbar view can be without any elements
@@ -86,7 +87,27 @@
     }
   }
 
-  void SetBrowserWithWidth(int width) {
+  // This checks menu model, not the actual menu that pops up.
+  // TODO(pengchaocai): Explore a way to check the actual menu appearing.
+  auto CheckMenuMatchesOverflowedElements() {
+    return Steps(Check(base::BindLambdaForTesting([this]() {
+      const ui::SimpleMenuModel* menu = GetOverflowMenu();
+      std::vector<const views::View*> overflowed_elements =
+          GetOverflowedElements();
+      EXPECT_NE(menu, nullptr);
+      EXPECT_GT(menu->GetItemCount(), size_t(0));
+      EXPECT_EQ(menu->GetItemCount(), overflowed_elements.size());
+      for (size_t i = 0; i < menu->GetItemCount(); ++i) {
+        if (menu->GetLabelAt(i).compare(
+                overflowed_elements[i]->GetAccessibleName()) != 0) {
+          return false;
+        }
+      }
+      return true;
+    })));
+  }
+
+  void SetBrowserWidth(int width) {
     browser_view_->SetSize({width, browser_view_->size().height()});
   }
 
@@ -100,6 +121,13 @@
     return element_ids_;
   }
   int overflow_threshold_width() const { return overflow_threshold_width_; }
+  std::vector<const views::View*> GetOverflowedElements() {
+    return toolbar_controller_->GetOverflowedElements();
+  }
+  const ui::SimpleMenuModel* GetOverflowMenu() {
+    return static_cast<OverflowButton*>(overflow_button_)
+        ->menu_model_for_testing();
+  }
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -115,7 +143,7 @@
   int overflow_threshold_width_;
 };
 
-IN_PROC_BROWSER_TEST_F(ToolbarControllerTest, FlexOrderCorrect) {
+IN_PROC_BROWSER_TEST_F(ToolbarControllerInteractiveTest, FlexOrderCorrect) {
   int order_start = element_flex_order_start();
   for (ui::ElementIdentifier id : element_ids()) {
     const views::View* toolbar_element = FindToolbarElementWithId(id);
@@ -126,70 +154,82 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_F(ToolbarControllerTest, StartBrowserWithThresholdWidth) {
+IN_PROC_BROWSER_TEST_F(ToolbarControllerInteractiveTest,
+                       StartBrowserWithThresholdWidth) {
   // Start browser with threshold width. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width());
+  SetBrowserWidth(overflow_threshold_width());
   EXPECT_FALSE(overflow_button()->GetVisible());
 
   // Resize browser a bit wider. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() + 1);
+  SetBrowserWidth(overflow_threshold_width() + 1);
   EXPECT_FALSE(overflow_button()->GetVisible());
 
   // Resize browser back to threshold width. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width());
+  SetBrowserWidth(overflow_threshold_width());
   EXPECT_FALSE(overflow_button()->GetVisible());
 
   // Resize browser a bit narrower. Should see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() - 1);
+  SetBrowserWidth(overflow_threshold_width() - 1);
   EXPECT_TRUE(overflow_button()->GetVisible());
 
   // Resize browser back to threshold width. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width());
+  SetBrowserWidth(overflow_threshold_width());
   EXPECT_FALSE(overflow_button()->GetVisible());
 }
 
-IN_PROC_BROWSER_TEST_F(ToolbarControllerTest,
+IN_PROC_BROWSER_TEST_F(ToolbarControllerInteractiveTest,
                        StartBrowserWithWidthSmallerThanThreshold) {
   // Start browser with a smaller width than threshold. Should see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() - 1);
+  SetBrowserWidth(overflow_threshold_width() - 1);
   EXPECT_TRUE(overflow_button()->GetVisible());
 
   // Resize browser wider to threshold width. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width());
+  SetBrowserWidth(overflow_threshold_width());
   EXPECT_FALSE(overflow_button()->GetVisible());
 
   // Resize browser a bit narrower. Should see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() - 1);
+  SetBrowserWidth(overflow_threshold_width() - 1);
   EXPECT_TRUE(overflow_button()->GetVisible());
 
   // Keep resizing browser narrower. Should see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() - 2);
+  SetBrowserWidth(overflow_threshold_width() - 2);
   EXPECT_TRUE(overflow_button()->GetVisible());
 
   // Resize browser a bit wider. Should still see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() - 1);
+  SetBrowserWidth(overflow_threshold_width() - 1);
   EXPECT_TRUE(overflow_button()->GetVisible());
 }
 
-IN_PROC_BROWSER_TEST_F(ToolbarControllerTest,
+IN_PROC_BROWSER_TEST_F(ToolbarControllerInteractiveTest,
                        StartBrowserWithWidthLargerThanThreshold) {
   // Start browser with a larger width than threshold. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() + 1);
+  SetBrowserWidth(overflow_threshold_width() + 1);
   EXPECT_FALSE(overflow_button()->GetVisible());
 
   // Resize browser wider. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() + 2);
+  SetBrowserWidth(overflow_threshold_width() + 2);
   EXPECT_FALSE(overflow_button()->GetVisible());
 
   // Resize browser a bit narrower. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() + 1);
+  SetBrowserWidth(overflow_threshold_width() + 1);
   EXPECT_FALSE(overflow_button()->GetVisible());
 
   // Resize browser back to threshold width. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width());
+  SetBrowserWidth(overflow_threshold_width());
   EXPECT_FALSE(overflow_button()->GetVisible());
 
   // Resize browser a bit wider. Should not see overflow.
-  SetBrowserWithWidth(overflow_threshold_width() + 1);
+  SetBrowserWidth(overflow_threshold_width() + 1);
   EXPECT_FALSE(overflow_button()->GetVisible());
 }
+
+IN_PROC_BROWSER_TEST_F(ToolbarControllerInteractiveTest,
+                       MenuMatchesOverflowedElements) {
+  RunTestSequence(Do(base::BindLambdaForTesting([this]() {
+                    SetBrowserWidth(overflow_threshold_width() - 1);
+                  })),
+                  WaitForShow(kToolbarOverflowButtonElementId),
+                  PressButton(kToolbarOverflowButtonElementId),
+                  WaitForActivate(kToolbarOverflowButtonElementId),
+                  CheckMenuMatchesOverflowedElements());
+}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_controller_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_controller_unittest.cc
index e2f50ea..d1d63674 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_controller_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_controller_unittest.cc
@@ -7,72 +7,158 @@
 #include <gtest/gtest.h>
 
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/test/views/chrome_views_test_base.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/events/test/event_generator.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/layout/flex_layout.h"
 #include "ui/views/layout/flex_layout_types.h"
 #include "ui/views/view_class_properties.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_utils.h"
 
-TEST(ToolbarControllerUnitTest, OverflowButtonVisibility) {
-  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kDummyButton1);
-  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kDummyButton2);
-  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kDummyButton3);
+namespace {
+// Toolbar button size is ~34dp.
+constexpr gfx::Size kButtonSize(34, 34);
 
-  std::unique_ptr<views::LayoutProvider> layout_provider =
-      ChromeLayoutProvider::CreateLayoutProvider();
+constexpr int kElementFlexOrderStart = 1;
+}  // namespace
 
-  views::View toolbar_container_view;
-  toolbar_container_view
-      .SetLayoutManager(std::make_unique<views::FlexLayout>())
-      ->SetOrientation(views::LayoutOrientation::kHorizontal)
-      .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
-      .SetDefault(views::kFlexBehaviorKey,
-                  views::FlexSpecification(
-                      views::LayoutOrientation::kHorizontal,
-                      views::MinimumFlexSizeRule::kPreferredSnapToZero,
-                      views::MaximumFlexSizeRule::kPreferred));
+class ToolbarControllerUnitTest : public ChromeViewsTestBase {
+ public:
+  ToolbarControllerUnitTest() = default;
+  ToolbarControllerUnitTest(const ToolbarControllerUnitTest&) = delete;
+  ToolbarControllerUnitTest& operator=(const ToolbarControllerUnitTest&) =
+      delete;
+  ~ToolbarControllerUnitTest() override = default;
 
-  gfx::Size button_preferred_size(10, 10);
+  void SetUp() override {
+    ChromeViewsTestBase::SetUp();
+    widget_ = CreateTestWidget();
+    widget_->Show();
 
-  views::View button1;
-  button1.SetProperty(views::kElementIdentifierKey, kDummyButton1);
-  toolbar_container_view.AddChildView(&button1);
-  button1.SetPreferredSize(button_preferred_size);
+    std::unique_ptr<views::View> toolbar_container_view =
+        std::make_unique<views::View>();
+    toolbar_container_view
+        ->SetLayoutManager(std::make_unique<views::FlexLayout>())
+        ->SetOrientation(views::LayoutOrientation::kHorizontal)
+        .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
+        .SetDefault(views::kFlexBehaviorKey,
+                    views::FlexSpecification(
+                        views::LayoutOrientation::kHorizontal,
+                        views::MinimumFlexSizeRule::kPreferredSnapToZero,
+                        views::MaximumFlexSizeRule::kPreferred));
+    toolbar_container_view_ =
+        widget_->SetContentsView(std::move(toolbar_container_view));
 
-  views::View button2;
-  button2.SetProperty(views::kElementIdentifierKey, kDummyButton2);
-  toolbar_container_view.AddChildView(&button2);
-  button2.SetPreferredSize(button_preferred_size);
+    DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kDummyButton1);
+    DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kDummyButton2);
+    DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kDummyButton3);
+    std::vector<ui::ElementIdentifier> element_ids = {
+        kDummyButton1, kDummyButton2, kDummyButton3};
+    InitToolbarContainerViewWithTestButtons(element_ids);
 
-  views::View button3;
-  button3.SetProperty(views::kElementIdentifierKey, kDummyButton3);
-  toolbar_container_view.AddChildView(&button3);
-  button3.SetPreferredSize(button_preferred_size);
+    auto overflow_button = std::make_unique<OverflowButton>();
+    overflow_button_ =
+        toolbar_container_view_->AddChildView(std::move(overflow_button));
+    overflow_button_->SetVisible(false);
+    toolbar_controller_ = std::make_unique<ToolbarController>(
+        element_ids, kElementFlexOrderStart, toolbar_container_view_,
+        overflow_button_);
+    overflow_button_->set_create_menu_model_callback(
+        base::BindRepeating(&ToolbarController::CreateOverflowMenuModel,
+                            base::Unretained(toolbar_controller_.get())));
 
-  OverflowButton overflow_button;
-  toolbar_container_view.AddChildView(&overflow_button);
+    event_generator_ = std::make_unique<ui::test::EventGenerator>(
+        views::GetRootWindow(widget_.get()));
+  }
 
-  std::vector<ui::ElementIdentifier> element_ids = {
-      kDummyButton1, kDummyButton2, kDummyButton3};
-  int element_flex_order_start = 1;
-  ToolbarController controller(element_ids, element_flex_order_start,
-                               &toolbar_container_view, &overflow_button);
+  // Add test buttons with `ids` to `toolbar_container_view_`.
+  void InitToolbarContainerViewWithTestButtons(
+      std::vector<ui::ElementIdentifier> ids) {
+    for (size_t i = 0; i < ids.size(); ++i) {
+      auto button = std::make_unique<views::View>();
+      button->SetProperty(views::kElementIdentifierKey, ids[i]);
+      button->SetPreferredSize(kButtonSize);
+      button->SetAccessibleName(
+          base::StrCat({u"DummyButton", base::NumberToString16(i)}));
+      button->SetVisible(true);
+      test_buttons_.emplace_back(
+          toolbar_container_view_->AddChildView(std::move(button)));
+    }
+  }
 
-  // Enough space to accommodate 3 buttons; overflow button does not show.
-  toolbar_container_view.SetSize(gfx::Size(30, 10));
-  EXPECT_TRUE(button1.GetVisible());
-  EXPECT_TRUE(button2.GetVisible());
-  EXPECT_TRUE(button3.GetVisible());
-  controller.SetOverflowButtonVisible(controller.ShouldShowOverflowButton());
-  EXPECT_FALSE(overflow_button.GetVisible());
+  void TearDown() override {
+    overflow_button_ = nullptr;
+    toolbar_container_view_ = nullptr;
+    event_generator_.reset();
+    toolbar_controller_.reset();
+    widget_.reset();
+    ChromeViewsTestBase::TearDown();
+  }
 
-  // One button overflows.
-  toolbar_container_view.SetSize(gfx::Size(25, 10));
-  EXPECT_TRUE(button1.GetVisible());
-  EXPECT_TRUE(button2.GetVisible());
-  EXPECT_FALSE(button3.GetVisible());
+  views::Widget* widget() { return widget_.get(); }
+  ToolbarController* toolbar_controller() { return toolbar_controller_.get(); }
+  ui::test::EventGenerator* event_generator() { return event_generator_.get(); }
+  const views::View* overflow_button() { return overflow_button_; }
+  const std::vector<views::View*>& test_buttons() { return test_buttons_; }
+  const ui::SimpleMenuModel* overflow_menu() {
+    return overflow_button_->menu_model_for_testing();
+  }
+  std::vector<const views::View*> GetOverflowedElements() {
+    return toolbar_controller()->GetOverflowedElements();
+  }
 
-  // Overflow button appears.
-  controller.SetOverflowButtonVisible(controller.ShouldShowOverflowButton());
-  EXPECT_TRUE(overflow_button.GetVisible());
+ private:
+  std::unique_ptr<views::Widget> widget_;
+  std::unique_ptr<ToolbarController> toolbar_controller_;
+  std::unique_ptr<ui::test::EventGenerator> event_generator_;
+  raw_ptr<views::View> toolbar_container_view_;
+  raw_ptr<OverflowButton> overflow_button_;
+
+  // Buttons being tested.
+  std::vector<views::View*> test_buttons_;
+};
+
+TEST_F(ToolbarControllerUnitTest, OverflowButtonVisibility) {
+  // Initialize widget width with total width of all test buttons.
+  // Should not see overflowed buttons.
+  widget()->SetSize(gfx::Size(kButtonSize.width() * test_buttons().size(),
+                              kButtonSize.height()));
+  EXPECT_EQ(GetOverflowedElements().size(), size_t(0));
+  toolbar_controller()->SetOverflowButtonVisible(
+      toolbar_controller()->ShouldShowOverflowButton());
+  EXPECT_FALSE(overflow_button()->GetVisible());
+
+  // Shrink widget width with one button width smaller.
+  widget()->SetSize(gfx::Size(kButtonSize.width() * (test_buttons().size() - 1),
+                              kButtonSize.height()));
+  EXPECT_EQ(GetOverflowedElements().size(), size_t(1));
+  toolbar_controller()->SetOverflowButtonVisible(
+      toolbar_controller()->ShouldShowOverflowButton());
+  EXPECT_TRUE(overflow_button()->GetVisible());
+}
+
+TEST_F(ToolbarControllerUnitTest, OverflowedButtonsMatchMenu) {
+  widget()->SetSize(gfx::Size(kButtonSize.width() * (test_buttons().size() - 1),
+                              kButtonSize.height()));
+  toolbar_controller()->SetOverflowButtonVisible(
+      toolbar_controller()->ShouldShowOverflowButton());
+  EXPECT_TRUE(overflow_button()->GetVisible());
+
+  widget()->LayoutRootViewIfNecessary();
+  event_generator()->MoveMouseTo(
+      overflow_button()->GetBoundsInScreen().CenterPoint());
+  event_generator()->PressLeftButton();
+
+  const ui::SimpleMenuModel* menu = overflow_menu();
+  std::vector<const views::View*> overflowed_buttons = GetOverflowedElements();
+
+  // Overflowed buttons should match overflow menu.
+  EXPECT_TRUE(menu);
+  EXPECT_EQ(overflowed_buttons.size(), menu->GetItemCount());
+  for (size_t i = 0; i < overflowed_buttons.size(); ++i) {
+    EXPECT_EQ(overflowed_buttons[i]->GetAccessibleName(), menu->GetLabelAt(i));
+  }
 }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 5ae06b7..52b33e6 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -932,6 +932,10 @@
             kToolbarForwardButtonElementId, kToolbarAvatarButtonElementId,
             kToolbarHomeButtonElementId, kToolbarChromeLabsButtonElementId},
         kToolbarFlexOrderStart, container_view_, overflow_button_);
+
+    overflow_button_->set_create_menu_model_callback(
+        base::BindRepeating(&ToolbarController::CreateOverflowMenuModel,
+                            base::Unretained(toolbar_controller_.get())));
   }
 
   LayoutCommon();
diff --git a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
index 4f32cac..a52773b 100644
--- a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
+++ b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
@@ -25,6 +25,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/interaction/interaction_test_util_browser.h"
 #include "chrome/test/interaction/interactive_browser_test.h"
+#include "components/user_education/common/events.h"
 #include "components/user_education/common/help_bubble.h"
 #include "components/user_education/common/help_bubble_factory_registry.h"
 #include "components/user_education/common/help_bubble_params.h"
diff --git a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
index 1b89ebb..000df88 100644
--- a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
@@ -121,7 +121,8 @@
     entry2.launch_type = apps::FileHandler::LaunchType::kMultipleClients;
     web_app_info->file_handlers.push_back(std::move(entry2));
 
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     provider()->scheduler().InstallFromInfoWithParams(
         std::move(web_app_info), /*overwrite_existing_manifest_fields=*/false,
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
@@ -130,13 +131,13 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      app_id_ = AppId();
+      app_id_ = webapps::AppId();
       return;
     }
 
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    app_id_ = result.Get<AppId>();
+    app_id_ = result.Get<webapps::AppId>();
 
     // Setting the user display mode is necessary because
     // `test::InstallWebApp()` forces a kBrowser display mode; see
@@ -204,7 +205,7 @@
   }
 
  private:
-  AppId app_id_;
+  webapps::AppId app_id_;
   std::unique_ptr<OsIntegrationTestOverrideImpl::BlockingRegistration>
       override_registration_;
 };
diff --git a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.cc b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.cc
index 73738db0..e50c591 100644
--- a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.cc
+++ b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.cc
@@ -31,7 +31,7 @@
 FileHandlerLaunchDialogView::FileHandlerLaunchDialogView(
     const std::vector<base::FilePath>& file_paths,
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     chrome::WebAppLaunchAcceptanceCallback close_callback)
     : LaunchAppUserChoiceDialogView(profile, app_id, std::move(close_callback)),
       file_paths_(file_paths) {
@@ -169,7 +169,7 @@
 
 void ShowWebAppFileLaunchDialog(const std::vector<base::FilePath>& file_paths,
                                 Profile* profile,
-                                const web_app::AppId& app_id,
+                                const webapps::AppId& app_id,
                                 WebAppLaunchAcceptanceCallback close_callback) {
   auto view = std::make_unique<web_app::FileHandlerLaunchDialogView>(
       file_paths, profile, app_id, std::move(close_callback));
diff --git a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.h b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.h
index c27aefb0..ee8ea33 100644
--- a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.h
+++ b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_view.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "url/gurl.h"
 
 class Profile;
@@ -29,7 +30,7 @@
   FileHandlerLaunchDialogView(
       const std::vector<base::FilePath>& file_paths,
       Profile* profile,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       chrome::WebAppLaunchAcceptanceCallback close_callback);
 
   FileHandlerLaunchDialogView(const FileHandlerLaunchDialogView&) = delete;
diff --git a/chrome/browser/ui/views/web_apps/force_installed_preinstalled_deprecated_app_dialog_view.cc b/chrome/browser/ui/views/web_apps/force_installed_preinstalled_deprecated_app_dialog_view.cc
index 4cb32efa..a86336f 100644
--- a/chrome/browser/ui/views/web_apps/force_installed_preinstalled_deprecated_app_dialog_view.cc
+++ b/chrome/browser/ui/views/web_apps/force_installed_preinstalled_deprecated_app_dialog_view.cc
@@ -13,12 +13,12 @@
 #include "base/no_destructor.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/web_applications/extension_status_utils.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/constants.h"
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
index 24fb37b..6680e37 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
@@ -844,7 +844,7 @@
     WebAppFrameToolbarBrowserTest::SetUp();
   }
 
-  web_app::AppId InstallAndLaunchWCOWebApp(GURL start_url,
+  webapps::AppId InstallAndLaunchWCOWebApp(GURL start_url,
                                            std::u16string app_title) {
     std::vector<blink::mojom::DisplayMode> display_overrides;
     display_overrides.push_back(web_app::DisplayMode::kWindowControlsOverlay);
@@ -861,7 +861,7 @@
         browser(), std::move(web_app_info), start_url);
   }
 
-  web_app::AppId InstallAndLaunchWebApp() {
+  webapps::AppId InstallAndLaunchWebApp() {
     EXPECT_TRUE(https_server()->Start());
     return InstallAndLaunchWCOWebApp(
         helper()->LoadWindowControlsOverlayTestPageWithDataAndGetURL(
@@ -869,7 +869,7 @@
         u"A window-controls-overlay app");
   }
 
-  web_app::AppId InstallAndLaunchFullyDraggableWebApp() {
+  webapps::AppId InstallAndLaunchFullyDraggableWebApp() {
     EXPECT_TRUE(https_server()->Start());
     return InstallAndLaunchWCOWebApp(
         helper()->LoadWholeAppIsDraggableTestPageWithDataAndGetURL(
@@ -1448,7 +1448,7 @@
 // Regression test for https://crbug.com/1239443.
 IN_PROC_BROWSER_TEST_F(WebAppFrameToolbarBrowserTest_WindowControlsOverlay,
                        OpenWithOverlayEnabled) {
-  web_app::AppId app_id = InstallAndLaunchWebApp();
+  webapps::AppId app_id = InstallAndLaunchWebApp();
   base::test::TestFuture<void> future;
   helper()
       ->browser_view()
@@ -1531,7 +1531,7 @@
 // Regression test for https://crbug.com/1351566.
 IN_PROC_BROWSER_TEST_F(WebAppFrameToolbarBrowserTest_WindowControlsOverlay,
                        ExtensionsIconVisibility) {
-  web_app::AppId app_id = InstallAndLaunchWebApp();
+  webapps::AppId app_id = InstallAndLaunchWebApp();
   ToggleWindowControlsOverlayAndWait();
 
   // There should be no visible Extensions icon.
@@ -1567,7 +1567,7 @@
 // app's window.
 IN_PROC_BROWSER_TEST_F(WebAppFrameToolbarBrowserTest_WindowControlsOverlay,
                        DownloadIconVisibilityForAppDownload) {
-  web_app::AppId app_id = InstallAndLaunchWebApp();
+  webapps::AppId app_id = InstallAndLaunchWebApp();
   ToggleWindowControlsOverlayAndWait();
 
   Browser* non_app_browser = CreateBrowser(profile());
@@ -1605,7 +1605,7 @@
 // app's window.
 IN_PROC_BROWSER_TEST_F(WebAppFrameToolbarBrowserTest_WindowControlsOverlay,
                        DownloadIconVisibilityForRegularDownload) {
-  web_app::AppId app_id = InstallAndLaunchWebApp();
+  webapps::AppId app_id = InstallAndLaunchWebApp();
   ToggleWindowControlsOverlayAndWait();
 
   Browser* non_app_browser = CreateBrowser(profile());
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.cc
index e3faf124..4751389 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.cc
@@ -35,7 +35,7 @@
 
 WebAppFrameToolbarTestHelper::~WebAppFrameToolbarTestHelper() = default;
 
-web_app::AppId WebAppFrameToolbarTestHelper::InstallAndLaunchWebApp(
+webapps::AppId WebAppFrameToolbarTestHelper::InstallAndLaunchWebApp(
     Browser* browser,
     const GURL& start_url) {
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
@@ -46,7 +46,7 @@
   web_app_info->user_display_mode =
       web_app::mojom::UserDisplayMode::kStandalone;
 
-  web_app::AppId app_id =
+  webapps::AppId app_id =
       web_app::test::InstallWebApp(browser->profile(), std::move(web_app_info));
   content::TestNavigationObserver navigation_observer(start_url);
   navigation_observer.StartWatchingNewWebContents();
@@ -65,11 +65,11 @@
   return app_id;
 }
 
-web_app::AppId WebAppFrameToolbarTestHelper::InstallAndLaunchCustomWebApp(
+webapps::AppId WebAppFrameToolbarTestHelper::InstallAndLaunchCustomWebApp(
     Browser* browser,
     std::unique_ptr<web_app::WebAppInstallInfo> web_app_info,
     const GURL& start_url) {
-  web_app::AppId app_id =
+  webapps::AppId app_id =
       web_app::test::InstallWebApp(browser->profile(), std::move(web_app_info));
   content::TestNavigationObserver navigation_observer(start_url);
   navigation_observer.StartWatchingNewWebContents();
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h
index ae157fd4..3bc4385 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h
@@ -10,6 +10,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 
 class Browser;
@@ -43,9 +44,9 @@
       delete;
   ~WebAppFrameToolbarTestHelper();
 
-  web_app::AppId InstallAndLaunchWebApp(Browser* browser,
+  webapps::AppId InstallAndLaunchWebApp(Browser* browser,
                                         const GURL& start_url);
-  web_app::AppId InstallAndLaunchCustomWebApp(
+  webapps::AppId InstallAndLaunchCustomWebApp(
       Browser* browser,
       std::unique_ptr<web_app::WebAppInstallInfo> web_app_info,
       const GURL& start_url);
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_mixin.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_mixin.cc
index ef649376..1be1852e 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_mixin.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_mixin.cc
@@ -34,7 +34,7 @@
   web_app_info->user_display_mode =
       web_app::mojom::UserDisplayMode::kStandalone;
 
-  web_app::AppId app_id =
+  webapps::AppId app_id =
       web_app::test::InstallWebApp(browser->profile(), std::move(web_app_info));
   content::TestNavigationObserver navigation_observer(start_url);
   navigation_observer.StartWatchingNewWebContents();
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc
index 4a6eb16..1ecd227 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc
@@ -25,7 +25,7 @@
     web_app_info->start_url = GURL("https://example.org");
     web_app_info->display_mode = display_mode;
     web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
-    AppId app_id = InstallWebApp(std::move(web_app_info));
+    webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
     Browser* browser = LaunchWebAppBrowser(app_id);
     return BrowserView::GetBrowserViewForBrowser(browser);
   }
diff --git a/chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.cc b/chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.cc
index 9cc22196..ec9bcb3 100644
--- a/chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.cc
+++ b/chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.cc
@@ -44,7 +44,7 @@
 
 LaunchAppUserChoiceDialogView::LaunchAppUserChoiceDialogView(
     Profile* profile,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     chrome::WebAppLaunchAcceptanceCallback close_callback)
     : profile_(profile),
       app_id_(app_id),
diff --git a/chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.h b/chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.h
index 07e2066..677017a 100644
--- a/chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.h
+++ b/chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "ui/views/window/dialog_delegate.h"
 
 class Profile;
@@ -36,7 +37,7 @@
 
   LaunchAppUserChoiceDialogView(
       Profile* profile,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       chrome::WebAppLaunchAcceptanceCallback close_callback);
 
   LaunchAppUserChoiceDialogView(const LaunchAppUserChoiceDialogView&) = delete;
@@ -54,10 +55,10 @@
   virtual std::u16string GetRememberChoiceString() = 0;
 
   Profile* profile() { return profile_; }
-  const AppId& app_id() { return app_id_; }
+  const webapps::AppId& app_id() { return app_id_; }
 
  private:
-  const AppId& GetSelectedAppId() const;
+  const webapps::AppId& GetSelectedAppId() const;
   void OnAccepted();
   void OnCanceled();
   void OnClosed();
@@ -68,7 +69,7 @@
   void RunCloseCallback(bool allowed, bool remember_user_choice);
 
   const raw_ptr<Profile> profile_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   raw_ptr<views::Checkbox> remember_selection_checkbox_;
   raw_ptr<views::ImageView> icon_image_view_;
   chrome::WebAppLaunchAcceptanceCallback close_callback_;
diff --git a/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_browsertest.cc
index 5f58569..a02c4cb 100644
--- a/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_browsertest.cc
@@ -27,7 +27,7 @@
 
 namespace {
 
-AppId InstallTestWebApp(Profile* profile) {
+webapps::AppId InstallTestWebApp(Profile* profile) {
   const GURL example_url = GURL("http://example.org/");
   auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->title = u"Test app";
@@ -51,7 +51,7 @@
     views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                          "ProtocolHandlerLaunchDialogView");
     GURL protocol_url("web+test://test");
-    AppId test_app_id = InstallTestWebApp(browser()->profile());
+    webapps::AppId test_app_id = InstallTestWebApp(browser()->profile());
 
     base::RunLoop run_loop;
     auto dialog_finished = base::BindLambdaForTesting(
@@ -122,7 +122,7 @@
     views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                          "ProtocolHandlerLaunchDialogView");
     GURL protocol_url("web+test://test");
-    AppId test_app_id = InstallTestWebApp(browser()->profile());
+    webapps::AppId test_app_id = InstallTestWebApp(browser()->profile());
     chrome::ShowWebAppProtocolLaunchDialog(protocol_url, browser()->profile(),
                                            test_app_id, base::DoNothing());
     waiter.WaitIfNeededAndGet()->CloseWithReason(
diff --git a/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.cc b/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.cc
index fd20d8a..2872b649 100644
--- a/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.cc
+++ b/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.cc
@@ -21,7 +21,7 @@
 ProtocolHandlerLaunchDialogView::ProtocolHandlerLaunchDialogView(
     GURL url,
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     chrome::WebAppLaunchAcceptanceCallback close_callback)
     : LaunchAppUserChoiceDialogView(profile, app_id, std::move(close_callback)),
       url_(std::move(url)) {
@@ -75,7 +75,7 @@
 void ShowWebAppProtocolLaunchDialog(
     const GURL& url,
     Profile* profile,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     WebAppLaunchAcceptanceCallback close_callback) {
   auto view = std::make_unique<web_app::ProtocolHandlerLaunchDialogView>(
       url, profile, app_id, std::move(close_callback));
diff --git a/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.h b/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.h
index a924c87..923fca1 100644
--- a/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.h
+++ b/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/views/web_apps/launch_app_user_choice_dialog_view.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "ui/views/window/dialog_delegate.h"
 #include "url/gurl.h"
 
@@ -29,7 +30,7 @@
   ProtocolHandlerLaunchDialogView(
       GURL url,
       Profile* profile,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       chrome::WebAppLaunchAcceptanceCallback close_callback);
 
   ProtocolHandlerLaunchDialogView(const ProtocolHandlerLaunchDialogView&) =
diff --git a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc
index 0587e0bc..af9159ed 100644
--- a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc
+++ b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc
@@ -236,7 +236,7 @@
     base::RecordAction(base::UserMetricsAction("WebAppInstallCancelled"));
 
     if (iph_state_ == chrome::PwaInProductHelpState::kShown) {
-      web_app::AppId app_id =
+      webapps::AppId app_id =
           web_app::GenerateAppIdFromManifestId(web_app_info_->manifest_id);
       web_app::RecordInstallIphIgnored(prefs_, app_id, base::Time::Now());
 
@@ -268,7 +268,7 @@
           ? web_app::mojom::UserDisplayMode::kTabbed
           : web_app::mojom::UserDisplayMode::kStandalone;
 
-  web_app::AppId app_id =
+  webapps::AppId app_id =
       web_app::GenerateAppIdFromManifestId(web_app_info_->manifest_id);
 
 #if BUILDFLAG(IS_CHROMEOS)
@@ -339,7 +339,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS)
   if (base::FeatureList::IsEnabled(metrics::structured::kAppDiscoveryLogging)) {
-    web_app::AppId app_id =
+    webapps::AppId app_id =
         web_app::GenerateAppIdFromManifestId(web_app_info->manifest_id);
     cros_events::AppDiscovery_Browser_AppInstallDialogShown()
         .SetAppId(app_id)
diff --git a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc
index 32807a7..7f841ea61 100644
--- a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_prefs_utils.h"
 #include "chrome/common/chrome_features.h"
@@ -28,6 +27,7 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/webapps/browser/installable/ml_install_operation_tracker.h"
 #include "components/webapps/browser/installable/ml_installability_promoter.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "ui/views/test/widget_test.h"
 #include "ui/views/widget/any_widget_observer.h"
@@ -77,7 +77,7 @@
   app_info->title = u"Test app";
   app_info->start_url = GURL("https://example.com");
   Profile* profile = browser()->profile();
-  AppId app_id = test::InstallWebApp(profile, std::move(app_info));
+  webapps::AppId app_id = test::InstallWebApp(profile, std::move(app_info));
   Browser* browser = ::web_app::LaunchWebAppBrowser(profile, app_id);
 
   app_info = GetAppInfo();
@@ -151,7 +151,8 @@
                                       ->GetActiveWebContents()
                                       ->GetBrowserContext())
           ->GetPrefs();
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   EXPECT_EQ(GetIntWebAppPref(pref_service, app_id, kIphIgnoreCount).value(), 1);
   EXPECT_TRUE(
       GetTimeWebAppPref(pref_service, app_id, kIphLastIgnoreTime).has_value());
@@ -167,7 +168,8 @@
                        AcceptDialogResetIphCounters) {
   auto app_info = GetAppInfo();
   GURL start_url = app_info->start_url;
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   PrefService* pref_service =
       Profile::FromBrowserContext(browser()
                                       ->tab_strip_model()
diff --git a/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc b/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc
index cedf546..3bcb430 100644
--- a/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc
@@ -32,7 +32,7 @@
   void SetUpOnMainThread() override {
     auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
     web_app_info->start_url = GURL("https://test.org");
-    web_app::AppId app_id = InstallWebApp(std::move(web_app_info));
+    webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
 
     Browser* browser = LaunchWebAppBrowser(app_id);
     browser_view_ = BrowserView::GetBrowserViewForBrowser(browser);
diff --git a/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc
index 389fc7ee..ed45c4a 100644
--- a/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_detailed_install_dialog.cc
@@ -434,7 +434,7 @@
 void WebAppDetailedInstallDialogDelegate::OnAccept() {
   base::RecordAction(base::UserMetricsAction("WebAppDetailedInstallAccepted"));
   if (iph_state_ == chrome::PwaInProductHelpState::kShown) {
-    web_app::AppId app_id =
+    webapps::AppId app_id =
         web_app::GenerateAppIdFromManifestId(install_info_->manifest_id);
     web_app::RecordInstallIphInstalled(prefs_, app_id);
     tracker_->NotifyEvent(feature_engagement::events::kDesktopPwaInstalled);
@@ -500,7 +500,7 @@
   base::RecordAction(base::UserMetricsAction("WebAppDetailedInstallCancelled"));
 
   if (iph_state_ == chrome::PwaInProductHelpState::kShown && install_info_) {
-    web_app::AppId app_id =
+    webapps::AppId app_id =
         web_app::GenerateAppIdFromManifestId(install_info_->manifest_id);
     web_app::RecordInstallIphIgnored(prefs_, app_id, base::Time::Now());
   }
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index da7a022..a1c5b11 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -103,7 +103,6 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -122,6 +121,7 @@
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
@@ -529,7 +529,8 @@
   base::RunLoop run_loop_;
 };
 
-Browser* GetAppBrowserForAppId(const Profile* profile, const AppId& app_id) {
+Browser* GetAppBrowserForAppId(const Profile* profile,
+                               const webapps::AppId& app_id) {
   const BrowserList* browser_list = BrowserList::GetInstance();
   for (auto it = browser_list->begin_browsers_ordered_by_activation();
        it != browser_list->end_browsers_ordered_by_activation(); ++it) {
@@ -544,17 +545,18 @@
   return nullptr;
 }
 
-bool AreAppBrowsersOpen(const Profile* profile, const AppId& app_id) {
+bool AreAppBrowsersOpen(const Profile* profile, const webapps::AppId& app_id) {
   return GetAppBrowserForAppId(profile, app_id) != nullptr;
 }
 
-content::WebContents* GetAnyWebContentsForAppId(const AppId& app_id) {
+content::WebContents* GetAnyWebContentsForAppId(const webapps::AppId& app_id) {
   auto* browser_list = BrowserList::GetInstance();
   for (Browser* browser : *browser_list) {
     for (int i = 0; i < browser->tab_strip_model()->GetTabCount(); i++) {
       content::WebContents* web_contents =
           browser->tab_strip_model()->GetWebContentsAt(i);
-      const AppId* web_contents_id = WebAppTabHelper::GetAppId(web_contents);
+      const webapps::AppId* web_contents_id =
+          WebAppTabHelper::GetAppId(web_contents);
       if (web_contents_id && *web_contents_id == app_id) {
         return web_contents;
       }
@@ -568,7 +570,7 @@
  public:
   explicit UninstallCompleteWaiter(
       Profile* profile,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       apps::Readiness readiness = apps::Readiness::kUninstalledByUser)
       : profile_(profile),
         app_id_(app_id),
@@ -596,7 +598,7 @@
 
   // WebAppInstallManagerObserver
   void OnWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override {
     if (app_id != app_id_) {
       return;
@@ -623,7 +625,7 @@
 
  private:
   raw_ptr<const Profile> profile_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   bool uninstall_complete_ = false;
   base::RunLoop run_loop_;
   apps::AppReadinessWaiter app_unregistration_waiter_;
@@ -669,7 +671,7 @@
 
 absl::optional<AppState> GetStateForAppId(StateSnapshot* state_snapshot,
                                           Profile* profile,
-                                          const web_app::AppId& id) {
+                                          const webapps::AppId& id) {
   absl::optional<ProfileState> profile_state =
       GetStateForProfile(state_snapshot, profile);
   if (!profile_state) {
@@ -742,7 +744,7 @@
     Browser* browser_ptr,
     base::flat_map<content::WebContents*, TabState> tab_state,
     content::WebContents* active_web_contents,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool launch_icon_visible)
     : browser(browser_ptr),
       tabs(std::move(tab_state)),
@@ -757,7 +759,7 @@
          launch_icon_shown == other.launch_icon_shown;
 }
 
-AppState::AppState(web_app::AppId app_id,
+AppState::AppState(webapps::AppId app_id,
                    std::string app_name,
                    GURL app_scope,
                    apps::RunOnOsLoginMode run_on_os_login_mode,
@@ -790,7 +792,7 @@
 }
 
 ProfileState::ProfileState(base::flat_map<Browser*, BrowserState> browser_state,
-                           base::flat_map<web_app::AppId, AppState> app_state)
+                           base::flat_map<webapps::AppId, AppState> app_state)
     : browsers(std::move(browser_state)), apps(std::move(app_state)) {}
 ProfileState::~ProfileState() = default;
 ProfileState::ProfileState(const ProfileState&) = default;
@@ -907,7 +909,8 @@
     if (!provider) {
       continue;
     }
-    std::vector<AppId> app_ids = provider->registrar_unsafe().GetAppIds();
+    std::vector<webapps::AppId> app_ids =
+        provider->registrar_unsafe().GetAppIds();
     for (auto& app_id : app_ids) {
       LOG(INFO) << "TearDownOnMainThread: Uninstalling " << app_id << ".";
       const WebApp* app = provider->registrar_unsafe().GetAppById(app_id);
@@ -1003,7 +1006,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   const WebApp* web_app = provider()->registrar_unsafe().GetAppById(app_id);
   // If the update resulted in an uninstall, then no need to wait.
   if (web_app) {
@@ -1084,7 +1087,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 #if !BUILDFLAG(IS_CHROMEOS)
@@ -1099,7 +1102,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 #if !BUILDFLAG(IS_CHROMEOS)
@@ -1119,7 +1122,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 #if !BUILDFLAG(IS_CHROMEOS)
@@ -1134,7 +1137,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 #if !BUILDFLAG(IS_CHROMEOS)
@@ -1252,7 +1255,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
   content::TestWebUI test_web_ui;
@@ -1282,10 +1285,10 @@
           GetCurrentTab(browser()));
   app_banner_manager->WaitForInstallableCheck();
 
-  web_app::AppId app_id;
+  webapps::AppId app_id;
   base::RunLoop run_loop;
   web_app::SetInstalledCallbackForTesting(base::BindLambdaForTesting(
-      [&app_id, &run_loop](const web_app::AppId& installed_app_id,
+      [&app_id, &run_loop](const webapps::AppId& installed_app_id,
                            webapps::InstallResultCode code) {
         app_id = installed_app_id;
         run_loop.Quit();
@@ -1502,7 +1505,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                        "FileHandlerLaunchDialogView");
   FileHandlerLaunchDialogView::SetDefaultRememberSelectionForTesting(
@@ -1556,7 +1559,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   base::RunLoop run_loop;
   BrowserAddedWaiter browser_added_waiter;
 #if BUILDFLAG(IS_MAC)
@@ -1589,7 +1592,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -1644,7 +1647,7 @@
   }
   base::AutoReset<bool> intent_picker_bubble_scope =
       IntentPickerBubbleView::SetAutoAcceptIntentPickerBubbleForTesting();
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -1679,7 +1682,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -1705,7 +1708,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -1771,7 +1774,7 @@
     return;
   }
 
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -1848,7 +1851,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -1894,7 +1897,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
   content::TestWebUI test_web_ui;
@@ -1928,7 +1931,7 @@
     return;
   }
   base::ScopedAllowBlockingForTesting allow_blocking;
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   std::string app_name = provider()->registrar_unsafe().GetAppShortName(app_id);
   if (app_name.empty()) {
     app_name = GetSiteConfiguration(site).app_name;
@@ -2199,7 +2202,7 @@
     return;
   }
   ASSERT_TRUE(IsBrowserOpen(app_browser())) << "No current app browser.";
-  AppId app_id = app_browser()->app_controller()->app_id();
+  webapps::AppId app_id = app_browser()->app_controller()->app_id();
   GURL app_url = GetCurrentTab(app_browser())->GetURL();
   ASSERT_TRUE(AppBrowserController::IsForWebApp(app_browser(), app_id));
   CHECK(chrome::ExecuteCommand(app_browser_, IDC_OPEN_IN_CHROME));
@@ -2214,7 +2217,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 #if BUILDFLAG(IS_CHROMEOS)
@@ -2241,7 +2244,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 #if BUILDFLAG(IS_CHROMEOS)
@@ -2262,7 +2265,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 #if BUILDFLAG(IS_CHROMEOS)
@@ -2289,7 +2292,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
   ;
@@ -2369,7 +2372,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -2417,7 +2420,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -2453,7 +2456,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -2497,7 +2500,7 @@
       profile(), policy_app->id, apps::Readiness::kUninstalledByNonUser);
   WebAppInstallManagerObserverAdapter observer(profile());
   observer.SetWebAppUninstalledDelegate(
-      base::BindLambdaForTesting([&](const AppId& app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& app_id) {
         if (policy_app->id == app_id) {
           run_loop.Quit();
         }
@@ -2505,7 +2508,7 @@
   // If there are still install sources, the app might not be fully uninstalled,
   // so this will listen for the removal of the policy install source.
   observer.SetWebAppSourceRemovedDelegate(
-      base::BindLambdaForTesting([&](const AppId& app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& app_id) {
         if (policy_app->id == app_id) {
           run_loop.Quit();
         }
@@ -2535,7 +2538,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
 
@@ -2565,7 +2568,7 @@
     return;
   }
   base::ScopedAllowBlockingForTesting allow_blocking;
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   std::string app_name = GetSiteConfiguration(site).app_name;
   base::FilePath app_path = GetShortcutPath(
       override_registration_->test_override->chrome_apps_folder(), app_name,
@@ -2609,7 +2612,7 @@
   if (!BeforeStateChangeAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   std::string app_name = GetSiteConfiguration(site).app_name;
   base::FilePath app_path = GetShortcutPath(
       override_registration_->test_override->chrome_apps_folder(), app_name,
@@ -2716,7 +2719,7 @@
   test_web_ui.set_web_contents(web_contents);
   auto app_home_page_handler = GetTestAppHomePageHandler(&test_web_ui);
   app_home::mojom::AppInfoPtr expected_app;
-  const AppId app_id = GetAppIdBySiteMode(site);
+  const webapps::AppId app_id = GetAppIdBySiteMode(site);
   expected_app = app_home_page_handler.GetApp(app_id);
 
   EXPECT_NE(expected_app, app_home::mojom::AppInfoPtr());
@@ -2742,7 +2745,7 @@
   test_web_ui.set_web_contents(web_contents);
   auto app_home_page_handler = GetTestAppHomePageHandler(&test_web_ui);
   app_home::mojom::AppInfoPtr expected_app;
-  const AppId app_id = GetAppIdBySiteMode(site);
+  const webapps::AppId app_id = GetAppIdBySiteMode(site);
   expected_app = app_home_page_handler.GetApp(app_id);
 
   EXPECT_NE(expected_app, app_home::mojom::AppInfoPtr());
@@ -2768,7 +2771,7 @@
   test_web_ui.set_web_contents(web_contents);
   auto app_home_page_handler = GetTestAppHomePageHandler(&test_web_ui);
   app_home::mojom::AppInfoPtr expected_app;
-  const AppId app_id = GetAppIdBySiteMode(site);
+  const webapps::AppId app_id = GetAppIdBySiteMode(site);
   expected_app = app_home_page_handler.GetApp(app_id);
 
   EXPECT_NE(expected_app, app_home::mojom::AppInfoPtr());
@@ -2851,7 +2854,7 @@
   if (!BeforeStateCheckAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
   ;
@@ -2888,7 +2891,7 @@
   test_web_ui.set_web_contents(web_contents);
   auto app_home_page_handler = GetTestAppHomePageHandler(&test_web_ui);
   app_home::mojom::AppInfoPtr expected_app;
-  const AppId app_id = GetAppIdBySiteMode(site);
+  const webapps::AppId app_id = GetAppIdBySiteMode(site);
   expected_app = app_home_page_handler.GetApp(app_id);
 
   // An empty app received means that the app does not exist in chrome://apps.
@@ -2924,7 +2927,7 @@
                                  profile(), site);
   }
   std::string app_name;
-  AppId app_id;
+  webapps::AppId app_id;
   // If app_state is still nullptr, the site is manually mapped to get an
   // app_name and app_id remains empty.
   if (!app_state) {
@@ -3074,7 +3077,7 @@
 
       static const std::string kFooHandler = "foo_handler.html";
       static const std::string kBarHandler = "bar_handler.html";
-      AppId app_id = *WebAppTabHelper::GetAppId(web_contents);
+      webapps::AppId app_id = *WebAppTabHelper::GetAppId(web_contents);
       std::string url_str = web_contents->GetURL().spec();
 
       if (app_id != GetAppIdBySiteMode(site) ||
@@ -3279,7 +3282,7 @@
   if (!BeforeStateCheckAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   std::string app_name = GetSiteConfiguration(site).app_name;
   std::string file_extension_str = "." + GetFileExtension(file_extension);
   ASSERT_TRUE(override_registration_->test_override->IsFileExtensionHandled(
@@ -3295,7 +3298,7 @@
   if (!BeforeStateCheckAction(__FUNCTION__)) {
     return;
   }
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   std::string app_name = GetSiteConfiguration(site).app_name;
   std::string file_extension_str = "." + GetFileExtension(file_extension);
   ASSERT_FALSE(override_registration_->test_override->IsFileExtensionHandled(
@@ -3444,7 +3447,7 @@
 
   int before_state_app_window_count = 0;
   int after_state_app_window_count = 0;
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   for (const auto& browser_pair : before_action_profile->browsers) {
     if (AppBrowserController::IsForWebApp(browser_pair.first, app_id)) {
       before_state_app_window_count++;
@@ -3713,7 +3716,7 @@
     for (int i = 0; i < browser->tab_strip_model()->GetTabCount(); i++) {
       content::WebContents* web_contents =
           browser->tab_strip_model()->GetWebContentsAt(i);
-      const AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
+      const webapps::AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
       if (!app_id) {
         continue;
       }
@@ -3728,7 +3731,8 @@
   AfterStateCheckAction();
 }
 
-void WebAppIntegrationTestDriver::OnWebAppManifestUpdated(const AppId& app_id) {
+void WebAppIntegrationTestDriver::OnWebAppManifestUpdated(
+    const webapps::AppId& app_id) {
   LOG(INFO) << "Manifest update received for " << app_id << ".";
   CHECK(!delegate_->IsSyncTest())
       << "Manifest update waiting only supported on non-sync tests.";
@@ -3750,7 +3754,7 @@
 }
 
 void WebAppIntegrationTestDriver::OnWebAppUninstalled(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   if (!waiting_for_update_id_.has_value()) {
     return;
@@ -3796,13 +3800,14 @@
   CHECK(executing_action_level_ > 0);
   --executing_action_level_;
 #if BUILDFLAG(IS_MAC)
-  std::map<AppId, size_t> open_browsers_per_app;
+  std::map<webapps::AppId, size_t> open_browsers_per_app;
   for (auto* profile : GetAllProfiles()) {
     auto* provider = GetProviderForProfile(profile);
     if (!provider) {
       continue;
     }
-    std::vector<AppId> app_ids = provider->registrar_unsafe().GetAppIds();
+    std::vector<webapps::AppId> app_ids =
+        provider->registrar_unsafe().GetAppIds();
     for (auto& app_id : app_ids) {
       // Wait for any shims to finish connecting.
       auto* app_shim_manager = apps::AppShimManager::Get();
@@ -3913,7 +3918,7 @@
   // If there are any apps that have no app windows, then wait for the
   // ui_manager to post the task and schedule the manifest update finalize
   // command.
-  for (const AppId& app_id :
+  for (const webapps::AppId& app_id :
        manifest_update_manager.GetAppsPendingWindowsClosingForTesting()) {
     if (provider()->ui_manager().GetNumWindowsForApp(app_id) == 0) {
       base::RunLoop().RunUntilIdle();
@@ -3923,7 +3928,7 @@
   command_manager.AwaitAllCommandsCompleteForTesting();
 }
 
-AppId WebAppIntegrationTestDriver::GetAppIdBySiteMode(Site site) {
+webapps::AppId WebAppIntegrationTestDriver::GetAppIdBySiteMode(Site site) {
   auto site_config = GetSiteConfiguration(site);
   std::string manifest_id = site_config.relative_manifest_id;
   auto relative_url = site_config.relative_url;
@@ -3948,7 +3953,7 @@
     return absl::nullopt;
   }
 
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   auto it = profile_state->apps.find(app_id);
   return it == profile_state->apps.end()
              ? absl::nullopt
@@ -3992,7 +3997,7 @@
 
         launch_icon_shown = intent_picker_view()->GetVisible();
       }
-      AppId app_id;
+      webapps::AppId app_id;
       if (AppBrowserController::IsWebApp(browser)) {
         app_id = browser->app_controller()->app_id();
       }
@@ -4003,7 +4008,7 @@
     }
 
     WebAppProvider* provider = GetProviderForProfile(profile);
-    base::flat_map<AppId, AppState> app_state;
+    base::flat_map<webapps::AppId, AppState> app_state;
     if (provider) {
       WebAppRegistrar& registrar = provider->registrar_unsafe();
       auto app_ids = registrar.GetAppIds();
@@ -4073,7 +4078,7 @@
 base::FilePath WebAppIntegrationTestDriver::GetShortcutPath(
     base::FilePath shortcut_dir,
     const std::string& app_name,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
   return override_registration_->test_override->GetShortcutPath(
       profile(), shortcut_dir, app_id, app_name);
@@ -4126,14 +4131,15 @@
   }
 }
 
-void WebAppIntegrationTestDriver::UninstallPolicyAppById(Profile* profile,
-                                                         const AppId& id) {
+void WebAppIntegrationTestDriver::UninstallPolicyAppById(
+    Profile* profile,
+    const webapps::AppId& id) {
   base::RunLoop run_loop;
   apps::AppReadinessWaiter app_registration_waiter(
       profile, id, apps::Readiness::kUninstalledByNonUser);
   WebAppInstallManagerObserverAdapter observer(profile);
   observer.SetWebAppUninstalledDelegate(
-      base::BindLambdaForTesting([&](const AppId& app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& app_id) {
         if (id == app_id) {
           run_loop.Quit();
         }
@@ -4141,7 +4147,7 @@
   // If there are still install sources, the app might not be fully uninstalled,
   // so this will listen for the removal of the policy install source.
   observer.SetWebAppSourceRemovedDelegate(
-      base::BindLambdaForTesting([&](const AppId& app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& app_id) {
         if (id == app_id) {
           run_loop.Quit();
         }
@@ -4264,7 +4270,7 @@
 bool WebAppIntegrationTestDriver::IsShortcutAndIconCreated(
     Profile* profile,
     const std::string& name,
-    const AppId& id) {
+    const webapps::AppId& id) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   bool is_shortcut_and_icon_correct = false;
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
@@ -4281,7 +4287,7 @@
 
 bool WebAppIntegrationTestDriver::DoIconColorsMatch(Profile* profile,
                                                     const std::string& name,
-                                                    const AppId& id) {
+                                                    const webapps::AppId& id) {
   bool do_icon_colors_match = false;
 #if BUILDFLAG(IS_WIN)
   SkColor expected_icon_pixel_color =
@@ -4334,7 +4340,7 @@
 void WebAppIntegrationTestDriver::SetFileHandlingEnabled(Site site,
                                                          bool enabled) {
 #if !BUILDFLAG(IS_CHROMEOS)
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar_unsafe().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
   auto app_management_page_handler = CreateAppManagementPageHandler(profile());
@@ -4344,7 +4350,7 @@
 
 void WebAppIntegrationTestDriver::LaunchFile(Site site,
                                              FilesOptions files_options) {
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   std::vector<base::FilePath> file_paths = GetTestFilePaths(files_options);
 #if BUILDFLAG(IS_MAC)
   std::vector<GURL> urls;
@@ -4369,7 +4375,7 @@
 }
 
 void WebAppIntegrationTestDriver::LaunchAppStartupBrowserCreator(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   command_line.AppendSwitchASCII(switches::kAppId, app_id);
   command_line.AppendSwitchASCII(switches::kTestType, "browser");
@@ -4463,7 +4469,7 @@
     Site site,
     const std::vector<GURL>& urls,
     bool wait_for_complete_launch) {
-  AppId app_id = GetAppIdBySiteMode(site);
+  webapps::AppId app_id = GetAppIdBySiteMode(site);
   std::string app_name = GetSiteConfiguration(site).app_name;
   base::FilePath app_path = GetShortcutPath(
       override_registration_->test_override->chrome_apps_folder(), app_name,
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
index a181015a..f95c7715 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
@@ -30,6 +30,7 @@
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/run_on_os_login_types.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/views/widget/any_widget_observer.h"
@@ -164,7 +165,7 @@
   BrowserState(Browser* browser_ptr,
                base::flat_map<content::WebContents*, TabState> tab_state,
                content::WebContents* active_web_contents,
-               const AppId& app_id,
+               const webapps::AppId& app_id,
                bool launch_icon_visible);
   ~BrowserState();
   BrowserState(const BrowserState&);
@@ -178,12 +179,12 @@
   // #union
   RAW_PTR_EXCLUSION content::WebContents* active_tab;
   // If this isn't an app browser, `app_id` is empty.
-  AppId app_id;
+  webapps::AppId app_id;
   bool launch_icon_shown;
 };
 
 struct AppState {
-  AppState(AppId app_id,
+  AppState(webapps::AppId app_id,
            std::string app_name,
            GURL app_scope,
            apps::RunOnOsLoginMode run_on_os_login_mode,
@@ -196,7 +197,7 @@
   AppState(const AppState&);
   bool operator==(const AppState& other) const;
 
-  AppId id;
+  webapps::AppId id;
   std::string name;
   GURL scope;
   apps::RunOnOsLoginMode run_on_os_login_mode;
@@ -209,13 +210,13 @@
 
 struct ProfileState {
   ProfileState(base::flat_map<Browser*, BrowserState> browser_state,
-               base::flat_map<AppId, AppState> app_state);
+               base::flat_map<webapps::AppId, AppState> app_state);
   ~ProfileState();
   ProfileState(const ProfileState&);
   bool operator==(const ProfileState& other) const;
 
   base::flat_map<Browser*, BrowserState> browsers;
-  base::flat_map<AppId, AppState> apps;
+  base::flat_map<webapps::AppId, AppState> apps;
 };
 
 struct StateSnapshot {
@@ -403,9 +404,9 @@
 
  protected:
   // WebAppInstallManagerObserver:
-  void OnWebAppManifestUpdated(const AppId& app_id) override;
+  void OnWebAppManifestUpdated(const webapps::AppId& app_id) override;
   void OnWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
 
  private:
@@ -422,7 +423,7 @@
 
   void AwaitManifestSystemIdle();
 
-  AppId GetAppIdBySiteMode(Site site);
+  webapps::AppId GetAppIdBySiteMode(Site site);
   GURL GetUrlForSite(Site site);
   absl::optional<AppState> GetAppBySiteMode(StateSnapshot* state_snapshot,
                                             Profile* profile,
@@ -438,14 +439,14 @@
   GURL GetInScopeURL(Site site);
   base::FilePath GetShortcutPath(base::FilePath shortcut_dir,
                                  const std::string& app_name,
-                                 const AppId& app_id);
+                                 const webapps::AppId& app_id);
   void InstallPolicyAppInternal(Site site,
                                 base::Value default_launch_container,
                                 const bool create_shortcut,
                                 const bool install_as_shortcut);
   void ApplyRunOnOsLoginPolicy(Site site, const char* policy);
 
-  void UninstallPolicyAppById(Profile* profile, const AppId& id);
+  void UninstallPolicyAppById(Profile* profile, const webapps::AppId& id);
   void ForceUpdateManifestContents(Site site,
                                    const GURL& app_url_with_manifest_param);
   void MaybeNavigateTabbedBrowserInScope(Site site);
@@ -459,17 +460,17 @@
 
   bool IsShortcutAndIconCreated(Profile* profile,
                                 const std::string& name,
-                                const AppId& id);
+                                const webapps::AppId& id);
 
   bool DoIconColorsMatch(Profile* profile,
                          const std::string& name,
-                         const AppId& id);
+                         const webapps::AppId& id);
 
   bool IsFileHandledBySite(Site site, FileExtension file_extension);
   void SetFileHandlingEnabled(Site site, bool enabled);
   void LaunchFile(Site site, FilesOptions files_options);
 
-  void LaunchAppStartupBrowserCreator(const AppId& app_id);
+  void LaunchAppStartupBrowserCreator(const webapps::AppId& app_id);
 #if BUILDFLAG(IS_MAC)
   bool LaunchFromAppShim(Site site,
                          const std::vector<GURL>& urls,
@@ -505,12 +506,12 @@
 
   base::test::ScopedFeatureList scoped_feature_list_;
 
-  base::flat_set<AppId> previous_manifest_updates_;
+  base::flat_set<webapps::AppId> previous_manifest_updates_;
 
   // |waiting_for_update_*| variables are either all populated or all not
   // populated. These signify that the test is currently waiting for the
   // given |waiting_for_update_id_| to receive an update before continuing.
-  absl::optional<AppId> waiting_for_update_id_;
+  absl::optional<webapps::AppId> waiting_for_update_id_;
   std::unique_ptr<base::RunLoop> waiting_for_update_run_loop_;
 
   raw_ptr<TestDelegate> delegate_;
@@ -527,7 +528,7 @@
   int executing_action_level_ = 0;
 
   raw_ptr<Profile, AcrossTasksDanglingUntriaged> active_profile_ = nullptr;
-  AppId active_app_id_;
+  webapps::AppId active_app_id_;
   raw_ptr<Browser, AcrossTasksDanglingUntriaged> app_browser_ = nullptr;
 
   bool in_tear_down_ = false;
diff --git a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
index 9fccf45..bf8b5ca 100644
--- a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
@@ -87,7 +87,7 @@
   }
 
   struct App {
-    AppId id;
+    webapps::AppId id;
     raw_ptr<Browser> browser;
     raw_ptr<BrowserView> browser_view;
     // This field is not a raw_ptr<> because of missing |.get()| in
@@ -105,7 +105,8 @@
     web_app_info->title = u"Test app";
     web_app_info->background_color = kAppBackgroundColor;
     web_app_info->user_display_mode = mojom::UserDisplayMode::kTabbed;
-    AppId app_id = test::InstallWebApp(profile, std::move(web_app_info));
+    webapps::AppId app_id =
+        test::InstallWebApp(profile, std::move(web_app_info));
 
     Browser* app_browser = ::web_app::LaunchWebAppBrowser(profile, app_id);
     return App{app_id, app_browser,
@@ -113,14 +114,14 @@
                app_browser->tab_strip_model()->GetActiveWebContents()};
   }
 
-  AppId InstallTestWebApp(GURL start_url, bool await_metric = true) {
+  webapps::AppId InstallTestWebApp(GURL start_url, bool await_metric = true) {
     page_load_metrics::PageLoadMetricsTestWaiter metrics_waiter(
         browser()->tab_strip_model()->GetActiveWebContents());
     if (await_metric) {
       metrics_waiter.AddWebFeatureExpectation(
           blink::mojom::WebFeature::kWebAppTabbed);
     }
-    AppId app_id = InstallWebAppFromPage(browser(), start_url);
+    webapps::AppId app_id = InstallWebAppFromPage(browser(), start_url);
     if (await_metric) {
       metrics_waiter.Wait();
     }
@@ -197,7 +198,7 @@
   NavigateToURLAndWait(browser(), start_url);
 
   // Install the site with the user display mode set to kTabbed.
-  AppId app_id;
+  webapps::AppId app_id;
   {
     base::RunLoop run_loop;
     auto* provider = WebAppProvider::GetForTest(browser()->profile());
@@ -216,7 +217,7 @@
                   .Run(/*user_accepted=*/true, std::move(web_app_info));
             }),
         base::BindLambdaForTesting(
-            [&run_loop, &app_id](const AppId& installed_app_id,
+            [&run_loop, &app_id](const webapps::AppId& installed_app_id,
                                  webapps::InstallResultCode code) {
               DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
               app_id = installed_app_id;
@@ -298,7 +299,7 @@
   GURL start_url = embedded_test_server()->GetURL(
       "/banners/"
       "manifest_test_page.html?manifest=manifest_tabbed_display_override.json");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = LaunchWebAppBrowser(app_id);
 
   EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
@@ -312,7 +313,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, NewTabUrl) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = LaunchWebAppBrowser(app_id);
 
   EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
@@ -326,7 +327,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, InstallingPinsHomeTab) {
   GURL start_url = embedded_test_server()->GetURL(
       "/web_apps/tab_strip_customizations.html?some_query#blah");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -357,9 +358,10 @@
   WebAppProvider::GetForTest(browser()->profile())
       ->icon_manager()
       .SetFaviconMonochromeReadCallbackForTesting(base::BindLambdaForTesting(
-          [&](const AppId& cached_app_id) { run_loop.Quit(); }));
+          [&](const webapps::AppId& cached_app_id) { run_loop.Quit(); }));
 
-  AppId app_id = InstallWebAppFromPageAndCloseAppBrowser(browser(), start_url);
+  webapps::AppId app_id =
+      InstallWebAppFromPageAndCloseAppBrowser(browser(), start_url);
   run_loop.Run();
 
   Browser* app_browser = LaunchWebAppBrowser(app_id);
@@ -399,7 +401,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, InstallFromNonHomeTabUrl) {
   GURL start_url = embedded_test_server()->GetURL(
       "/web_apps/get_manifest.html?tab_strip_customizations.json");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -417,7 +419,7 @@
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
   // Install and close app.
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   CloseAndWait(app_browser);
 
@@ -451,7 +453,7 @@
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
   // Install and close app.
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   CloseAndWait(app_browser);
 
@@ -496,7 +498,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, DISABLED_NavigationThrottle) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -588,7 +590,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, OpenInChrome) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = LaunchWebAppBrowser(app_id);
 
   EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
@@ -606,7 +608,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, WebAppMenuModelTabbedApp) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = LaunchWebAppBrowser(app_id);
 
   WebAppMenuModel model(nullptr, app_browser);
@@ -617,7 +619,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, WebAppMenuModelNonTabbedApp) {
   GURL start_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = InstallTestWebApp(start_url, /*await_metric=*/false);
+  webapps::AppId app_id = InstallTestWebApp(start_url, /*await_metric=*/false);
   Browser* app_browser = LaunchWebAppBrowser(app_id);
 
   WebAppMenuModel model(nullptr, app_browser);
@@ -629,7 +631,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, MoveTabsToNewWindow) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = LaunchWebAppBrowser(app_id);
 
   chrome::NewTab(app_browser);
@@ -658,7 +660,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, MoveTabsToExistingWindow) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = LaunchWebAppBrowser(app_id);
   chrome::NewTab(app_browser);
 
@@ -695,7 +697,7 @@
                        OnlyNavigateHomeTabIfDifferentUrl) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -738,7 +740,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, NoFavicons) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -753,7 +755,7 @@
                        OnlyThrottlePrimaryMainFrame) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
   content::WebContents* web_contents = tab_strip->GetActiveWebContents();
@@ -778,7 +780,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, DontCreateThrottleForReload) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
   EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
@@ -797,7 +799,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, QueryParamsInStartUrl) {
   GURL start_url = embedded_test_server()->GetURL(
       "/web_apps/get_manifest.html?tab_strip_query_params_in_start_url.json");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -822,7 +824,7 @@
                        OutOfScopeNavigationFromHomeTab) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -850,7 +852,7 @@
   GURL start_url = embedded_test_server()->GetURL(
       "/banners/"
       "manifest_test_page.html?manifest=manifest_tabbed_display_override.json");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
 
   Browser* app_browser = LaunchWebAppBrowser(app_id);
   content::WebContents* web_contents =
@@ -869,7 +871,7 @@
                        CloseTabCommandDisabledForHomeTab) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -905,7 +907,7 @@
                        MiddleClickDoesntCloseHomeTab) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip_model = app_browser->tab_strip_model();
 
@@ -942,7 +944,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, HomeTabCantBeClosedUsingJS) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -978,7 +980,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, HomeTabScopeSegmentWildcard) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -1017,7 +1019,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, HomeTabScopeFixedString) {
   GURL start_url = embedded_test_server()->GetURL(
       "/web_apps/get_manifest.html?tab_strip_fixed_home_scope.json");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -1067,7 +1069,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, HomeTabScopeWildcardString) {
   GURL start_url = embedded_test_server()->GetURL(
       "/web_apps/get_manifest.html?tab_strip_wildcard_home_scope.json");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -1116,7 +1118,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, CloseAllTabsCommand) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -1148,7 +1150,7 @@
                        NewTabButtonUrlInHomeTabScope) {
   GURL start_url = embedded_test_server()->GetURL(
       "/web_apps/get_manifest.html?tab_strip_wildcard_home_scope.json");
-  AppId app_id = InstallTestWebApp(start_url);
+  webapps::AppId app_id = InstallTestWebApp(start_url);
   Browser* app_browser = LaunchWebAppBrowser(app_id);
 
   EXPECT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id));
@@ -1166,7 +1168,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, MiddleClickHomeTabLink) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallWebAppFromPage(browser(), start_url);
+  webapps::AppId app_id = InstallWebAppFromPage(browser(), start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -1207,7 +1209,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppTabStripBrowserTest, PageTitle) {
   GURL start_url =
       embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html");
-  AppId app_id = InstallWebAppFromPage(browser(), start_url);
+  webapps::AppId app_id = InstallWebAppFromPage(browser(), start_url);
   Browser* app_browser = FindWebAppBrowser(browser()->profile(), app_id);
   TabStripModel* tab_strip = app_browser->tab_strip_model();
 
@@ -1341,7 +1343,7 @@
       }));
 
   // Install web app with origin trial token.
-  AppId app_id =
+  webapps::AppId app_id =
       web_app::InstallWebAppFromPage(browser(), GURL(kTestWebAppUrl));
 
   WebAppProvider& provider = *WebAppProvider::GetForTest(browser()->profile());
diff --git a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc
index 20b7d406..285131d 100644
--- a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc
@@ -38,11 +38,11 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/widget/any_widget_observer.h"
 
-using web_app::AppId;
+using webapps::AppId;
 
 namespace {
 
-AppId InstallTestWebApp(Profile* profile) {
+webapps::AppId InstallTestWebApp(Profile* profile) {
   const GURL example_url = GURL("http://example.org/");
 
   auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>();
@@ -68,7 +68,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppUninstallDialogViewBrowserTest,
                        TrackParentWindowDestructionAfterViewCreation) {
-  AppId app_id = InstallTestWebApp(browser()->profile());
+  webapps::AppId app_id = InstallTestWebApp(browser()->profile());
 
   base::test::TestFuture<webapps::UninstallResultCode> test_future;
   provider()->ui_manager().PresentUserUninstallDialog(
@@ -96,7 +96,7 @@
                        TrackParentWindowDestructionBeforeViewCreation) {
   extensions::ScopedTestDialogAutoConfirm auto_confirm(
       extensions::ScopedTestDialogAutoConfirm::ACCEPT);
-  AppId app_id = InstallTestWebApp(browser()->profile());
+  webapps::AppId app_id = InstallTestWebApp(browser()->profile());
   Browser* app_browser =
       web_app::LaunchWebAppBrowser(browser()->profile(), app_id);
   chrome::CloseWindow(browser());
@@ -115,7 +115,7 @@
                        TestDialogUserFlow_Cancel) {
   extensions::ScopedTestDialogAutoConfirm auto_confirm(
       extensions::ScopedTestDialogAutoConfirm::CANCEL);
-  AppId app_id = InstallTestWebApp(browser()->profile());
+  webapps::AppId app_id = InstallTestWebApp(browser()->profile());
 
   base::test::TestFuture<webapps::UninstallResultCode> test_future;
   provider()->ui_manager().PresentUserUninstallDialog(
@@ -131,7 +131,7 @@
                        TestDialogUserFlow_Accept) {
   extensions::ScopedTestDialogAutoConfirm auto_confirm(
       extensions::ScopedTestDialogAutoConfirm::ACCEPT_AND_OPTION);
-  AppId app_id = InstallTestWebApp(browser()->profile());
+  webapps::AppId app_id = InstallTestWebApp(browser()->profile());
 
   base::test::TestFuture<webapps::UninstallResultCode> test_future;
   provider()->ui_manager().PresentUserUninstallDialog(
diff --git a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.cc b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.cc
index 7ba6ce6..41312910 100644
--- a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.cc
@@ -54,7 +54,7 @@
 
 WebAppUninstallDialogDelegateView::WebAppUninstallDialogDelegateView(
     Profile* profile,
-    web_app::AppId app_id,
+    webapps::AppId app_id,
     webapps::WebappUninstallSource uninstall_source,
     std::map<SquareSizePx, SkBitmap> icon_bitmaps,
     web_app::UninstallDialogCallback uninstall_choice_callback)
@@ -167,7 +167,7 @@
 }
 
 void WebAppUninstallDialogDelegateView::OnWebAppWillBeUninstalled(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   // Handle the case when web app was uninstalled externally and we have to
   // cancel current dialog.
   if (app_id == app_id_) {
@@ -208,7 +208,7 @@
 
 void ShowWebAppUninstallDialog(
     Profile* profile,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     gfx::NativeWindow parent,
     std::map<SquareSizePx, SkBitmap> icon_bitmaps,
diff --git a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h
index b222c85..62ae5861a 100644
--- a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h
+++ b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_uninstall_dialog_user_options.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/image/image_skia.h"
@@ -46,7 +47,7 @@
   // Constructor for view component of dialog.
   WebAppUninstallDialogDelegateView(
       Profile* profile,
-      web_app::AppId app_id,
+      webapps::AppId app_id,
       webapps::WebappUninstallSource uninstall_source,
       std::map<SquareSizePx, SkBitmap> icon_bitmaps,
       web_app::UninstallDialogCallback uninstall_choice_callback);
@@ -69,14 +70,14 @@
   void OnDialogCanceled();
 
   // web_app::WebAppInstallManagerObserver:
-  void OnWebAppWillBeUninstalled(const web_app::AppId& app_id) override;
+  void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
 
   raw_ptr<views::Checkbox> checkbox_ = nullptr;
   gfx::ImageSkia image_;
 
   // The web app we are showing the dialog for.
-  const web_app::AppId app_id_;
+  const webapps::AppId app_id_;
 
   const raw_ptr<Profile, AcrossTasksDanglingUntriaged> profile_;
   base::WeakPtr<web_app::WebAppProvider> provider_;
diff --git a/chrome/browser/ui/views/web_apps/web_ui_web_app_browsertest.cc b/chrome/browser/ui/views/web_apps/web_ui_web_app_browsertest.cc
index 823d42f..6a6ed54 100644
--- a/chrome/browser/ui/views/web_apps/web_ui_web_app_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_ui_web_app_browsertest.cc
@@ -38,7 +38,7 @@
   }
 
   struct App {
-    AppId id;
+    webapps::AppId id;
     std::string start_url;
     raw_ptr<Browser> browser;
     raw_ptr<BrowserView> browser_view;
@@ -53,7 +53,8 @@
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GURL(start_url);
     web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
-    AppId app_id = test::InstallWebApp(profile, std::move(web_app_info));
+    webapps::AppId app_id =
+        test::InstallWebApp(profile, std::move(web_app_info));
 
     Browser* app_browser = ::web_app::LaunchWebAppBrowser(profile, app_id);
     return App{app_id, start_url, app_browser,
diff --git a/chrome/browser/ui/web_applications/BUILD.gn b/chrome/browser/ui/web_applications/BUILD.gn
index 3d449ff..c1e3b4f 100644
--- a/chrome/browser/ui/web_applications/BUILD.gn
+++ b/chrome/browser/ui/web_applications/BUILD.gn
@@ -91,6 +91,7 @@
     "//components/services/app_service",
     "//components/site_engagement/content",
     "//components/webapps/browser",
+    "//components/webapps/common",
   ]
 
   if (is_chromeos_ash) {
diff --git a/chrome/browser/ui/web_applications/app_browser_controller.cc b/chrome/browser/ui/web_applications/app_browser_controller.cc
index 16e8f63..a1850498 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller.cc
+++ b/chrome/browser/ui/web_applications/app_browser_controller.cc
@@ -82,13 +82,13 @@
 
 // static
 bool AppBrowserController::IsForWebApp(const Browser* browser,
-                                       const AppId& app_id) {
+                                       const webapps::AppId& app_id) {
   return IsWebApp(browser) && browser->app_controller()->app_id() == app_id;
 }
 
 // static
 Browser* AppBrowserController::FindForWebApp(const Profile& profile,
-                                             const AppId& app_id) {
+                                             const webapps::AppId& app_id) {
   const BrowserList* browser_list = BrowserList::GetInstance();
   for (auto it = browser_list->begin_browsers_ordered_by_activation();
        it != browser_list->end_browsers_ordered_by_activation(); ++it) {
@@ -118,10 +118,9 @@
   return theme_provider_.get();
 }
 
-AppBrowserController::AppBrowserController(
-    Browser* browser,
-    AppId app_id,
-    bool has_tab_strip)
+AppBrowserController::AppBrowserController(Browser* browser,
+                                           webapps::AppId app_id,
+                                           bool has_tab_strip)
     : content::WebContentsObserver(nullptr),
       browser_(browser),
       app_id_(std::move(app_id)),
@@ -131,7 +130,8 @@
   browser->tab_strip_model()->AddObserver(this);
 }
 
-AppBrowserController::AppBrowserController(Browser* browser, AppId app_id)
+AppBrowserController::AppBrowserController(Browser* browser,
+                                           webapps::AppId app_id)
     : AppBrowserController(browser, std::move(app_id), false) {}
 
 void AppBrowserController::Init() {
diff --git a/chrome/browser/ui/web_applications/app_browser_controller.h b/chrome/browser/ui/web_applications/app_browser_controller.h
index d354d7d0..bc1d74e 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller.h
+++ b/chrome/browser/ui/web_applications/app_browser_controller.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/url_formatter/url_formatter.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -66,10 +67,11 @@
   // Returns whether |browser| is a web app window/pop-up.
   static bool IsWebApp(const Browser* browser);
   // Returns whether |browser| is a web app window/pop-up for |app_id|.
-  static bool IsForWebApp(const Browser* browser, const AppId& app_id);
+  static bool IsForWebApp(const Browser* browser, const webapps::AppId& app_id);
   // Returns a Browser* that is for |app_id| and |profile| if any, searches in
   // order of last browser activation. Ignores pop-up Browsers.
-  static Browser* FindForWebApp(const Profile& profile, const AppId& app_id);
+  static Browser* FindForWebApp(const Profile& profile,
+                                const webapps::AppId& app_id);
 
   // Renders |url|'s origin as Unicode.
   static std::u16string FormatUrlOrigin(
@@ -229,7 +231,7 @@
   // animated.
   void UpdateCustomTabBarVisibility(bool animate) const;
 
-  const AppId& app_id() const { return app_id_; }
+  const webapps::AppId& app_id() const { return app_id_; }
 
   Browser* browser() const { return browser_; }
 
@@ -275,9 +277,9 @@
 
  protected:
   AppBrowserController(Browser* browser,
-                       AppId app_id,
+                       webapps::AppId app_id,
                        bool has_tab_strip);
-  AppBrowserController(Browser* browser, AppId app_id);
+  AppBrowserController(Browser* browser, webapps::AppId app_id);
 
   // Called once the app browser controller has determined its initial url.
   virtual void OnReceivedInitialURL();
@@ -296,7 +298,7 @@
   void SetInitialURL(const GURL& initial_url);
 
   const raw_ptr<Browser> browser_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   const bool has_tab_strip_;
   GURL initial_url_;
 
diff --git a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
index f18c88f..9d40e0ad 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
+++ b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
@@ -22,7 +22,7 @@
 IN_PROC_BROWSER_TEST_F(AppBrowserControllerBrowserTest,
                        HighContrastThemeColor) {
   const GURL start_url("https://app.site.test/example/index");
-  const AppId app_id = InstallPWA(start_url);
+  const webapps::AppId app_id = InstallPWA(start_url);
 
   Browser* browser = web_app::LaunchWebAppBrowser(profile(), app_id);
 
diff --git a/chrome/browser/ui/web_applications/commands/launch_web_app_command_browsertest.cc b/chrome/browser/ui/web_applications/commands/launch_web_app_command_browsertest.cc
index 3820bce..7178607 100644
--- a/chrome/browser/ui/web_applications/commands/launch_web_app_command_browsertest.cc
+++ b/chrome/browser/ui/web_applications/commands/launch_web_app_command_browsertest.cc
@@ -92,7 +92,7 @@
     return params;
   }
 
-  AppId app_id_;
+  webapps::AppId app_id_;
 };
 
 IN_PROC_BROWSER_TEST_F(LaunchWebAppCommandTest, TabbedLaunchCurrentBrowser) {
diff --git a/chrome/browser/ui/web_applications/create_shortcut_browsertest.cc b/chrome/browser/ui/web_applications/create_shortcut_browsertest.cc
index da367de3..67d1af89a 100644
--- a/chrome/browser/ui/web_applications/create_shortcut_browsertest.cc
+++ b/chrome/browser/ui/web_applications/create_shortcut_browsertest.cc
@@ -33,7 +33,6 @@
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -41,6 +40,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "components/webapps/browser/features.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/common/extension.h"
@@ -69,12 +69,12 @@
 
 class CreateShortcutBrowserTest : public WebAppControllerBrowserTest {
  public:
-  AppId InstallShortcutAppForCurrentUrl(bool open_as_window = false) {
+  webapps::AppId InstallShortcutAppForCurrentUrl(bool open_as_window = false) {
     chrome::SetAutoAcceptWebAppDialogForTesting(true, open_as_window);
     WebAppTestInstallObserver observer(profile());
     observer.BeginListening();
     CHECK(chrome::ExecuteCommand(browser(), IDC_CREATE_SHORTCUT));
-    AppId app_id = observer.Wait();
+    webapps::AppId app_id = observer.Wait();
     chrome::SetAutoAcceptWebAppDialogForTesting(false, false);
     return app_id;
   }
@@ -106,7 +106,7 @@
   base::UserActionTester user_action_tester;
   NavigateToURLAndWait(browser(), GetInstallableAppURL());
 
-  AppId app_id = InstallShortcutAppForCurrentUrl();
+  webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
   EXPECT_EQ(registrar().GetAppShortName(app_id), GetInstallableAppName());
   // Shortcut apps to PWAs should launch in a tab.
   EXPECT_EQ(registrar().GetAppUserDisplayMode(app_id),
@@ -133,7 +133,7 @@
             "/web_apps/get_manifest.html?theme_color_only.json")}) {
     base::HistogramTester histogram_tester;
     NavigateToURLAndWait(browser(), url);
-    AppId app_id = InstallShortcutAppForCurrentUrl();
+    webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
 
     EXPECT_EQ(webapps::WebappInstallSource::MENU_CREATE_SHORTCUT,
               *registrar().GetLatestAppInstallSource(app_id));
@@ -161,7 +161,7 @@
 IN_PROC_BROWSER_TEST_F(CreateShortcutBrowserTest,
                        CannotInstallOverWindowShortcutApp) {
   NavigateToURLAndWait(browser(), GetInstallableAppURL());
-  AppId app_id = InstallShortcutAppForCurrentUrl();
+  webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
   // Change launch container to open in window.
   sync_bridge().SetAppUserDisplayMode(app_id,
                                       mojom::UserDisplayMode::kStandalone,
@@ -206,7 +206,7 @@
   // TODO(crbug.com/1253234): IDC_CREATE_SHORTCUT command must become disabled.
   ASSERT_TRUE(chrome::IsCommandEnabled(browser(), IDC_CREATE_SHORTCUT));
 
-  const AppId app_id = InstallShortcutAppForCurrentUrl();
+  const webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
   CHECK(app_browser);
   CHECK(app_browser != browser());
@@ -248,7 +248,7 @@
   NavigateToURLAndWait(
       browser(), embedded_test_server()->GetURL(
                      "/web_apps/get_manifest.html?theme_color_only.json"));
-  AppId app_id = InstallShortcutAppForCurrentUrl();
+  webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
   EXPECT_EQ(registrar().GetAppThemeColor(app_id),
             SkColorSetRGB(0x12, 0x34, 0x56));
 }
@@ -259,7 +259,7 @@
   GURL url = embedded_test_server()->GetURL(
       "/web_apps/get_manifest.html?invalid_start_url.json");
   NavigateToURLAndWait(browser(), url);
-  AppId app_id = InstallShortcutAppForCurrentUrl();
+  webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
   EXPECT_EQ(registrar().GetAppStartUrl(app_id), url);
 }
 
@@ -269,7 +269,7 @@
   base::UserActionTester user_action_tester;
   NavigateToURLAndWait(browser(), GetInstallableAppURL());
 
-  AppId app_id = InstallShortcutAppForCurrentUrl();
+  webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
   EXPECT_EQ(registrar().GetAppShortName(app_id), GetInstallableAppName());
   // Shortcut apps to PWAs should launch in a tab.
   EXPECT_EQ(registrar().GetAppUserDisplayMode(app_id),
@@ -309,7 +309,7 @@
 IN_PROC_BROWSER_TEST_F(CreateShortcutBrowserTest, UseHostWhenTitleIsUrl) {
   NavigateToURLAndWait(browser(),
                        https_server()->GetURL("example.com", "/empty.html"));
-  AppId app_id = InstallShortcutAppForCurrentUrl();
+  webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
 
   base::test::TestFuture<std::map<SquareSizePx, SkBitmap>> future;
   WebAppProvider::GetForTest(profile())->icon_manager().ReadIcons(
@@ -349,7 +349,7 @@
                        InstallableSiteDifferentStartUrl) {
   bool create_shortcut_ignores_manifest = GetParam();
   NavigateToURLAndWait(browser(), PageWithDifferentStartUrl());
-  AppId app_id = InstallShortcutAppForCurrentUrl();
+  webapps::AppId app_id = InstallShortcutAppForCurrentUrl();
 
   EXPECT_EQ(registrar().GetAppUserDisplayMode(app_id),
             mojom::UserDisplayMode::kBrowser);
diff --git a/chrome/browser/ui/web_applications/diagnostics/BUILD.gn b/chrome/browser/ui/web_applications/diagnostics/BUILD.gn
index c2c1896..bcf19eb 100644
--- a/chrome/browser/ui/web_applications/diagnostics/BUILD.gn
+++ b/chrome/browser/ui/web_applications/diagnostics/BUILD.gn
@@ -20,6 +20,7 @@
     "//chrome/test:test_support",
     "//chrome/test:test_support_ui",
     "//components/services/app_service",
+    "//components/webapps/common",
   ]
 
   if (is_chromeos_lacros) {
diff --git a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_diagnostic.cc b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_diagnostic.cc
index f9fa05b..338992f2 100644
--- a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_diagnostic.cc
+++ b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_diagnostic.cc
@@ -14,7 +14,8 @@
 
 namespace web_app {
 
-WebAppIconDiagnostic::WebAppIconDiagnostic(Profile* profile, AppId app_id)
+WebAppIconDiagnostic::WebAppIconDiagnostic(Profile* profile,
+                                           webapps::AppId app_id)
     : profile_(profile),
       app_id_(std::move(app_id)),
       provider_(WebAppProvider::GetForLocalAppsUnchecked(profile_.get())),
diff --git a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_diagnostic.h b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_diagnostic.h
index a87e11c..4d69dc3 100644
--- a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_diagnostic.h
+++ b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_diagnostic.h
@@ -10,6 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -41,7 +42,7 @@
     }
   };
 
-  WebAppIconDiagnostic(Profile* profile, AppId app_id);
+  WebAppIconDiagnostic(Profile* profile, webapps::AppId app_id);
   ~WebAppIconDiagnostic();
 
   void Run(base::OnceCallback<void(absl::optional<Result>)> result_callback);
@@ -65,7 +66,7 @@
       WebAppIconManager::IconFilesCheck icon_files_check);
 
   const raw_ptr<Profile> profile_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
 
   const raw_ptr<WebAppProvider> provider_;
   const raw_ptr<const WebApp> app_;
diff --git a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks.cc b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks.cc
index 9335674..73ea5ce 100644
--- a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks.cc
+++ b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks.cc
@@ -35,7 +35,8 @@
   return weak_ptr_factory_.GetWeakPtr();
 }
 
-void WebAppIconHealthChecks::OnWebAppWillBeUninstalled(const AppId& app_id) {
+void WebAppIconHealthChecks::OnWebAppWillBeUninstalled(
+    const webapps::AppId& app_id) {
   if (running_diagnostics_.erase(app_id) > 0)
     run_complete_callback_.Run();
 }
@@ -48,13 +49,14 @@
 
   install_manager_observation_.Observe(&provider->install_manager());
 
-  std::vector<AppId> app_ids = provider->registrar_unsafe().GetAppIds();
+  std::vector<webapps::AppId> app_ids =
+      provider->registrar_unsafe().GetAppIds();
   run_complete_callback_ = base::BarrierClosure(
       app_ids.size(),
       base::BindOnce(&WebAppIconHealthChecks::RecordDiagnosticResults,
                      GetWeakPtr()));
 
-  for (const AppId& app_id : app_ids) {
+  for (const webapps::AppId& app_id : app_ids) {
     WebAppIconDiagnostic* diagnostic =
         running_diagnostics_
             .insert_or_assign(app_id, std::make_unique<WebAppIconDiagnostic>(
@@ -66,7 +68,7 @@
 }
 
 void WebAppIconHealthChecks::SaveDiagnosticForApp(
-    AppId app_id,
+    webapps::AppId app_id,
     absl::optional<WebAppIconDiagnostic::Result> result) {
   running_diagnostics_.erase(app_id);
   if (result)
diff --git a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks.h b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks.h
index 4b73f001..88c6d10 100644
--- a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks.h
+++ b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -31,13 +32,13 @@
   base::WeakPtr<WebAppIconHealthChecks> GetWeakPtr();
 
   // WebAppInstallManagerObserver:
-  void OnWebAppWillBeUninstalled(const AppId& app_id) override;
+  void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
 
  private:
   void RunDiagnostics();
   void SaveDiagnosticForApp(
-      AppId app_id,
+      webapps::AppId app_id,
       absl::optional<WebAppIconDiagnostic::Result> result);
   void RecordDiagnosticResults();
 
@@ -45,7 +46,7 @@
   apps::AppType app_type_;
   AppTypeInitializedEvent web_apps_published_event_;
 
-  base::flat_map<AppId, std::unique_ptr<WebAppIconDiagnostic>>
+  base::flat_map<webapps::AppId, std::unique_ptr<WebAppIconDiagnostic>>
       running_diagnostics_;
   base::RepeatingClosure run_complete_callback_;
   std::vector<WebAppIconDiagnostic::Result> results_;
diff --git a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks_browsertest.cc b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks_browsertest.cc
index 4498ceff4..3974ad01 100644
--- a/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks_browsertest.cc
+++ b/chrome/browser/ui/web_applications/diagnostics/web_app_icon_health_checks_browsertest.cc
@@ -16,11 +16,11 @@
 #include "chrome/browser/ui/web_applications/web_app_metrics.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 
 namespace web_app {
@@ -82,8 +82,8 @@
                     expected_result.has_missing_icon_file);
   }
 
-  AppId InstallWebAppAndAwaitAppService(const char* path) {
-    AppId app_id =
+  webapps::AppId InstallWebAppAndAwaitAppService(const char* path) {
+    webapps::AppId app_id =
         InstallWebAppFromPage(browser(), embedded_test_server()->GetURL(path));
     apps::AppReadinessWaiter(profile(), app_id, apps::Readiness::kReady)
         .Await();
@@ -97,7 +97,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIconHealthChecksBrowserTest, EmptyAppName) {
-  AppId app_id = InstallWebAppAndAwaitAppService("/web_apps/basic.html");
+  webapps::AppId app_id =
+      InstallWebAppAndAwaitAppService("/web_apps/basic.html");
 
   // Delete the app name (some users may have corrupt web app databases with
   // missing app names).
@@ -116,7 +117,8 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppIconHealthChecksBrowserTest,
                        MissingDownloadedIconSizes) {
-  AppId app_id = InstallWebAppAndAwaitAppService("/web_apps/basic.html");
+  webapps::AppId app_id =
+      InstallWebAppAndAwaitAppService("/web_apps/basic.html");
   CreateUpdateScope()->UpdateApp(app_id)->SetDownloadedIconSizes(
       IconPurpose::ANY, {});
   RunIconChecksWithMetricExpectations(
@@ -131,7 +133,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppIconHealthChecksBrowserTest,
                        GeneratedIconFlagFalseNegative) {
-  AppId app_id = InstallWebAppAndAwaitAppService(
+  webapps::AppId app_id = InstallWebAppAndAwaitAppService(
       "/web_apps/get_manifest.html?no_icons.json");
   // In https://crbug.com/1317922 manifest update erroneously set
   // is_generated_icon to false.
@@ -143,7 +145,8 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppIconHealthChecksBrowserTest,
                        PRE_DeletedIconFiles) {
-  AppId app_id = InstallWebAppAndAwaitAppService("/web_apps/basic.html");
+  webapps::AppId app_id =
+      InstallWebAppAndAwaitAppService("/web_apps/basic.html");
   RunIconChecksWithMetricExpectations({});
 
   // Delete the icons.
@@ -161,7 +164,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIconHealthChecksBrowserTest, PRE_EmptyIconFile) {
-  AppId app_id = InstallWebAppAndAwaitAppService("/web_apps/basic.html");
+  webapps::AppId app_id =
+      InstallWebAppAndAwaitAppService("/web_apps/basic.html");
   RunIconChecksWithMetricExpectations({});
 
   // Empty the contents of one of the icon files.
@@ -187,7 +191,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppIconHealthChecksBrowserTest, PRE_CorruptIconFile) {
-  AppId app_id = InstallWebAppAndAwaitAppService("/web_apps/basic.html");
+  webapps::AppId app_id =
+      InstallWebAppAndAwaitAppService("/web_apps/basic.html");
   RunIconChecksWithMetricExpectations({});
 
   // Corrupt the contents of one of the icon files.
diff --git a/chrome/browser/ui/web_applications/lacros_web_app_browsertest.cc b/chrome/browser/ui/web_applications/lacros_web_app_browsertest.cc
index 20c91b1..add3fbf2 100644
--- a/chrome/browser/ui/web_applications/lacros_web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/lacros_web_app_browsertest.cc
@@ -49,7 +49,7 @@
 
   const GURL app_url =
       https_server()->GetURL("/web_apps/file_handler_index.html");
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   EXPECT_EQ(provider().registrar_unsafe().GetAppFileHandlers(app_id)->size(),
             1U);
 
@@ -102,7 +102,7 @@
 
   const GURL app_url =
       https_server()->GetURL("/web_app_shortcuts/shortcuts.html");
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   EXPECT_EQ(
       provider().registrar_unsafe().GetAppShortcutsMenuItemInfos(app_id).size(),
       6U);
diff --git a/chrome/browser/ui/web_applications/lacros_web_app_shelf_browsertest.cc b/chrome/browser/ui/web_applications/lacros_web_app_shelf_browsertest.cc
index e70ed76..bda7d69 100644
--- a/chrome/browser/ui/web_applications/lacros_web_app_shelf_browsertest.cc
+++ b/chrome/browser/ui/web_applications/lacros_web_app_shelf_browsertest.cc
@@ -83,12 +83,12 @@
 
   const GURL app1_url =
       https_server().GetURL(kFirstAppUrlHost, "/web_apps/basic.html");
-  const AppId app1_id =
+  const webapps::AppId app1_id =
       InstallWebAppFromPageAndCloseAppBrowser(browser(), app1_url);
 
   const GURL app2_url = https_server().GetURL(
       kSecondAppUrlHost, "/web_apps/standalone/basic.html");
-  const AppId app2_id =
+  const webapps::AppId app2_id =
       InstallWebAppFromPageAndCloseAppBrowser(browser(), app2_url);
 
   apps::AppReadinessWaiter(profile(), app1_id).Await();
@@ -130,12 +130,12 @@
 
   const GURL app1_url =
       https_server().GetURL(kFirstAppUrlHost, "/web_apps/basic.html");
-  const AppId app1_id =
+  const webapps::AppId app1_id =
       InstallWebAppFromPageAndCloseAppBrowser(browser(), app1_url);
 
   const GURL app2_url = https_server().GetURL(
       kSecondAppUrlHost, "/web_app_shortcuts/shortcuts.html");
-  const AppId app2_id =
+  const webapps::AppId app2_id =
       InstallWebAppFromPageAndCloseAppBrowser(browser(), app2_url);
 
   GURL out_of_scope_url = https_server().GetURL("/empty.html");
@@ -180,7 +180,7 @@
 
   const GURL app_url = https_server().GetURL(kFirstAppUrlHost,
                                              "/web_apps/minimal_ui/basic.html");
-  const AppId app_id =
+  const webapps::AppId app_id =
       InstallWebAppFromPageAndCloseAppBrowser(browser(), app_url);
 
   apps::AppReadinessWaiter(profile(), app_id).Await();
@@ -215,12 +215,12 @@
                               ->GetRemote<crosapi::mojom::TestController>();
   const GURL app1_url = https_server().GetURL(
       kFirstAppUrlHost, "/web_apps/standalone/basic.html");
-  const AppId app1_id =
+  const webapps::AppId app1_id =
       InstallWebAppFromPageAndCloseAppBrowser(browser(), app1_url);
 
   const GURL app2_url =
       https_server().GetURL(kSecondAppUrlHost, "/web_apps/basic.html");
-  const AppId app2_id =
+  const webapps::AppId app2_id =
       InstallWebAppFromPageAndCloseAppBrowser(browser(), app2_url);
 
   {
@@ -334,7 +334,7 @@
       embedded_test_server()->GetURL("/banners/scope_a/no_manifest.html"));
   GURL app2_url(
       embedded_test_server()->GetURL("/banners/scope_b/scope_b.html"));
-  AppId app1_id;
+  webapps::AppId app1_id;
   Browser* app1_browser;
   {
     web_app::ServiceWorkerRegistrationWaiter registration_waiter(profile(),
@@ -395,7 +395,7 @@
   }
 
   // Install app2 PWA.
-  AppId app2_id;
+  webapps::AppId app2_id;
   Browser* app2_browser;
   {
     browser()->tab_strip_model()->ActivateTabAt(/*index=*/1);
diff --git a/chrome/browser/ui/web_applications/launch_web_app_browsertest.cc b/chrome/browser/ui/web_applications/launch_web_app_browsertest.cc
index 0cdee82..3d0e825 100644
--- a/chrome/browser/ui/web_applications/launch_web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/launch_web_app_browsertest.cc
@@ -30,7 +30,7 @@
 
 IN_PROC_BROWSER_TEST_F(LaunchWebAppBrowserTest, OpenLinkInWebApp) {
   const GURL start_url("https://app.site.test/example/index");
-  const AppId app_id = InstallPWA(start_url);
+  const webapps::AppId app_id = InstallPWA(start_url);
   apps::AppReadinessWaiter(profile(), app_id).Await();
 
   size_t num_browsers = chrome::GetBrowserCount(browser()->profile());
diff --git a/chrome/browser/ui/web_applications/pwa_mixed_content_browsertest.cc b/chrome/browser/ui/web_applications/pwa_mixed_content_browsertest.cc
index 31f11de..29762fd 100644
--- a/chrome/browser/ui/web_applications/pwa_mixed_content_browsertest.cc
+++ b/chrome/browser/ui/web_applications/pwa_mixed_content_browsertest.cc
@@ -118,7 +118,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   const GURL app_url = GetMixedContentAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
   CHECK(app_browser);
   web_app::CheckMixedContentLoaded(app_browser);
@@ -131,7 +131,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   const GURL app_url = GetMixedContentAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   // Mixed content should be able to load in web app windows.
@@ -168,7 +168,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   const GURL app_url = GetMixedContentAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   NavigateToURLAndWait(browser(), GetMixedContentAppURL());
   content::WebContents* tab_contents =
@@ -204,7 +204,7 @@
 // Tests that mixed content is not loaded inside iframes in PWA windows.
 IN_PROC_BROWSER_TEST_F(PWAMixedContentBrowserTest, IFrameMixedContentInPWA) {
   const GURL app_url = GetSecureIFrameAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   CheckMixedContentFailedToLoad(app_browser);
@@ -218,7 +218,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   const GURL app_url = GetSecureIFrameAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   NavigateToURLAndWait(browser(), app_url);
   CheckMixedContentFailedToLoad(browser());
@@ -254,7 +254,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   const GURL app_url = GetSecureIFrameAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   chrome::OpenInChrome(app_browser);
diff --git a/chrome/browser/ui/web_applications/share_to_target_browsertest.cc b/chrome/browser/ui/web_applications/share_to_target_browsertest.cc
index 86afb845..f1b2127 100644
--- a/chrome/browser/ui/web_applications/share_to_target_browsertest.cc
+++ b/chrome/browser/ui/web_applications/share_to_target_browsertest.cc
@@ -94,7 +94,7 @@
     app_id_ = web_app::InstallWebAppFromManifest(browser(), app_url);
   }
 
-  const AppId& app_id() const { return app_id_; }
+  const webapps::AppId& app_id() const { return app_id_; }
 
  private:
   // WebAppControllerBrowserTest:
@@ -104,7 +104,7 @@
     WebAppControllerBrowserTest::TearDownOnMainThread();
   }
 
-  static void CloseAppWindows(const AppId& app_id) {
+  static void CloseAppWindows(const webapps::AppId& app_id) {
     for (auto* browser : *BrowserList::GetInstance()) {
       const AppBrowserController* app_controller = browser->app_controller();
       if (app_controller && app_controller->app_id() == app_id)
@@ -117,7 +117,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
   }
 
-  AppId app_id_;
+  webapps::AppId app_id_;
 };
 
 IN_PROC_BROWSER_TEST_F(ShareToTargetBrowserTest, ShareToPosterWebApp) {
diff --git a/chrome/browser/ui/web_applications/status_bar_browsertest.cc b/chrome/browser/ui/web_applications/status_bar_browsertest.cc
index 056a002..82c753bc 100644
--- a/chrome/browser/ui/web_applications/status_bar_browsertest.cc
+++ b/chrome/browser/ui/web_applications/status_bar_browsertest.cc
@@ -17,7 +17,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppStatusBarTest, NoStatusBar) {
   NavigateToURLAndWait(browser(),
                        https_server()->GetURL("/web_apps/basic.html"));
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   Browser* const app_browser =
       ::web_app::LaunchWebAppBrowserAndWait(profile(), app_id);
   EXPECT_EQ(nullptr, app_browser->GetStatusBubbleForTesting());
@@ -26,7 +26,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppStatusBarTest, DisplayBrowserHasStatusBar) {
   NavigateToURLAndWait(
       browser(), https_server()->GetURL("/web_apps/display_browser.html"));
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   Browser* const app_browser =
       ::web_app::LaunchWebAppBrowserAndWait(profile(), app_id);
   EXPECT_NE(nullptr, app_browser->GetStatusBubbleForTesting());
@@ -35,7 +35,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppStatusBarTest, NoManifestHasStatusBar) {
   NavigateToURLAndWait(
       browser(), https_server()->GetURL("/banners/no_manifest_test_page.html"));
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   Browser* const app_browser =
       ::web_app::LaunchWebAppBrowserAndWait(profile(), app_id);
   EXPECT_NE(nullptr, app_browser->GetStatusBubbleForTesting());
@@ -44,7 +44,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppStatusBarTest, DisplayMinimalUiHasStatusBar) {
   NavigateToURLAndWait(
       browser(), https_server()->GetURL("/web_apps/minimal_ui/basic.html"));
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   Browser* const app_browser =
       ::web_app::LaunchWebAppBrowserAndWait(profile(), app_id);
   EXPECT_NE(nullptr, app_browser->GetStatusBubbleForTesting());
diff --git a/chrome/browser/ui/web_applications/sub_apps_service_impl.cc b/chrome/browser/ui/web_applications/sub_apps_service_impl.cc
index e922fdf..29b9ebd 100644
--- a/chrome/browser/ui/web_applications/sub_apps_service_impl.cc
+++ b/chrome/browser/ui/web_applications/sub_apps_service_impl.cc
@@ -23,7 +23,6 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -32,6 +31,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -83,17 +83,17 @@
   return base::ok(resolved);
 }
 
-std::string ConvertUrlToPath(const ManifestId& manifest_id) {
+std::string ConvertUrlToPath(const webapps::ManifestId& manifest_id) {
   return manifest_id.PathForRequest();
 }
 
-base::expected<std::vector<std::pair<ManifestId, GURL>>, std::string>
+base::expected<std::vector<std::pair<webapps::ManifestId, GURL>>, std::string>
 AddOptionsFromMojo(
     const url::Origin& origin,
     const std::vector<SubAppsServiceAddParametersPtr>& sub_apps_to_add_mojo) {
-  std::vector<std::pair<ManifestId, GURL>> sub_apps;
+  std::vector<std::pair<webapps::ManifestId, GURL>> sub_apps;
   for (const auto& sub_app : sub_apps_to_add_mojo) {
-    ASSIGN_OR_RETURN(ManifestId manifest_id,
+    ASSIGN_OR_RETURN(webapps::ManifestId manifest_id,
                      ConvertPathToUrl(sub_app->manifest_id_path, origin));
     ASSIGN_OR_RETURN(GURL install_url,
                      ConvertPathToUrl(sub_app->install_url_path, origin));
@@ -114,7 +114,7 @@
   return provider;
 }
 
-const AppId* GetAppId(content::RenderFrameHost& render_frame_host) {
+const webapps::AppId* GetAppId(content::RenderFrameHost& render_frame_host) {
   auto* const initiator_web_contents =
       content::WebContents::FromRenderFrameHost(&render_frame_host);
   return WebAppTabHelper::GetAppId(initiator_web_contents);
@@ -224,7 +224,7 @@
   }
 
   ASSIGN_OR_RETURN(
-      (std::vector<std::pair<ManifestId, GURL>> add_options),
+      (std::vector<std::pair<webapps::ManifestId, GURL>> add_options),
       AddOptionsFromMojo(render_frame_host().GetLastCommittedOrigin(),
                          sub_apps_to_add),
       // Compromised renderer, bail immediately (this call deletes *this).
@@ -243,9 +243,9 @@
 
 void SubAppsServiceImpl::CollectInstallData(
     int add_call_id,
-    std::vector<std::pair<ManifestId, GURL>> requested_installs) {
+    std::vector<std::pair<webapps::ManifestId, GURL>> requested_installs) {
   const auto install_info_collector = base::BarrierCallback<
-      std::pair<ManifestId, std::unique_ptr<WebAppInstallInfo>>>(
+      std::pair<webapps::ManifestId, std::unique_ptr<WebAppInstallInfo>>>(
       requested_installs.size(),
       base::BindOnce(&SubAppsServiceImpl::ProcessInstallData,
                      weak_ptr_factory_.GetWeakPtr(), add_call_id));
@@ -267,7 +267,7 @@
     provider->scheduler().FetchInstallInfoFromInstallUrl(
         manifest_id, url_to_load,
         base::BindOnce(
-            [](ManifestId manifest_app_id,
+            [](webapps::ManifestId manifest_app_id,
                std::unique_ptr<WebAppInstallInfo> install_info) {
               return std::pair(manifest_app_id, std::move(install_info));
             },
@@ -278,10 +278,10 @@
 
 void SubAppsServiceImpl::ProcessInstallData(
     int add_call_id,
-    std::vector<std::pair<ManifestId, std::unique_ptr<WebAppInstallInfo>>>
-        install_data) {
+    std::vector<std::pair<webapps::ManifestId,
+                          std::unique_ptr<WebAppInstallInfo>>> install_data) {
   AddCallInfo& add_call_info = add_call_info_.at(add_call_id);
-  const AppId* parent_app_id = GetAppId(render_frame_host());
+  const webapps::AppId* parent_app_id = GetAppId(render_frame_host());
 
   for (auto& [manifest_id, install_info] : install_data) {
     // If manifest_id is empty, the app was already installed and no install
@@ -316,7 +316,7 @@
 
   WebAppRegistrar& registrar =
       GetWebAppProvider(render_frame_host())->registrar_unsafe();
-  const AppId* parent_app_id = GetAppId(render_frame_host());
+  const webapps::AppId* parent_app_id = GetAppId(render_frame_host());
 
   add_call_info.install_dialog =
       std::make_unique<SubAppsInstallDialogController>();
@@ -353,21 +353,22 @@
 void SubAppsServiceImpl::ScheduleSubAppInstalls(int add_call_id) {
   AddCallInfo& add_call_info = add_call_info_.at(add_call_id);
 
-  const auto install_results_collector = base::BarrierCallback<
-      std::tuple<ManifestId, AppId, webapps::InstallResultCode>>(
-      add_call_info.install_infos.size(),
-      base::BindOnce(&SubAppsServiceImpl::FinishAddCall,
-                     weak_ptr_factory_.GetWeakPtr(), add_call_id));
+  const auto install_results_collector =
+      base::BarrierCallback<std::tuple<webapps::ManifestId, webapps::AppId,
+                                       webapps::InstallResultCode>>(
+          add_call_info.install_infos.size(),
+          base::BindOnce(&SubAppsServiceImpl::FinishAddCall,
+                         weak_ptr_factory_.GetWeakPtr(), add_call_id));
 
   // Schedule install for each install_info that was collected
   WebAppProvider* provider = GetWebAppProvider(render_frame_host());
   for (auto& install_info : add_call_info.install_infos) {
-    ManifestId manifest_id = install_info->manifest_id;
+    webapps::ManifestId manifest_id = install_info->manifest_id;
     provider->scheduler().InstallFromInfo(
         std::move(install_info), /*overwrite_existing_manifest_fields=*/false,
         webapps::WebappInstallSource::SUB_APP,
         base::BindOnce(
-            [](ManifestId manifest_id, const AppId& app_id,
+            [](webapps::ManifestId manifest_id, const webapps::AppId& app_id,
                webapps::InstallResultCode result_code) {
               return std::tuple(manifest_id, app_id, result_code);
             },
@@ -378,8 +379,9 @@
 
 void SubAppsServiceImpl::FinishAddCall(
     int add_call_id,
-    std::vector<std::tuple<ManifestId, AppId, webapps::InstallResultCode>>
-        install_results) {
+    std::vector<std::tuple<webapps::ManifestId,
+                           webapps::AppId,
+                           webapps::InstallResultCode>> install_results) {
   AddCallInfo& add_call_info = add_call_info_.at(add_call_id);
 
   for (const auto& [manifest_id, app_id, result_code] : install_results) {
@@ -411,10 +413,10 @@
 
   const WebAppRegistrar& registrar = provider->registrar_unsafe();
   std::vector<SubAppsServiceListResultEntryPtr> sub_apps_list;
-  for (const AppId& sub_app_id :
+  for (const webapps::AppId& sub_app_id :
        registrar.GetAllSubAppIds(*GetAppId(render_frame_host()))) {
     const WebApp* sub_app = registrar.GetAppById(sub_app_id);
-    ManifestId manifest_id = sub_app->manifest_id();
+    webapps::ManifestId manifest_id = sub_app->manifest_id();
     sub_apps_list.push_back(SubAppsServiceListResultEntry::New(
         ConvertUrlToPath(manifest_id), sub_app->untranslated_name()));
   }
@@ -463,16 +465,16 @@
 void SubAppsServiceImpl::RemoveSubApp(
     const std::string& manifest_id_path,
     base::OnceCallback<void(SubAppsServiceRemoveResultPtr)> callback,
-    const AppId* calling_app_id) {
+    const webapps::AppId* calling_app_id) {
   // Convert `manifest_id_path` from path form to full URL form.
   ASSIGN_OR_RETURN(
-      const ManifestId manifest_id,
+      const webapps::ManifestId manifest_id,
       ConvertPathToUrl(manifest_id_path,
                        render_frame_host().GetLastCommittedOrigin()),
       // Compromised renderer, bail immediately (this call deletes *this).
       &SubAppsServiceImpl::ReportBadMessageAndDeleteThis, this);
 
-  AppId sub_app_id = GenerateAppIdFromManifestId(manifest_id);
+  webapps::AppId sub_app_id = GenerateAppIdFromManifestId(manifest_id);
   WebAppProvider* provider = GetWebAppProvider(render_frame_host());
   const WebApp* app = provider->registrar_unsafe().GetAppById(sub_app_id);
 
@@ -512,7 +514,7 @@
   if (num_successful_uninstalls > 0) {
     WebAppRegistrar& registrar =
         GetWebAppProvider(render_frame_host())->registrar_unsafe();
-    const AppId* parent_app_id = GetAppId(render_frame_host());
+    const webapps::AppId* parent_app_id = GetAppId(render_frame_host());
     const std::u16string parent_app_name =
         base::ASCIIToUTF16(registrar.GetAppShortName(*parent_app_id));
     const GURL start_url = registrar.GetAppStartUrl(*parent_app_id);
diff --git a/chrome/browser/ui/web_applications/sub_apps_service_impl.h b/chrome/browser/ui/web_applications/sub_apps_service_impl.h
index 73c966a..76bfe944 100644
--- a/chrome/browser/ui/web_applications/sub_apps_service_impl.h
+++ b/chrome/browser/ui/web_applications/sub_apps_service_impl.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/document_service.h"
 #include "third_party/blink/public/mojom/subapps/sub_apps_service.mojom.h"
 
@@ -64,24 +65,25 @@
 
   void CollectInstallData(
       int add_call_id,
-      std::vector<std::pair<ManifestId, GURL>> requested_installs);
+      std::vector<std::pair<webapps::ManifestId, GURL>> requested_installs);
   void ProcessInstallData(
       int add_call_id,
-      std::vector<std::pair<ManifestId, std::unique_ptr<WebAppInstallInfo>>>
-          install_data);
+      std::vector<std::pair<webapps::ManifestId,
+                            std::unique_ptr<WebAppInstallInfo>>> install_data);
   void ScheduleSubAppInstalls(int add_call_id);
   void ProcessDialogResponse(int add_call_id, bool dialog_accepted);
   void FinishAddCallOrShowInstallDialog(int add_call_id);
   void FinishAddCall(
       int add_call_id,
-      std::vector<std::tuple<ManifestId, AppId, webapps::InstallResultCode>>
-          install_results);
+      std::vector<std::tuple<webapps::ManifestId,
+                             webapps::AppId,
+                             webapps::InstallResultCode>> install_results);
 
   void RemoveSubApp(
       const std::string& manifest_id_path,
       base::OnceCallback<void(blink::mojom::SubAppsServiceRemoveResultPtr)>
           remove_barrier_callback,
-      const AppId* calling_app_id);
+      const webapps::AppId* calling_app_id);
   void NotifyUninstall(
       RemoveCallback result_callback,
       std::vector<blink::mojom::SubAppsServiceRemoveResultPtr> remove_results);
diff --git a/chrome/browser/ui/web_applications/sub_apps_service_impl_browsertest.cc b/chrome/browser/ui/web_applications/sub_apps_service_impl_browsertest.cc
index 219af8f..ceafc84 100644
--- a/chrome/browser/ui/web_applications/sub_apps_service_impl_browsertest.cc
+++ b/chrome/browser/ui/web_applications/sub_apps_service_impl_browsertest.cc
@@ -78,8 +78,8 @@
 using RemoveResultsMojo =
     std::vector<blink::mojom::SubAppsServiceRemoveResultPtr>;
 
-using AddResults =
-    std::vector<std::pair<ManifestId, blink::mojom::SubAppsServiceResultCode>>;
+using AddResults = std::vector<
+    std::pair<webapps::ManifestId, blink::mojom::SubAppsServiceResultCode>>;
 
 // There's one simple end-to-end test that actually calls the JS API interface,
 // the rest test the mojo interface (since the first layer listening to the API
@@ -123,13 +123,14 @@
     return GURL(parent_frame->GetLastCommittedOrigin().GetURL().Resolve(path));
   }
 
-  AppId GenerateAppIdFromPath(const std::string& path,
-                              const content::RenderFrameHost* parent_frame) {
+  webapps::AppId GenerateAppIdFromPath(
+      const std::string& path,
+      const content::RenderFrameHost* parent_frame) {
     return GenerateAppId(/*manifest_id_path=*/absl::nullopt,
                          GetURLFromPath(path, parent_frame));
   }
 
-  AppId InstallPwaFromPath(const std::string& path) {
+  webapps::AppId InstallPwaFromPath(const std::string& path) {
     return InstallPWA(GetURLFromPath(path));
   }
 
@@ -184,7 +185,8 @@
         << "UninstallExternalWebApp did not trigger the callback.";
   }
 
-  std::vector<AppId> GetAllSubAppIds(const AppId& parent_app_id) {
+  std::vector<webapps::AppId> GetAllSubAppIds(
+      const webapps::AppId& parent_app_id) {
     return provider().registrar_unsafe().GetAllSubAppIds(parent_app_id);
   }
 
@@ -219,7 +221,8 @@
   }
 
   void ExpectCallAdd(
-      base::flat_set<std::pair<ManifestId, SubAppsServiceResultCode>> expected,
+      base::flat_set<std::pair<webapps::ManifestId, SubAppsServiceResultCode>>
+          expected,
       std::vector<std::pair<std::string, std::string>> subapps) {
     AddResults actual = CallAdd(subapps);
     EXPECT_THAT(actual, testing::UnorderedElementsAreArray(expected));
@@ -253,9 +256,9 @@
     return result;
   }
 
-  std::vector<std::pair<ManifestId, SubAppsServiceResultCode>>
+  std::vector<std::pair<webapps::ManifestId, SubAppsServiceResultCode>>
   RemoveResultsToList(RemoveResultsMojo results) {
-    std::vector<std::pair<ManifestId, SubAppsServiceResultCode>> list;
+    std::vector<std::pair<webapps::ManifestId, SubAppsServiceResultCode>> list;
     for (auto& result : results) {
       list.emplace_back(GetURLFromPath(result->manifest_id_path),
                         result->result_code);
@@ -271,7 +274,7 @@
 
  protected:
   base::test::ScopedFeatureList features_{blink::features::kDesktopPWAsSubApps};
-  AppId parent_app_id_;
+  webapps::AppId parent_app_id_;
   mojo::Remote<SubAppsService> remote_;
   base::AutoReset<
       absl::optional<SubAppsInstallDialogController::DialogActionForTesting>>
@@ -323,7 +326,7 @@
                 {{kSub1, kSub1}});
 
   // Verify a bunch of things for the newly installed sub-app.
-  AppId sub_app_id = GenerateAppIdFromPath(kSub1, iwa_frame);
+  webapps::AppId sub_app_id = GenerateAppIdFromPath(kSub1, iwa_frame);
 
   EXPECT_TRUE(provider().registrar_unsafe().IsInstalled(sub_app_id));
   EXPECT_TRUE(provider().registrar_unsafe().IsLocallyInstalled(sub_app_id));
@@ -333,7 +336,7 @@
 
   const WebApp* sub_app = provider().registrar_unsafe().GetAppById(sub_app_id);
   EXPECT_EQ(parent_app_id_, sub_app->parent_app_id());
-  EXPECT_EQ(std::vector<AppId>{sub_app->app_id()},
+  EXPECT_EQ(std::vector<webapps::AppId>{sub_app->app_id()},
             GetAllSubAppIds(parent_app_id_));
   EXPECT_TRUE(sub_app->IsSubAppInstalledApp());
   EXPECT_TRUE(sub_app->CanUserUninstallWebApp());
@@ -454,7 +457,7 @@
   ExpectCallAdd(
       {{GetURLFromPath(kSubAppPath), SubAppsServiceResultCode::kSuccess}},
       {{kSubAppPath, kSubAppPath}});
-  AppId sub_app_id = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
+  webapps::AppId sub_app_id = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
   EXPECT_EQ(
       DisplayMode::kStandalone,
       provider().registrar_unsafe().GetAppEffectiveDisplayMode(sub_app_id));
@@ -622,9 +625,9 @@
        {kSubAppPath3, kSubAppPath3}});
 
   // Verify that sub-apps are installed.
-  AppId sub_app_id_1 = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
-  AppId sub_app_id_2 = GenerateAppIdFromPath(kSubAppPath2, iwa_frame);
-  AppId sub_app_id_3 = GenerateAppIdFromPath(kSubAppPath3, iwa_frame);
+  webapps::AppId sub_app_id_1 = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
+  webapps::AppId sub_app_id_2 = GenerateAppIdFromPath(kSubAppPath2, iwa_frame);
+  webapps::AppId sub_app_id_3 = GenerateAppIdFromPath(kSubAppPath3, iwa_frame);
 
   EXPECT_TRUE(provider().registrar_unsafe().IsInstalled(sub_app_id_1));
   EXPECT_TRUE(provider().registrar_unsafe().IsInstalled(sub_app_id_2));
@@ -661,8 +664,8 @@
       {{kSubAppPath, kSubAppPath}, {kSubAppPath2, kSubAppPath2}});
 
   // Verify that 2 sub-apps are installed.
-  AppId sub_app_id_1 = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
-  AppId sub_app_id_2 = GenerateAppIdFromPath(kSubAppPath2, iwa_frame);
+  webapps::AppId sub_app_id_1 = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
+  webapps::AppId sub_app_id_2 = GenerateAppIdFromPath(kSubAppPath2, iwa_frame);
   EXPECT_TRUE(provider().registrar_unsafe().IsInstalled(sub_app_id_1));
   EXPECT_TRUE(provider().registrar_unsafe().IsInstalled(sub_app_id_2));
 
@@ -688,7 +691,7 @@
   BindRemote(iwa_frame);
 
   // Install app as standalone app.
-  AppId standalone_app_id = InstallPwaFromPath(kSubAppPath2);
+  webapps::AppId standalone_app_id = InstallPwaFromPath(kSubAppPath2);
   EXPECT_TRUE(provider().registrar_unsafe().IsInstalled(standalone_app_id));
 
   // Add another sub-app to verify standalone app install/uninstall does not
@@ -697,7 +700,7 @@
       {{GetURLFromPath(kSubAppPath), SubAppsServiceResultCode::kSuccess}},
       {{kSubAppPath, kSubAppPath}});
 
-  AppId sub_app_id = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
+  webapps::AppId sub_app_id = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
   EXPECT_TRUE(provider().registrar_unsafe().IsInstalled(sub_app_id));
 
   // Add standalone app as sub-app.
@@ -866,7 +869,7 @@
       {{GetURLFromPath(kSubAppPath), SubAppsServiceResultCode::kSuccess}},
       {{kSubAppPath, kSubAppPath}});
 
-  AppId app_id = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
+  webapps::AppId app_id = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
   EXPECT_EQ(1ul, GetAllSubAppIds(parent_app_id_).size());
   EXPECT_TRUE(provider().registrar_unsafe().IsInstalled(app_id));
 
@@ -890,7 +893,8 @@
 
   EXPECT_EQ(2ul, GetAllSubAppIds(parent_app_id_).size());
 
-  std::vector<std::pair<ManifestId, SubAppsServiceResultCode>> expected_result;
+  std::vector<std::pair<webapps::ManifestId, SubAppsServiceResultCode>>
+      expected_result;
   expected_result.emplace_back(GetURLFromPath(kSubAppPath),
                                SubAppsServiceResultCode::kSuccess);
   expected_result.emplace_back(GetURLFromPath(kSubAppPath2),
@@ -904,8 +908,8 @@
 
   EXPECT_EQ(0ul, GetAllSubAppIds(parent_app_id_).size());
 
-  ManifestId sub_app_id_1 = GetURLFromPath(kSubAppPath);
-  ManifestId sub_app_id_2 = GetURLFromPath(kSubAppPath2);
+  webapps::ManifestId sub_app_id_1 = GetURLFromPath(kSubAppPath);
+  webapps::ManifestId sub_app_id_2 = GetURLFromPath(kSubAppPath2);
   EXPECT_FALSE(provider().registrar_unsafe().IsInstalled(
       GenerateAppIdFromManifestId(sub_app_id_1)));
   EXPECT_FALSE(provider().registrar_unsafe().IsInstalled(
@@ -927,7 +931,7 @@
   content::RenderFrameHost* iwa_frame = InstallAndOpenParentIwaApp();
   BindRemote(iwa_frame);
 
-  AppId sub_app_id = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
+  webapps::AppId sub_app_id = GenerateAppIdFromPath(kSubAppPath, iwa_frame);
 
   ExpectCallAdd(
       {{GetURLFromPath(kSubAppPath), SubAppsServiceResultCode::kSuccess}},
diff --git a/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc b/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
index 3eebd8a..8434f5e 100644
--- a/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
+++ b/chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.cc
@@ -9,10 +9,10 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/web_app_tabbed_utils.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_tab_helper.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/web_contents.h"
@@ -52,7 +52,7 @@
   if (!provider)
     return nullptr;
 
-  const AppId& app_id = browser->app_controller()->app_id();
+  const webapps::AppId& app_id = browser->app_controller()->app_id();
 
   absl::optional<GURL> home_tab_url =
       provider->registrar_unsafe().GetAppPinnedHomeTabUrl(app_id);
@@ -81,7 +81,7 @@
   web_app::AppBrowserController* app_controller = browser->app_controller();
   DCHECK(app_controller);
 
-  const AppId& app_id = app_controller->app_id();
+  const webapps::AppId& app_id = app_controller->app_id();
 
   absl::optional<GURL> home_tab_url =
       provider->registrar_unsafe().GetAppPinnedHomeTabUrl(app_id);
diff --git a/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc b/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc
index 67e985d3..8b830fcd 100644
--- a/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc
+++ b/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -27,6 +26,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/common/content_features.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -67,7 +67,7 @@
 }
 
 content::RenderFrameHost* IsolatedWebAppBrowserTestHarness::OpenApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::StringPiece path) {
   return OpenIsolatedWebApp(profile(), app_id, path);
 }
@@ -117,7 +117,7 @@
 }
 
 content::RenderFrameHost* OpenIsolatedWebApp(Profile* profile,
-                                             const AppId& app_id,
+                                             const webapps::AppId& app_id,
                                              base::StringPiece path) {
   WebAppRegistrar& registrar =
       WebAppProvider::GetForWebApps(profile)->registrar_unsafe();
@@ -159,7 +159,7 @@
 // by that function does not currently allow setting the `WebApp::IsolationData`
 // (which is good for non-test-code, as all real IWA installs must go through
 // the `InstallIsolatedWebAppCommand`).
-AppId AddDummyIsolatedAppToRegistry(
+webapps::AppId AddDummyIsolatedAppToRegistry(
     Profile* profile,
     const GURL& start_url,
     const std::string& name,
@@ -169,7 +169,7 @@
   CHECK(provider);
 
   std::unique_ptr<WebApp> isolated_web_app = test::CreateWebApp(start_url);
-  const AppId app_id = isolated_web_app->app_id();
+  const webapps::AppId app_id = isolated_web_app->app_id();
   isolated_web_app->SetName(name);
   isolated_web_app->SetScope(isolated_web_app->start_url());
   isolated_web_app->SetIsolationData(isolation_data);
diff --git a/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h b/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h
index 7fca642..fbece2f 100644
--- a/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h
+++ b/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h
@@ -51,7 +51,7 @@
       const base::FilePath::StringPieceType& chrome_test_data_relative_root);
   IsolatedWebAppUrlInfo InstallDevModeProxyIsolatedWebApp(
       const url::Origin& origin);
-  content::RenderFrameHost* OpenApp(const AppId& app_id,
+  content::RenderFrameHost* OpenApp(const webapps::AppId& app_id,
                                     base::StringPiece path = "");
   content::RenderFrameHost* NavigateToURLInNewTab(
       Browser* window,
@@ -72,7 +72,7 @@
     const url::Origin& proxy_origin);
 
 content::RenderFrameHost* OpenIsolatedWebApp(Profile* profile,
-                                             const AppId& app_id,
+                                             const webapps::AppId& app_id,
                                              base::StringPiece path = "");
 
 void CreateIframe(content::RenderFrameHost* parent_frame,
@@ -82,7 +82,7 @@
 
 // Adds an Isolated Web App to the WebAppRegistrar. The IWA will have an empty
 // filepath for |IsolatedWebAppLocation|.
-AppId AddDummyIsolatedAppToRegistry(
+webapps::AppId AddDummyIsolatedAppToRegistry(
     Profile* profile,
     const GURL& start_url,
     const std::string& name,
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
index b189516..c85bf23f 100644
--- a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
+++ b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
@@ -558,8 +558,8 @@
     run_loop.Run();
   }
 
-  AppId GetAppId(Profile* profile) {
-    absl::optional<AppId> app_id =
+  webapps::AppId GetAppId(Profile* profile) {
+    absl::optional<webapps::AppId> app_id =
         ash::SystemWebAppManager::Get(profile)->GetAppIdForSystemApp(
             installation_->GetType());
     CHECK(app_id.has_value());
@@ -567,7 +567,7 @@
   }
 
   Browser* LaunchAppOnProfile(Profile* profile) {
-    AppId app_id = GetAppId(profile);
+    webapps::AppId app_id = GetAppId(profile);
 
     auto launch_params = apps::AppLaunchParams(
         app_id, apps::LaunchContainer::kLaunchContainerWindow,
@@ -678,8 +678,8 @@
   Profile* profile2 = ash::ProfileHelper::Get()->GetProfileByUser(
       user_manager->FindUser(account_id2_));
   WaitForSystemWebAppInstall(profile2);
-  const AppId& app_id1 = GetAppId(profile1);
-  const AppId& app_id2 = GetAppId(profile2);
+  const webapps::AppId& app_id1 = GetAppId(profile1);
+  const webapps::AppId& app_id2 = GetAppId(profile2);
 
   g_browser_process->profile_manager()
       ->GetDeleteProfileHelper()
@@ -820,7 +820,8 @@
   EXPECT_EQ(web_contents->GetLastCommittedURL(), GetStartUrl());
   EXPECT_EQ(1, browser()->tab_strip_model()->count());
 
-  // Verifies the tab has an associated tab helper for System App's AppId.
+  // Verifies the tab has an associated tab helper for System App's
+  // webapps::AppId.
   EXPECT_EQ(*web_app::WebAppTabHelper::GetAppId(web_contents),
             *ash::GetAppIdForSystemWebApp(browser()->profile(), GetAppType()));
 }
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
index c09bd3eb..3bb60fa1 100644
--- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
+++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
@@ -91,10 +91,10 @@
 
 }  // namespace
 
-AppId InstallWebAppFromPage(Browser* browser, const GURL& app_url) {
+webapps::AppId InstallWebAppFromPage(Browser* browser, const GURL& app_url) {
   NavigateToURLAndWait(browser, app_url);
 
-  AppId app_id;
+  webapps::AppId app_id;
   base::RunLoop run_loop;
 
   auto* provider = WebAppProvider::GetForTest(browser->profile());
@@ -106,7 +106,7 @@
       /*bypass_service_worker_check=*/false,
       base::BindOnce(&AutoAcceptDialogCallback),
       base::BindLambdaForTesting(
-          [&run_loop, &app_id](const AppId& installed_app_id,
+          [&run_loop, &app_id](const webapps::AppId& installed_app_id,
                                webapps::InstallResultCode code) {
             DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             app_id = installed_app_id;
@@ -118,8 +118,8 @@
   return app_id;
 }
 
-AppId InstallWebAppFromPageAndCloseAppBrowser(Browser* browser,
-                                              const GURL& app_url) {
+webapps::AppId InstallWebAppFromPageAndCloseAppBrowser(Browser* browser,
+                                                       const GURL& app_url) {
   // Create new tab to navigate, install, automatically pop out and then
   // close. This sequence avoids altering the browser window state it started
   // with.
@@ -128,7 +128,7 @@
 
   ui_test_utils::BrowserChangeObserver observer(
       nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-  AppId app_id = InstallWebAppFromPage(browser, app_url);
+  webapps::AppId app_id = InstallWebAppFromPage(browser, app_url);
 
   Browser* app_browser = observer.Wait();
   DCHECK_NE(app_browser, browser);
@@ -138,13 +138,14 @@
   return app_id;
 }
 
-AppId InstallWebAppFromManifest(Browser* browser, const GURL& app_url) {
+webapps::AppId InstallWebAppFromManifest(Browser* browser,
+                                         const GURL& app_url) {
   ServiceWorkerRegistrationWaiter registration_waiter(browser->profile(),
                                                       app_url);
   NavigateToURLAndWait(browser, app_url);
   registration_waiter.AwaitRegistration();
 
-  AppId app_id;
+  webapps::AppId app_id;
   base::RunLoop run_loop;
 
   auto* provider = WebAppProvider::GetForTest(browser->profile());
@@ -156,7 +157,7 @@
       /*bypass_service_worker_check=*/false,
       base::BindOnce(&AutoAcceptDialogCallback),
       base::BindLambdaForTesting(
-          [&run_loop, &app_id](const AppId& installed_app_id,
+          [&run_loop, &app_id](const webapps::AppId& installed_app_id,
                                webapps::InstallResultCode code) {
             DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             app_id = installed_app_id;
@@ -169,7 +170,7 @@
 }
 
 Browser* LaunchWebAppBrowser(Profile* profile,
-                             const AppId& app_id,
+                             const webapps::AppId& app_id,
                              WindowOpenDisposition disposition) {
   content::WebContents* web_contents =
       apps::AppServiceProxyFactory::GetForProfile(profile)
@@ -185,7 +186,7 @@
 
 // Launches the app, waits for the app url to load.
 Browser* LaunchWebAppBrowserAndWait(Profile* profile,
-                                    const AppId& app_id,
+                                    const webapps::AppId& app_id,
                                     WindowOpenDisposition disposition) {
   ui_test_utils::UrlLoadObserver url_observer(
       WebAppProvider::GetForTest(profile)->registrar_unsafe().GetAppLaunchUrl(
@@ -197,7 +198,8 @@
   return app_browser;
 }
 
-Browser* LaunchBrowserForWebAppInTab(Profile* profile, const AppId& app_id) {
+Browser* LaunchBrowserForWebAppInTab(Profile* profile,
+                                     const webapps::AppId& app_id) {
   content::WebContents* web_contents =
       apps::AppServiceProxyFactory::GetForProfile(profile)
           ->BrowserAppLauncher()
@@ -216,7 +218,7 @@
 }
 
 Browser* LaunchWebAppToURL(Profile* profile,
-                           const AppId& app_id,
+                           const webapps::AppId& app_id,
                            const GURL& url) {
   apps::AppLaunchParams params(
       app_id, apps::LaunchContainer::kLaunchContainerWindow,
@@ -327,7 +329,7 @@
   return model->IsEnabledAt(index) ? kEnabled : kDisabled;
 }
 
-Browser* FindWebAppBrowser(Profile* profile, const AppId& app_id) {
+Browser* FindWebAppBrowser(Profile* profile, const webapps::AppId& app_id) {
   for (auto* browser : *BrowserList::GetInstance()) {
     if (browser->profile() != profile)
       continue;
@@ -353,7 +355,7 @@
   return false;
 }
 
-absl::optional<AppId> ForceInstallWebApp(Profile* profile, GURL url) {
+absl::optional<webapps::AppId> ForceInstallWebApp(Profile* profile, GURL url) {
   web_app::ExternalInstallOptions install_options(
       url, web_app::mojom::UserDisplayMode::kStandalone,
       web_app::ExternalInstallSource::kExternalPolicy);
@@ -362,7 +364,7 @@
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
   const auto& registrar =
       WebAppProvider::GetForTest(profile)->registrar_unsafe();
-  absl::optional<web_app::AppId> policy_app_id =
+  absl::optional<webapps::AppId> policy_app_id =
       registrar.LookupExternalAppId(url);
   EXPECT_TRUE(policy_app_id.has_value());
   EXPECT_TRUE(
@@ -416,7 +418,7 @@
   run_loop_.Run(location);
 }
 
-void UpdateAwaiter::OnWebAppManifestUpdated(const AppId& app_id) {
+void UpdateAwaiter::OnWebAppManifestUpdated(const webapps::AppId& app_id) {
   run_loop_.Quit();
 }
 
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h
index b4cbc57..290d584 100644
--- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h
+++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/window_open_disposition.h"
 
@@ -41,35 +42,35 @@
 
 // Navigates to |app_url| and installs app without any installability checks.
 // Always selects to open app in its own window.
-AppId InstallWebAppFromPage(Browser* browser, const GURL& app_url);
+webapps::AppId InstallWebAppFromPage(Browser* browser, const GURL& app_url);
 
 // Same as InstallWebAppFromPage() but waits for the app browser window to
 // appear and closes it.
-AppId InstallWebAppFromPageAndCloseAppBrowser(Browser* browser,
-                                              const GURL& app_url);
+webapps::AppId InstallWebAppFromPageAndCloseAppBrowser(Browser* browser,
+                                                       const GURL& app_url);
 
 // Navigates to |app_url|, verifies WebApp installability, and installs app.
-AppId InstallWebAppFromManifest(Browser* browser, const GURL& app_url);
+webapps::AppId InstallWebAppFromManifest(Browser* browser, const GURL& app_url);
 
 // Launches a new app window for |app| in |profile| with specified
 // |disposition|.
 Browser* LaunchWebAppBrowser(
     Profile*,
-    const AppId&,
+    const webapps::AppId&,
     WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB);
 
 // Launches the app, waits for the app url to load.
 Browser* LaunchWebAppBrowserAndWait(
     Profile*,
-    const AppId&,
+    const webapps::AppId&,
     WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB);
 
 // Launches a new tab for |app| in |profile|.
-Browser* LaunchBrowserForWebAppInTab(Profile*, const AppId&);
+Browser* LaunchBrowserForWebAppInTab(Profile*, const webapps::AppId&);
 
 // Launches the web app to the given URL.
 Browser* LaunchWebAppToURL(Profile* profile,
-                           const AppId& app_id,
+                           const webapps::AppId& app_id,
                            const GURL& url);
 
 // Return |ExternalInstallOptions| with OS shortcut creation disabled.
@@ -110,7 +111,7 @@
 
 // Searches for a Browser window for a given |app_id|. browser->app_name() must
 // be defined.
-Browser* FindWebAppBrowser(Profile* profile, const AppId& app_id);
+Browser* FindWebAppBrowser(Profile* profile, const webapps::AppId& app_id);
 
 void CloseAndWait(Browser* browser);
 
@@ -118,7 +119,7 @@
 
 // Install a web policy app with |url|.
 // Returns a valid app ID of the installed app or nullopt.
-absl::optional<AppId> ForceInstallWebApp(Profile* profile, GURL url);
+absl::optional<webapps::AppId> ForceInstallWebApp(Profile* profile, GURL url);
 
 // Helper class that lets you await one Browser added and one Browser removed
 // event. Optionally filters to a specific Browser with |filter|. Useful for
@@ -154,7 +155,7 @@
   void AwaitUpdate(const base::Location& location = base::Location::Current());
 
   // WebAppInstallManagerObserver:
-  void OnWebAppManifestUpdated(const AppId& app_id) override;
+  void OnWebAppManifestUpdated(const webapps::AppId& app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
 
  private:
diff --git a/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc b/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
index 85aceef..37a36c5 100644
--- a/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
+++ b/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
@@ -248,7 +248,7 @@
 #if BUILDFLAG(IS_CHROMEOS)
   auto* const provider = WebAppProvider::GetForWebApps(profile());
   const WebAppRegistrar& registrar = provider->registrar_unsafe();
-  std::vector<AppId> app_ids = registrar.GetAppIds();
+  std::vector<webapps::AppId> app_ids = registrar.GetAppIds();
   for (const auto& app_id : app_ids) {
     if (!registrar.IsInstalled(app_id)) {
       continue;
@@ -280,7 +280,7 @@
   test_web_app_ = InstallTestWebApp(GetAppUrlHost(), GetAppScopePath());
 }
 
-AppId WebAppNavigationBrowserTest::InstallTestWebApp(
+webapps::AppId WebAppNavigationBrowserTest::InstallTestWebApp(
     const std::string& app_host,
     const std::string& app_scope) {
   if (!https_server_.Started()) {
@@ -295,7 +295,8 @@
   web_app_info->user_display_mode =
       web_app::mojom::UserDisplayMode::kStandalone;
 
-  AppId app_id = test::InstallWebApp(profile(), std::move(web_app_info));
+  webapps::AppId app_id =
+      test::InstallWebApp(profile(), std::move(web_app_info));
   DCHECK(!app_id.empty());
   apps::AppReadinessWaiter(profile(), app_id).Await();
   return app_id;
diff --git a/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.h b/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.h
index e9edb9f..f240d9d 100644
--- a/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.h
+++ b/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/content_mock_cert_verifier.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/gurl.h"
@@ -106,8 +107,8 @@
   Profile* profile();
 
   void InstallTestWebApp();
-  AppId InstallTestWebApp(const std::string& app_host,
-                          const std::string& app_scope);
+  webapps::AppId InstallTestWebApp(const std::string& app_host,
+                                   const std::string& app_scope);
 
   Browser* OpenTestWebApp();
 
@@ -129,7 +130,7 @@
 
   net::EmbeddedTestServer& https_server() { return https_server_; }
 
-  const AppId& test_web_app_id() const { return test_web_app_; }
+  const webapps::AppId& test_web_app_id() const { return test_web_app_; }
 
   const GURL& test_web_app_start_url();
 
@@ -139,7 +140,7 @@
   // used by the NetworkService.
   content::ContentMockCertVerifier cert_verifier_;
   raw_ptr<Profile, DanglingUntriaged> profile_ = nullptr;
-  AppId test_web_app_;
+  webapps::AppId test_web_app_;
   base::HistogramTester histogram_tester_;
 };
 
diff --git a/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc b/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc
index fda6447..abec8e0 100644
--- a/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc
@@ -163,7 +163,7 @@
         set_badge_change.was_flagged_ =
             set_badge_change.last_badge_content_ == absl::nullopt;
 
-        const AppId& set_app_id = set_app_badge.first;
+        const webapps::AppId& set_app_id = set_app_badge.first;
         ASSERT_TRUE(badge_change_map_.find(set_app_id) ==
                     badge_change_map_.end())
             << "ERROR: Cannot record badge set.  App with ID: '" << set_app_id
@@ -236,9 +236,9 @@
         main_frame_, expected_badge_change_count);
   }
 
-  const AppId& main_app_id() { return main_app_id_; }
-  const AppId& sub_app_id() { return sub_app_id_; }
-  const AppId& cross_site_app_id() { return cross_site_app_id_; }
+  const webapps::AppId& main_app_id() { return main_app_id_; }
+  const webapps::AppId& sub_app_id() { return sub_app_id_; }
+  const webapps::AppId& cross_site_app_id() { return cross_site_app_id_; }
 
   raw_ptr<RenderFrameHost, AcrossTasksDanglingUntriaged> main_frame_ = nullptr;
   raw_ptr<RenderFrameHost, AcrossTasksDanglingUntriaged> sub_app_frame_ =
@@ -271,12 +271,12 @@
   };
 
   // Records a single badge update for multiple apps.
-  std::unordered_map<AppId, BadgeChange> badge_change_map_;
+  std::unordered_map<webapps::AppId, BadgeChange> badge_change_map_;
 
   // Gets the recorded badge update for |app_id| from |badge_change_map_|.
   // Asserts when no recorded badge update exists for |app_id|.  Calls should be
   // wrapped in the ASSERT_NO_FATAL_FAILURE() macro.
-  void GetBadgeChange(const AppId& app_id, BadgeChange* result) {
+  void GetBadgeChange(const webapps::AppId& app_id, BadgeChange* result) {
     auto it = badge_change_map_.find(app_id);
 
     ASSERT_NE(it, badge_change_map_.end())
@@ -286,9 +286,9 @@
   }
 
  private:
-  AppId main_app_id_;
-  AppId sub_app_id_;
-  AppId cross_site_app_id_;
+  webapps::AppId main_app_id_;
+  webapps::AppId sub_app_id_;
+  webapps::AppId cross_site_app_id_;
   std::unique_ptr<base::RunLoop> awaiter_;
   raw_ptr<badging::TestBadgeManagerDelegate, AcrossTasksDanglingUntriaged>
       delegate_ = nullptr;
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.cc b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
index f5861276..2efcf76 100644
--- a/chrome/browser/ui/web_applications/web_app_browser_controller.cc
+++ b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -41,6 +40,7 @@
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/site_isolation_policy.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
@@ -118,7 +118,7 @@
 WebAppBrowserController::WebAppBrowserController(
     WebAppProvider& provider,
     Browser* browser,
-    AppId app_id,
+    webapps::AppId app_id,
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     const ash::SystemWebAppDelegate* system_app,
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -178,7 +178,7 @@
       "WebAppBrowserController::ToggleWindowControlsOverlayEnabled",
       std::make_unique<AppLockDescription>(app_id()),
       base::BindOnce(
-          [](base::OnceClosure on_complete, const AppId& app_id,
+          [](base::OnceClosure on_complete, const webapps::AppId& app_id,
              AppLock& lock) {
             lock.sync_bridge().SetAppWindowControlsOverlayEnabled(
                 app_id,
@@ -250,7 +250,7 @@
       "WebAppBrowserController::ToggleAlwaysShowToolbarInFullscreen",
       std::make_unique<AppLockDescription>(app_id()),
       base::BindOnce(
-          [](const AppId& app_id, AppLock& lock) {
+          [](const webapps::AppId& app_id, AppLock& lock) {
             lock.sync_bridge().SetAlwaysShowToolbarInFullscreen(
                 app_id,
                 !lock.registrar().AlwaysShowToolbarInFullscreen(app_id));
@@ -313,14 +313,14 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
 void WebAppBrowserController::OnWebAppUninstalled(
-    const AppId& uninstalled_app_id,
+    const webapps::AppId& uninstalled_app_id,
     webapps::WebappUninstallSource uninstall_source) {
   if (uninstalled_app_id == app_id())
     chrome::CloseWindow(browser());
 }
 
 void WebAppBrowserController::OnWebAppManifestUpdated(
-    const AppId& updated_app_id) {
+    const webapps::AppId& updated_app_id) {
   if (updated_app_id == app_id()) {
     UpdateThemePack();
     app_icon_.reset();
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.h b/chrome/browser/ui/web_applications/web_app_browser_controller.h
index 9279a14..c30e7657 100644
--- a/chrome/browser/ui/web_applications/web_app_browser_controller.h
+++ b/chrome/browser/ui/web_applications/web_app_browser_controller.h
@@ -23,6 +23,7 @@
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/liburlpattern/options.h"
 #include "third_party/liburlpattern/pattern.h"
@@ -67,7 +68,7 @@
  public:
   WebAppBrowserController(WebAppProvider& provider,
                           Browser* browser,
-                          AppId app_id,
+                          webapps::AppId app_id,
 #if BUILDFLAG(IS_CHROMEOS_ASH)
                           const ash::SystemWebAppDelegate* system_app,
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -129,9 +130,9 @@
 
   // WebAppInstallManagerObserver:
   void OnWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
-  void OnWebAppManifestUpdated(const AppId& app_id) override;
+  void OnWebAppManifestUpdated(const webapps::AppId& app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
 
   base::CallbackListSubscription AddHomeTabIconLoadCallbackForTesting(
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index bbccc1a0f..3acf6bd 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -75,7 +75,6 @@
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
@@ -89,6 +88,7 @@
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/webapps/browser/features.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
@@ -221,7 +221,7 @@
       web_app_info->display_override.push_back(*display_override_mode);
     }
 
-    AppId app_id = InstallWebApp(std::move(web_app_info));
+    webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
     Browser* app_browser = LaunchWebAppBrowser(app_id);
     DCHECK(app_browser->is_type_app());
     DCHECK(app_browser->app_controller());
@@ -287,7 +287,7 @@
     web_app::UpdateWebAppInfoFromManifest(manifest, GURL(kExampleManifestURL),
                                           web_app_info.get());
 
-    AppId app_id = InstallWebApp(std::move(web_app_info));
+    webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
     Browser* app_browser = LaunchWebAppBrowser(app_id);
 
     EXPECT_EQ(GetAppIdFromApplicationName(app_browser->app_name()), app_id);
@@ -299,7 +299,7 @@
         GURL("http://example.org/2"));
     web_app_info->scope = GURL("http://example.org/");
     web_app_info->theme_color = absl::optional<SkColor>();
-    AppId app_id = InstallWebApp(std::move(web_app_info));
+    webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
     Browser* app_browser = LaunchWebAppBrowser(app_id);
 
     EXPECT_EQ(GetAppIdFromApplicationName(app_browser->app_name()), app_id);
@@ -318,7 +318,7 @@
       std::make_unique<WebAppInstallInfo>(manifest.id, manifest.start_url);
   web_app::UpdateWebAppInfoFromManifest(manifest, GURL(kExampleManifestURL),
                                         web_app_info.get());
-  AppId app_id = InstallWebApp(std::move(web_app_info));
+  webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
 
   auto* provider = WebAppProvider::GetForTest(profile());
   EXPECT_EQ(provider->registrar_unsafe().GetAppBackgroundColor(app_id),
@@ -327,7 +327,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, ShortcutBackgroundColor) {
   const GURL app_url = https_server()->GetURL("/banners/background-color.html");
-  const AppId app_id = InstallWebAppFromPage(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromPage(browser(), app_url);
   auto* provider = WebAppProvider::GetForTest(profile());
 
   EXPECT_EQ(provider->registrar_unsafe().GetAppBackgroundColor(app_id),
@@ -337,7 +337,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, ManifestWithColor) {
   const GURL app_url =
       https_server()->GetURL("/banners/no-sw-with-colors.html");
-  const AppId app_id = InstallWebAppFromPage(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromPage(browser(), app_url);
   auto* provider = WebAppProvider::GetForTest(profile());
 
   EXPECT_EQ(provider->registrar_unsafe().GetAppBackgroundColor(app_id),
@@ -357,7 +357,7 @@
   web_app_info->background_color = SK_ColorWHITE;
   web_app_info->dark_mode_background_color = SK_ColorBLACK;
 
-  const AppId app_id = InstallWebApp(std::move(web_app_info));
+  const webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
 
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
   content::WebContents* const web_contents =
@@ -402,8 +402,8 @@
   }
 
   // Installs the web app under test, blocking until installation is complete,
-  // and returning the `AppId` for the installed web app.
-  AppId WaitForSwaInstall() {
+  // and returning the `webapps::AppId` for the installed web app.
+  webapps::AppId WaitForSwaInstall() {
     system_web_app_installation_->WaitForAppInstall();
     return system_web_app_installation_->GetAppId();
   }
@@ -468,7 +468,7 @@
 // Also see WebAppBrowserTest.BackgroundColorChange above.
 IN_PROC_BROWSER_TEST_P(BackgroundColorChangeSystemWebAppBrowserTest,
                        BackgroundColorChange) {
-  const AppId app_id = WaitForSwaInstall();
+  const webapps::AppId app_id = WaitForSwaInstall();
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
   content::WebContents* const web_contents =
       app_browser->tab_strip_model()->GetActiveWebContents();
@@ -521,7 +521,7 @@
                          });
 
 IN_PROC_BROWSER_TEST_P(DynamicColorSystemWebAppBrowserTest, Colors) {
-  const AppId app_id = WaitForSwaInstall();
+  const webapps::AppId app_id = WaitForSwaInstall();
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
   auto* app_controller = app_browser->app_controller();
   auto theme_color = app_controller->GetThemeColor().value();
@@ -548,7 +548,7 @@
 
   auto web_app_info =
       WebAppInstallInfo::CreateWithStartUrlForTesting(GURL(kExampleURL));
-  AppId app_id = InstallWebApp(std::move(web_app_info));
+  webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
 
   LaunchWebAppBrowser(app_id);
 }
@@ -556,7 +556,7 @@
 // Check the 'Open in Chrome' menu button for web app windows.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, OpenInChrome) {
   const GURL app_url(kExampleURL);
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   {
     Browser* const app_browser = LaunchWebAppBrowser(app_id);
@@ -594,7 +594,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, MAYBE_AppInfoOpensPageInfo) {
   const GURL app_url(kExampleURL);
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
 
   base::RunLoop run_loop_dialog_created;
@@ -612,7 +612,7 @@
 // Check that last launch time is set after launch.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, AppLastLaunchTime) {
   const GURL app_url(kExampleURL);
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   auto* provider = WebAppProvider::GetForTest(profile());
 
   // last_launch_time is not set before launch
@@ -656,7 +656,7 @@
       "manifest_test_page.html?manifest=manifest_display_override.json");
   NavigateToURLAndWait(browser(), test_url);
 
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   auto* provider = WebAppProvider::GetForTest(profile());
 
   std::vector<DisplayMode> app_display_mode_override =
@@ -704,7 +704,7 @@
 // Tests that desktop PWAs open out-of-scope links with a custom toolbar.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, DesktopPWAsOpenLinksInApp) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
   NavigateToURLAndWait(app_browser, app_url);
   ASSERT_TRUE(app_browser->app_controller());
@@ -715,7 +715,7 @@
 // the last active browser.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, DesktopPWAsOpenLinksInNewTab) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
   NavigateToURLAndWait(app_browser, app_url);
   ASSERT_TRUE(app_browser->app_controller());
@@ -748,7 +748,7 @@
 // Tests that desktop PWAs are opened at the correct size.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, PWASizeIsCorrectlyRestored) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   EXPECT_TRUE(AppBrowserController::IsWebApp(app_browser));
@@ -774,7 +774,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest,
                        MAYBE_OffScopePWAPopupsHaveCorrectSize) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
 
   EXPECT_TRUE(AppBrowserController::IsWebApp(app_browser));
@@ -814,7 +814,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest,
                        MAYBE_InScopePWAPopupsHaveCorrectSize) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
 
   EXPECT_TRUE(AppBrowserController::IsWebApp(app_browser));
@@ -843,7 +843,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest,
                        LocationBarIsVisibleOffScopeOnSameOrigin) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   // Toolbar should not be visible in the app.
@@ -865,7 +865,7 @@
   rep.SetSchemeStr(url::kHttpScheme);
   const GURL app_url = secure_app_url.ReplaceComponents(rep);
 
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
   NavigateToURLAndWait(app_browser, secure_app_url);
 
@@ -879,7 +879,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, OverscrollEnabled) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   // Overscroll is only enabled on Aura platforms currently.
@@ -893,7 +893,7 @@
 // Check the 'Copy URL' menu button for Web App windows.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, CopyURL) {
   const GURL app_url(kExampleURL);
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   content::BrowserTestClipboardScope test_clipboard_scope;
@@ -910,7 +910,7 @@
 // incognito.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, PopOutDisabledInIncognito) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   Browser* const incognito_browser = OpenURLOffTheRecord(profile(), app_url);
   auto app_menu_model =
@@ -926,7 +926,7 @@
 // Tests that web app menus don't crash when no tabs are selected.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, NoTabSelectedMenuCrash) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   app_browser->tab_strip_model()->CloseAllTabs();
@@ -944,7 +944,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, MAYBE_UninstallMenuOption) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   auto app_menu_model = std::make_unique<WebAppMenuModel>(
@@ -1051,7 +1051,7 @@
   base::UserActionTester user_action_tester;
   NavigateToURLAndWait(browser(), GetInstallableAppURL());
 
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   auto* provider = WebAppProvider::GetForTest(profile());
   EXPECT_EQ(provider->registrar_unsafe().GetAppShortName(app_id),
             GetInstallableAppName());
@@ -1089,7 +1089,7 @@
   base::Time before_install_time = base::Time::Now();
   NavigateToURLAndWait(browser(), GetInstallableAppURL());
 
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   auto* provider = WebAppProvider::GetForTest(profile());
   EXPECT_EQ(provider->registrar_unsafe().GetAppShortName(app_id),
             GetInstallableAppName());
@@ -1131,7 +1131,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, CanInstallOverBrowserTabPwa) {
   NavigateToURLAndWait(browser(), GetInstallableAppURL());
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
 
   // Change display mode to open in tab.
   auto* provider = WebAppProvider::GetForTest(profile());
@@ -1165,7 +1165,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, NoOpenInAppForBrowserTabPwa) {
   GURL app_url = https_server()->GetURL(
       "/web_apps/get_manifest.html?display_browser.json");
-  AppId app_id = InstallWebAppFromPage(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromPage(browser(), app_url);
 
   // Change display mode to open in tab.
   auto* provider = WebAppProvider::GetForTest(profile());
@@ -1221,7 +1221,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, WindowsOffsetForMultiWindowPWA) {
   const GURL app_url(kExampleURL);
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   Browser* first_browser = LaunchWebAppBrowserAndWait(app_id);
   // We should have the original (tabbed) browser for this BrowserTest, plus a
@@ -1280,7 +1280,7 @@
   ExternallyManagedAppManagerInstall(profile(), options);
 
   auto* provider = WebAppProvider::GetForTest(browser()->profile());
-  AppId app_id =
+  webapps::AppId app_id =
       provider->registrar_unsafe().LookupExternalAppId(install_url).value();
 
   EXPECT_FALSE(provider->registrar_unsafe().CanUserUninstallWebApp(app_id));
@@ -1299,7 +1299,7 @@
 // pages in an app's scope.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, ReparentWebAppForSecureActiveTab) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   NavigateToURLAndWait(browser(), app_url);
   content::WebContents* tab_contents =
@@ -1326,10 +1326,12 @@
   // Wait for OS hooks and installation to complete and the app to launch.
   base::RunLoop run_loop_install;
   WebAppInstallManagerObserverAdapter observer(profile());
-  observer.SetWebAppInstalledWithOsHooksDelegate(base::BindLambdaForTesting(
-      [&](const AppId& installed_app_id) { run_loop_install.Quit(); }));
+  observer.SetWebAppInstalledWithOsHooksDelegate(
+      base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id) {
+        run_loop_install.Quit();
+      }));
   content::CreateAndLoadWebContentsObserver app_loaded_observer;
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   run_loop_install.Run();
   app_loaded_observer.Wait();
 
@@ -1411,14 +1413,14 @@
   base::RunLoop run_loop_install;
   WebAppInstallManagerObserverAdapter observer(profile());
   observer.SetWebAppInstalledWithOsHooksDelegate(
-      base::BindLambdaForTesting([&](const AppId& installed_app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id) {
         EXPECT_THAT(
             tester.GetAllSamples("WebApp.ShortcutsMenuRegistration.Result"),
             BucketsAre(base::Bucket(true, 1)));
         run_loop_install.Quit();
       }));
   content::CreateAndLoadWebContentsObserver app_loaded_observer;
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   run_loop_install.Run();
   app_loaded_observer.Wait();
 
@@ -1486,7 +1488,7 @@
   base::RunLoop run_loop_install;
   WebAppInstallManagerObserverAdapter observer(profile());
   observer.SetWebAppInstalledWithOsHooksDelegate(
-      base::BindLambdaForTesting([&](const AppId& installed_app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id) {
         // Verify that since the shortcuts menu items are not registered,
         // none of the buckets are filled.
         EXPECT_THAT(
@@ -1495,7 +1497,7 @@
         run_loop_install.Quit();
       }));
   content::CreateAndLoadWebContentsObserver app_loaded_observer;
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   run_loop_install.Run();
   app_loaded_observer.Wait();
 
@@ -1538,10 +1540,12 @@
   // Wait for OS hooks and installation to complete and the app to launch.
   base::RunLoop run_loop_install;
   WebAppInstallManagerObserverAdapter observer(profile());
-  observer.SetWebAppInstalledWithOsHooksDelegate(base::BindLambdaForTesting(
-      [&](const AppId& installed_app_id) { run_loop_install.Quit(); }));
+  observer.SetWebAppInstalledWithOsHooksDelegate(
+      base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id) {
+        run_loop_install.Quit();
+      }));
   content::CreateAndLoadWebContentsObserver app_loaded_observer;
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   run_loop_install.Run();
   app_loaded_observer.Wait();
 
@@ -1594,7 +1598,7 @@
       registration = OsIntegrationTestOverrideImpl::OverrideForTesting();
 
   auto* provider = WebAppProvider::GetForTest(profile());
-  const AppId& app_id = InstallPWA(pwa_url);
+  const webapps::AppId& app_id = InstallPWA(pwa_url);
 
   ASSERT_TRUE(provider->registrar_unsafe().IsInstalled(app_id));
 
@@ -1622,7 +1626,7 @@
 // Tests that reparenting the last browser tab doesn't close the browser window.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, ReparentLastBrowserTab) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   NavigateToURLAndWait(browser(), app_url);
 
   Browser* const app_browser = ReparentWebAppForActiveTab(browser());
@@ -1664,7 +1668,7 @@
 
   WebAppProvider* provider = WebAppProvider::GetForTest(profile());
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode>
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
       install_future;
   provider->scheduler().FetchManifestAndInstall(
       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
@@ -1674,7 +1678,7 @@
       install_future.GetCallback(),
       /*use_fallback=*/false);
 
-  const AppId& app_id = install_future.Get<0>();
+  const webapps::AppId& app_id = install_future.Get<0>();
   EXPECT_EQ(provider->registrar_unsafe().GetAppShortName(app_id),
             GetInstallableAppName());
 
@@ -1746,7 +1750,7 @@
   web_app_info->display_mode = DisplayMode::kBrowser;
   web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
   web_app_info->title = u"A Shortcut App";
-  const AppId app_id = InstallWebApp(std::move(web_app_info));
+  const webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
 
   base::HistogramTester tester;
   NavigateToURLAndWait(browser(), app_url);
@@ -1807,7 +1811,7 @@
 // Check that no assertions are hit when showing a permission request bubble.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, PermissionBubble) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   content::RenderFrameHost* const render_frame_host =
@@ -1831,7 +1835,7 @@
   auto web_app_info = WebAppInstallInfo::CreateWithStartUrlForTesting(app_url);
   web_app_info->scope = app_url.GetWithoutFilename();
   web_app_info->title = app_title;
-  const AppId app_id = InstallWebApp(std::move(web_app_info));
+  const webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
 
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
   content::WebContents* const web_contents =
@@ -1854,7 +1858,7 @@
   auto web_app_info = WebAppInstallInfo::CreateWithStartUrlForTesting(app_url);
   web_app_info->scope = app_url.GetWithoutFilename();
   web_app_info->title = app_title;
-  const AppId app_id = InstallWebApp(std::move(web_app_info));
+  const webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
   content::WebContents* const web_contents =
       app_browser->tab_strip_model()->GetActiveWebContents();
@@ -1875,7 +1879,7 @@
   auto web_app_info = WebAppInstallInfo::CreateWithStartUrlForTesting(app_url);
   web_app_info->scope = app_url.GetWithoutFilename();
   web_app_info->title = app_title;
-  const AppId app_id = InstallWebApp(std::move(web_app_info));
+  const webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
 
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
   content::WebContents* const web_contents =
@@ -1902,7 +1906,7 @@
 
   auto web_app_info = WebAppInstallInfo::CreateWithStartUrlForTesting(app_url);
   web_app_info->title = app_title;
-  const AppId app_id = InstallWebApp(std::move(web_app_info));
+  const webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
 
   Browser* const app_browser = LaunchWebAppBrowser(app_id);
   content::WebContents* const web_contents =
@@ -1926,7 +1930,7 @@
 // WebApps should not have origin text with this feature on.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest_HideOrigin, OriginTextRemoved) {
   const GURL app_url = GetInstallableAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
   EXPECT_FALSE(app_browser->app_controller()->HasTitlebarAppOriginText());
 }
@@ -1938,7 +1942,7 @@
 
   // Set up a web app which covers app.com URLs.
   GURL app_url = embedded_test_server()->GetURL("app.com", "/title1.html");
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   // Navigate a regular tab to a page with a subframe.
   const GURL url = embedded_test_server()->GetURL("foo.com", "/iframe.html");
@@ -1967,7 +1971,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, NewAppWindow) {
   BrowserList* const browser_list = BrowserList::GetInstance();
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   EXPECT_EQ(browser_list->size(), 2U);
@@ -2010,7 +2014,7 @@
   const GURL app_url = GetSecureAppURL();
   const GURL in_scope =
       https_server()->GetURL("app.com", "/ssl/page_with_subresource.html");
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   Browser* const popup_browser = web_app::CreateWebApplicationWindow(
       profile(), app_id, WindowOpenDisposition::NEW_POPUP, /*restore_id=*/0);
@@ -2080,7 +2084,7 @@
       "manifest_test_page.html?manifest=manifest_window_controls_overlay.json");
   NavigateToURLAndWait(browser(), test_url);
 
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   auto* provider = WebAppProvider::GetForTest(profile());
 
   std::vector<DisplayMode> app_display_mode_override =
@@ -2100,7 +2104,7 @@
       "manifest_test_page.html?manifest=manifest_borderless.json");
   NavigateToURLAndWait(browser(), test_url);
 
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   auto* provider = WebAppProvider::GetForTest(profile());
 
   std::vector<DisplayMode> app_display_mode_override =
@@ -2121,7 +2125,7 @@
       "manifest_test_page.html?manifest=manifest_tabbed_display_override.json");
   NavigateToURLAndWait(browser(), test_url);
 
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   auto* provider = WebAppProvider::GetForTest(profile());
 
   std::vector<DisplayMode> app_display_mode_override =
@@ -2150,7 +2154,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest_NoDestroyProfile, Shutdown) {
   Profile* profile = browser()->profile();
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   apps::AppLaunchParams params(
       app_id, apps::LaunchContainer::kLaunchContainerWindow,
       WindowOpenDisposition::NEW_WINDOW, apps::LaunchSource::kFromTest);
@@ -2171,7 +2175,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest_ManifestId, NoManifestId) {
   NavigateToURLAndWait(browser(), GetInstallableAppURL());
 
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   auto* provider = WebAppProvider::GetForTest(profile());
   auto* app = provider->registrar_unsafe().GetAppById(app_id);
 
@@ -2188,7 +2192,7 @@
       https_server()->GetURL(
           "/banners/manifest_test_page.html?manifest=manifest_with_id.json"));
 
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   auto* provider = WebAppProvider::GetForTest(profile());
   auto* app = provider->registrar_unsafe().GetAppById(app_id);
 
@@ -2244,13 +2248,13 @@
   base::RunLoop run_loop_install;
   WebAppInstallManagerObserverAdapter observer(profile());
   observer.SetWebAppInstalledWithOsHooksDelegate(
-      base::BindLambdaForTesting([&](const AppId& installed_app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id) {
         EXPECT_THAT(
             tester.GetAllSamples("WebApp.FileHandlersRegistration.Result"),
             BucketsAre(base::Bucket(true, 1)));
         run_loop_install.Quit();
       }));
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   run_loop_install.Run();
   content::RunAllTasksUntilIdle();
   chrome::SetAutoAcceptWebAppDialogForTesting(false, false);
@@ -2342,9 +2346,11 @@
   chrome::SetAutoAcceptWebAppDialogForTesting(true, true);
   base::RunLoop run_loop_install;
   WebAppInstallManagerObserverAdapter observer(profile());
-  observer.SetWebAppInstalledWithOsHooksDelegate(base::BindLambdaForTesting(
-      [&](const AppId& installed_app_id) { run_loop_install.Quit(); }));
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  observer.SetWebAppInstalledWithOsHooksDelegate(
+      base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id) {
+        run_loop_install.Quit();
+      }));
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   run_loop_install.Run();
   content::RunAllTasksUntilIdle();
   chrome::SetAutoAcceptWebAppDialogForTesting(false, false);
@@ -2391,9 +2397,11 @@
   // Wait for OS hooks and installation to complete and the app to launch.
   base::RunLoop run_loop_install;
   WebAppInstallManagerObserverAdapter observer(profile());
-  observer.SetWebAppInstalledWithOsHooksDelegate(base::BindLambdaForTesting(
-      [&](const AppId& installed_app_id) { run_loop_install.Quit(); }));
-  const AppId app_id = test::InstallPwaForCurrentUrl(browser());
+  observer.SetWebAppInstalledWithOsHooksDelegate(
+      base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id) {
+        run_loop_install.Quit();
+      }));
+  const webapps::AppId app_id = test::InstallPwaForCurrentUrl(browser());
   run_loop_install.Run();
 
   EXPECT_TRUE(provider->registrar_unsafe().IsInstalled(app_id));
@@ -2418,7 +2426,7 @@
   // 2) It hasn't been uninstalled yet.
   // The test body here handles both cases, and ensures that the app has been
   // uninstalled.
-  std::set<AppId> apps;
+  std::set<webapps::AppId> apps;
   for (const auto& web_app :
        provider->registrar_unsafe().GetAppsIncludingStubs()) {
     EXPECT_TRUE(web_app.is_uninstalling());
@@ -2497,7 +2505,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest_PageInfoManagementLink, LaunchAsTab) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   // A non appy tab is showing, so the app settings link should not be visible.
   EXPECT_FALSE(ShowingAppManagementLink(browser()));
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
index abee201..659052c 100644
--- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
@@ -88,7 +88,7 @@
   return browser()->profile();
 }
 
-AppId WebAppControllerBrowserTest::InstallPWA(const GURL& start_url) {
+webapps::AppId WebAppControllerBrowserTest::InstallPWA(const GURL& start_url) {
   auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url.GetWithoutFilename();
@@ -97,27 +97,29 @@
   return web_app::test::InstallWebApp(profile(), std::move(web_app_info));
 }
 
-AppId WebAppControllerBrowserTest::InstallWebApp(
+webapps::AppId WebAppControllerBrowserTest::InstallWebApp(
     std::unique_ptr<WebAppInstallInfo> web_app_info) {
   return web_app::test::InstallWebApp(profile(), std::move(web_app_info));
 }
 
-void WebAppControllerBrowserTest::UninstallWebApp(const AppId& app_id) {
+void WebAppControllerBrowserTest::UninstallWebApp(
+    const webapps::AppId& app_id) {
   web_app::test::UninstallWebApp(profile(), app_id);
 }
 
-Browser* WebAppControllerBrowserTest::LaunchWebAppBrowser(const AppId& app_id) {
+Browser* WebAppControllerBrowserTest::LaunchWebAppBrowser(
+    const webapps::AppId& app_id) {
   return web_app::LaunchWebAppBrowser(profile(), app_id);
 }
 
 Browser* WebAppControllerBrowserTest::LaunchWebAppBrowserAndWait(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   return web_app::LaunchWebAppBrowserAndWait(profile(), app_id);
 }
 
 Browser*
 WebAppControllerBrowserTest::LaunchWebAppBrowserAndAwaitInstallabilityCheck(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   Browser* browser = web_app::LaunchWebAppBrowserAndWait(profile(), app_id);
   webapps::TestAppBannerManagerDesktop::FromWebContents(
       browser->tab_strip_model()->GetActiveWebContents())
@@ -126,7 +128,7 @@
 }
 
 Browser* WebAppControllerBrowserTest::LaunchBrowserForWebAppInTab(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   return web_app::LaunchBrowserForWebAppInTab(profile(), app_id);
 }
 
@@ -179,8 +181,8 @@
   return new_browser;
 }
 
-absl::optional<AppId> WebAppControllerBrowserTest::FindAppWithUrlInScope(
-    const GURL& url) {
+absl::optional<webapps::AppId>
+WebAppControllerBrowserTest::FindAppWithUrlInScope(const GURL& url) {
   return provider().registrar_unsafe().FindAppWithUrlInScope(url);
 }
 
@@ -212,7 +214,7 @@
 }
 
 content::WebContents* WebAppControllerBrowserTest::OpenApplication(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   ui_test_utils::UrlLoadObserver url_observer(
       provider().registrar_unsafe().GetAppStartUrl(app_id),
       content::NotificationService::AllSources());
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.h b/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
index 04e044d6..dff1e42 100644
--- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
+++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_ui_manager.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/content_mock_cert_verifier.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/gurl.h"
@@ -45,23 +46,24 @@
 
   Profile* profile();
 
-  AppId InstallPWA(const GURL& app_url);
+  webapps::AppId InstallPWA(const GURL& app_url);
 
-  AppId InstallWebApp(std::unique_ptr<WebAppInstallInfo> web_app_info);
+  webapps::AppId InstallWebApp(std::unique_ptr<WebAppInstallInfo> web_app_info);
 
-  void UninstallWebApp(const AppId& app_id);
+  void UninstallWebApp(const webapps::AppId& app_id);
 
   // Launches the app as a window and returns the browser.
-  Browser* LaunchWebAppBrowser(const AppId&);
+  Browser* LaunchWebAppBrowser(const webapps::AppId&);
 
   // Launches the app, waits for the app url to load.
-  Browser* LaunchWebAppBrowserAndWait(const AppId&);
+  Browser* LaunchWebAppBrowserAndWait(const webapps::AppId&);
 
   // Launches the app, waits for it to load and finish the installability check.
-  Browser* LaunchWebAppBrowserAndAwaitInstallabilityCheck(const AppId&);
+  Browser* LaunchWebAppBrowserAndAwaitInstallabilityCheck(
+      const webapps::AppId&);
 
   // Launches the app as a tab and returns the browser.
-  Browser* LaunchBrowserForWebAppInTab(const AppId&);
+  Browser* LaunchBrowserForWebAppInTab(const webapps::AppId&);
 
   // Simulates a page calling window.open on an URL and waits for the
   // navigation.
@@ -79,7 +81,7 @@
 
   Browser* NavigateInNewWindowAndAwaitInstallabilityCheck(const GURL&);
 
-  absl::optional<AppId> FindAppWithUrlInScope(const GURL& url);
+  absl::optional<webapps::AppId> FindAppWithUrlInScope(const GURL& url);
 
   // Opens |url| in a new popup window with the dimensions |popup_size|.
   Browser* OpenPopupAndWait(Browser* browser,
@@ -94,7 +96,7 @@
   absl::optional<OsIntegrationManager::ScopedSuppressForTesting>
       os_hooks_suppress_;
 
-  content::WebContents* OpenApplication(const AppId&);
+  content::WebContents* OpenApplication(const webapps::AppId&);
 
   net::EmbeddedTestServer* https_server() { return &https_server_; }
 
diff --git a/chrome/browser/ui/web_applications/web_app_dark_mode_browsertest.cc b/chrome/browser/ui/web_applications/web_app_dark_mode_browsertest.cc
index f21e533..4f115ce 100644
--- a/chrome/browser/ui/web_applications/web_app_dark_mode_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_dark_mode_browsertest.cc
@@ -34,7 +34,7 @@
       delete;
   ~WebAppDarkModeBrowserTest() override = default;
 
-  AppId InstallWebAppFromInfo() {
+  webapps::AppId InstallWebAppFromInfo() {
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     // We want to hang so WebContents does not update the background color.
     web_app_info->start_url = https_server()->GetURL("/hung");
@@ -48,7 +48,8 @@
     return web_app::test::InstallWebApp(profile(), std::move(web_app_info));
   }
 
-  AppId InstallWebAppFromPath(const char* path, bool await_metric = true) {
+  webapps::AppId InstallWebAppFromPath(const char* path,
+                                       bool await_metric = true) {
     GURL start_url = https_server()->GetURL(path);
     page_load_metrics::PageLoadMetricsTestWaiter metrics_waiter(
         browser()->tab_strip_model()->GetActiveWebContents());
@@ -56,7 +57,7 @@
       metrics_waiter.AddWebFeatureExpectation(
           blink::mojom::WebFeature::kWebAppManifestUserPreferences);
 
-    AppId app_id = InstallWebAppFromPage(browser(), start_url);
+    webapps::AppId app_id = InstallWebAppFromPage(browser(), start_url);
     if (await_metric)
       metrics_waiter.Wait();
 
@@ -71,7 +72,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(WebAppDarkModeBrowserTest, DarkColors) {
-  AppId app_id = InstallWebAppFromInfo();
+  webapps::AppId app_id = InstallWebAppFromInfo();
 
   WebAppBrowserController* controller;
   Browser* app_browser = LaunchWebAppBrowser(app_id);
@@ -87,7 +88,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppDarkModeBrowserTest, ColorSchemeDarkSet) {
-  AppId app_id = InstallWebAppFromPath(
+  webapps::AppId app_id = InstallWebAppFromPath(
       "/web_apps/get_manifest.html?color_scheme_dark.json");
 
   histogram_tester_.ExpectBucketCount(
@@ -110,7 +111,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppDarkModeBrowserTest, NoUserPreferences) {
-  AppId app_id =
+  webapps::AppId app_id =
       InstallWebAppFromPath("/web_apps/basic.html", /*await_metric=*/false);
 
   histogram_tester_.ExpectBucketCount(
@@ -221,7 +222,7 @@
       }));
 
   // Install web app with origin trial token.
-  AppId app_id =
+  webapps::AppId app_id =
       web_app::InstallWebAppFromPage(browser(), GURL(kTestWebAppUrl));
 
   // Origin trial should grant the app access.
diff --git a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
index a96dd65..6b372f6d 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
@@ -65,7 +65,7 @@
       if (base::FeatureList::IsEnabled(
               metrics::structured::kAppDiscoveryLogging) &&
           install_source == webapps::WebappInstallSource::MENU_BROWSER_TAB) {
-        web_app::AppId app_id =
+        webapps::AppId app_id =
             web_app::GenerateAppIdFromManifestId(web_app_info->manifest_id);
         cros_events::AppDiscovery_Browser_ClickInstallAppFromMenu()
             .SetAppId(app_id)
@@ -93,7 +93,7 @@
 #if BUILDFLAG(IS_CHROMEOS)
       if (base::FeatureList::IsEnabled(
               metrics::structured::kAppDiscoveryLogging)) {
-        web_app::AppId app_id =
+        webapps::AppId app_id =
             web_app::GenerateAppIdFromManifestId(web_app_info->manifest_id);
         cros_events::AppDiscovery_Browser_CreateShortcut()
             .SetAppId(app_id)
@@ -117,7 +117,7 @@
 }
 
 void OnWebAppInstalled(WebAppInstalledCallback callback,
-                       const AppId& installed_app_id,
+                       const webapps::AppId& installed_app_id,
                        webapps::InstallResultCode code) {
   if (GetInstalledCallbackForTesting())
     std::move(GetInstalledCallbackForTesting()).Run(installed_app_id, code);
diff --git a/chrome/browser/ui/web_applications/web_app_dialog_utils.h b/chrome/browser/ui/web_applications/web_app_dialog_utils.h
index 1b13cf95..3f3af2c7 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_utils.h
+++ b/chrome/browser/ui/web_applications/web_app_dialog_utils.h
@@ -9,6 +9,7 @@
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Browser;
 class Profile;
@@ -34,7 +35,7 @@
 bool CanPopOutWebApp(Profile* profile);
 
 using WebAppInstalledCallback =
-    base::OnceCallback<void(const AppId& app_id,
+    base::OnceCallback<void(const webapps::AppId& app_id,
                             webapps::InstallResultCode code)>;
 
 // Initiates user install of a WebApp for the current page.
diff --git a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
index cbc3154..3a1c9ef91 100644
--- a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
@@ -174,9 +174,9 @@
     web_app_metrics->CountUserInstalledAppsForTesting();
   }
 
-  AppId InstallWebAppAndCountApps(
+  webapps::AppId InstallWebAppAndCountApps(
       std::unique_ptr<WebAppInstallInfo> web_app_info) {
-    AppId app_id = InstallWebApp(std::move(web_app_info));
+    webapps::AppId app_id = InstallWebApp(std::move(web_app_info));
     CountUserInstalledApps();
     return app_id;
   }
@@ -202,7 +202,7 @@
   web_app_info->start_url = example_url;
   web_app_info->scope = example_url;
   web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
-  AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
+  webapps::AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
 
   Browser* app_browser = LaunchWebAppBrowserAndWait(app_id);
   NavigateToURLAndWait(app_browser, example_url);
@@ -235,7 +235,7 @@
   web_app_info->start_url = example_url;
   web_app_info->scope = example_url;
   web_app_info->user_display_mode = mojom::UserDisplayMode::kBrowser;
-  AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
+  webapps::AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
 
   Browser* browser = LaunchBrowserForWebAppInTab(app_id);
   EXPECT_FALSE(browser->app_controller());
@@ -271,7 +271,7 @@
   // the app is counted as installed via the Create Shortcut button.
   web_app_info->scope = GURL();
   web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
-  AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
+  webapps::AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
 
   Browser* browser = LaunchWebAppBrowserAndWait(app_id);
 
@@ -302,7 +302,7 @@
   const GURL example_url2 =
       embedded_test_server()->GetURL("/banners/scope_a/page_1.html");
 
-  AppId app_id1, app_id2;
+  webapps::AppId app_id1, app_id2;
 
   // Install two apps.
   {
@@ -352,7 +352,7 @@
   // A small number of launches, to avoid timeouts.
   const int num_launches = 2;
 
-  std::vector<AppId> app_ids;
+  std::vector<webapps::AppId> app_ids;
 
   // Install apps.
   const std::string base_url =
@@ -363,7 +363,7 @@
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = url;
     web_app_info->scope = url;
-    AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
+    webapps::AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
     app_ids.push_back(app_id);
   }
 
@@ -408,7 +408,7 @@
   ASSERT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
 
-  absl::optional<AppId> app_id = FindAppWithUrlInScope(example_url);
+  absl::optional<webapps::AppId> app_id = FindAppWithUrlInScope(example_url);
   ASSERT_TRUE(app_id);
   // TODO(ericwilligers): Assert app_id was installed by default.
 
@@ -443,7 +443,7 @@
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url;
   web_app_info->user_display_mode = mojom::UserDisplayMode::kBrowser;
-  AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
+  webapps::AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
 
   Browser* browser = LaunchBrowserForWebAppInTab(app_id);
   EXPECT_FALSE(browser->app_controller());
@@ -507,7 +507,7 @@
   auto result = ExternallyManagedAppManagerInstall(
       browser()->profile(), CreateInstallOptions(example_url));
   ASSERT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-  absl::optional<AppId> app_id = FindAppWithUrlInScope(example_url);
+  absl::optional<webapps::AppId> app_id = FindAppWithUrlInScope(example_url);
   ASSERT_TRUE(app_id);
   content::CreateAndLoadWebContentsObserver app_loaded_observer;
 
@@ -563,7 +563,7 @@
   auto result = ExternallyManagedAppManagerInstall(
       browser()->profile(), CreateInstallOptions(example_url));
   ASSERT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-  absl::optional<AppId> app_id = FindAppWithUrlInScope(example_url);
+  absl::optional<webapps::AppId> app_id = FindAppWithUrlInScope(example_url);
   ASSERT_TRUE(app_id);
   content::CreateAndLoadWebContentsObserver app_loaded_observer;
 
@@ -616,7 +616,7 @@
   auto result =
       ExternallyManagedAppManagerInstall(browser()->profile(), install_options);
   ASSERT_EQ(webapps::InstallResultCode::kSuccessNewInstall, result.code);
-  absl::optional<AppId> app_id = FindAppWithUrlInScope(example_url);
+  absl::optional<webapps::AppId> app_id = FindAppWithUrlInScope(example_url);
   ASSERT_TRUE(app_id);
   content::CreateAndLoadWebContentsObserver app_loaded_observer;
 
diff --git a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
index d496548..5955cdc 100644
--- a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
@@ -128,7 +128,7 @@
         WebAppControllerBrowserTest::InstallWebApp(std::move(web_app_info));
   }
 
-  AppId InstallAnotherFileHandlingPwa(const GURL& start_url) {
+  webapps::AppId InstallAnotherFileHandlingPwa(const GURL& start_url) {
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
@@ -146,10 +146,10 @@
   }
 
  protected:
-  const AppId& app_id() { return app_id_; }
+  const webapps::AppId& app_id() { return app_id_; }
 
  private:
-  AppId app_id_;
+  webapps::AppId app_id_;
 };
 
 namespace {
@@ -205,8 +205,8 @@
     }
   }
 
-  AppId InstallFileHandlingWebApp(const std::u16string& title,
-                                  const GURL& handler_url) {
+  webapps::AppId InstallFileHandlingWebApp(const std::u16string& title,
+                                           const GURL& handler_url) {
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url =
         https_server()->GetURL("app.com", "/web_app_file_handling/index.html");
@@ -326,7 +326,7 @@
                        LaunchQueueSetOnRedirect) {
   GURL handler_url = https_server()->GetURL(
       "app.com", "/web_app_file_handling/handle_files_with_redirect.html");
-  AppId app_id =
+  webapps::AppId app_id =
       InstallFileHandlingWebApp(u"An app that will be reloaded", handler_url);
 
   base::FilePath file = CreateTestFileWithExtension("txt");
@@ -349,7 +349,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppFileHandlingBrowserTest, LaunchQueueSetOnReload) {
   GURL handler_url = https_server()->GetURL(
       "app.com", "/web_app_file_handling/handle_files.html");
-  AppId app_id =
+  webapps::AppId app_id =
       InstallFileHandlingWebApp(u"An app that will be reloaded", handler_url);
 
   base::FilePath file = CreateTestFileWithExtension("txt");
@@ -371,7 +371,7 @@
                        LaunchQueueSetOnReloadAfterPushState) {
   GURL handler_url = https_server()->GetURL(
       "app.com", "/web_app_file_handling/handle_files.html");
-  AppId app_id =
+  webapps::AppId app_id =
       InstallFileHandlingWebApp(u"An app that will be reloaded", handler_url);
 
   base::FilePath file = CreateTestFileWithExtension("txt");
@@ -406,7 +406,7 @@
   GURL handler_url = https_server()->GetURL(
       "app.com",
       "/web_app_file_handling/handle_files_with_redirect_to_other_origin.html");
-  AppId app_id =
+  webapps::AppId app_id =
       InstallFileHandlingWebApp(u"An app that will be reloaded", handler_url);
   base::FilePath file = CreateTestFileWithExtension("txt");
 
@@ -431,7 +431,7 @@
       "app.com", "/web_app_file_handling/handle_files.html");
   GURL start_url =
       https_server()->GetURL("app.com", "/web_app_file_handling/index.html");
-  AppId app_id =
+  webapps::AppId app_id =
       InstallFileHandlingWebApp(u"An app that will be navigated", handler_url);
 
   base::FilePath file = CreateTestFileWithExtension("txt");
@@ -526,7 +526,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url(
       embedded_test_server()->GetURL("/web_app_file_handling/icons_app.html"));
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   auto* provider = WebAppProvider::GetForTest(browser()->profile());
   const WebApp* web_app = provider->registrar_unsafe().GetAppById(app_id);
   ASSERT_TRUE(web_app);
diff --git a/chrome/browser/ui/web_applications/web_app_interactive_uitest.cc b/chrome/browser/ui/web_applications/web_app_interactive_uitest.cc
index 0b17f90..ced52e5 100644
--- a/chrome/browser/ui/web_applications/web_app_interactive_uitest.cc
+++ b/chrome/browser/ui/web_applications/web_app_interactive_uitest.cc
@@ -57,7 +57,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Install test app.
-  const AppId app_id = InstallPWA(GURL(kExampleURL));
+  const webapps::AppId app_id = InstallPWA(GURL(kExampleURL));
 
   // Figure out what display the original tabbed browser was created on, as well
   // as what the display Id is for a second display.
diff --git a/chrome/browser/ui/web_applications/web_app_launch_handler_browsertest.cc b/chrome/browser/ui/web_applications/web_app_launch_handler_browsertest.cc
index 329cec0..dd9efc8 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_handler_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_handler_browsertest.cc
@@ -63,8 +63,8 @@
  protected:
   Profile* profile() { return browser()->profile(); }
 
-  AppId InstallTestWebApp(const char* test_file_path,
-                          bool await_metric = true) {
+  webapps::AppId InstallTestWebApp(const char* test_file_path,
+                                   bool await_metric = true) {
     BrowserWaiter browser_waiter;
 
     page_load_metrics::PageLoadMetricsTestWaiter metrics_waiter(
@@ -74,7 +74,7 @@
           blink::mojom::WebFeature::kWebAppManifestLaunchHandler);
     }
 
-    AppId app_id = InstallWebAppFromPage(
+    webapps::AppId app_id = InstallWebAppFromPage(
         browser(), embedded_test_server()->GetURL(test_file_path));
 
     if (await_metric)
@@ -89,16 +89,16 @@
     return app_id;
   }
 
-  const WebApp* GetWebApp(const AppId& app_id) {
+  const WebApp* GetWebApp(const webapps::AppId& app_id) {
     return WebAppProvider::GetForTest(profile())->registrar_unsafe().GetAppById(
         app_id);
   }
 
-  absl::optional<LaunchHandler> GetLaunchHandler(const AppId& app_id) {
+  absl::optional<LaunchHandler> GetLaunchHandler(const webapps::AppId& app_id) {
     return GetWebApp(app_id)->launch_handler();
   }
 
-  void ExpectNavigateNewBehavior(const AppId& app_id) {
+  void ExpectNavigateNewBehavior(const webapps::AppId& app_id) {
     std::string start_url = GetWebApp(app_id)->start_url().spec();
 
     Browser* browser_1 = LaunchWebAppBrowserAndWait(app_id);
@@ -144,7 +144,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest, ClientModeEmpty) {
   base::HistogramTester histogram_tester;
-  AppId app_id =
+  webapps::AppId app_id =
       InstallTestWebApp("/web_apps/basic.html", /*await_metric=*/false);
   EXPECT_EQ(GetLaunchHandler(app_id), absl::nullopt);
 
@@ -156,7 +156,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest, ClientModeAuto) {
   base::HistogramTester histogram_tester;
-  AppId app_id = InstallTestWebApp(
+  webapps::AppId app_id = InstallTestWebApp(
       "/web_apps/get_manifest.html?launch_handler_client_mode_auto.json");
   EXPECT_EQ(GetLaunchHandler(app_id), (LaunchHandler{ClientMode::kAuto}));
 
@@ -168,7 +168,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest, ClientModeNavigateNew) {
   base::HistogramTester histogram_tester;
-  AppId app_id = InstallTestWebApp(
+  webapps::AppId app_id = InstallTestWebApp(
       "/web_apps/get_manifest.html?"
       "launch_handler_client_mode_navigate_new.json");
   EXPECT_EQ(GetLaunchHandler(app_id),
@@ -182,7 +182,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest,
                        ClientModeNavigateExisting) {
-  AppId app_id = InstallTestWebApp(
+  webapps::AppId app_id = InstallTestWebApp(
       "/web_apps/get_manifest.html?"
       "launch_handler_client_mode_navigate_existing.json");
 
@@ -237,7 +237,7 @@
 // TODO(crbug.com/1308334): Fix flakiness.
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest,
                        DISABLED_ClientModeExistingClientRetain) {
-  AppId app_id = InstallTestWebApp(
+  webapps::AppId app_id = InstallTestWebApp(
       "/web_apps/get_manifest.html?"
       "launch_handler_client_mode_focus_existing.json");
 
@@ -314,7 +314,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest,
                        ClientModeFocusExistingMultipleLaunches) {
   base::HistogramTester histogram_tester;
-  AppId app_id = InstallTestWebApp(
+  webapps::AppId app_id = InstallTestWebApp(
       "/web_apps/get_manifest.html?"
       "launch_handler_client_mode_focus_existing.json");
   EXPECT_EQ(GetLaunchHandler(app_id),
@@ -366,7 +366,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest,
                        ClientModeNavigateExistingMultipleLaunches) {
   base::HistogramTester histogram_tester;
-  AppId app_id = InstallTestWebApp(
+  webapps::AppId app_id = InstallTestWebApp(
       "/web_apps/get_manifest.html?"
       "launch_handler_client_mode_navigate_existing.json");
   EXPECT_EQ(GetLaunchHandler(app_id),
@@ -405,7 +405,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest,
                        LaunchNavigationInterruptedByOutOfScopeNavigation) {
   base::HistogramTester histogram_tester;
-  AppId app_id = InstallTestWebApp(
+  webapps::AppId app_id = InstallTestWebApp(
       "/web_apps/get_manifest.html?"
       "launch_handler_client_mode_navigate_new.json");
   EXPECT_EQ(GetLaunchHandler(app_id),
@@ -441,7 +441,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest, GlobalLaunchQueue) {
   base::HistogramTester histogram_tester;
-  AppId app_id =
+  webapps::AppId app_id =
       InstallTestWebApp("/web_apps/basic.html", /*await_metric=*/false);
 
   Browser* app_browser = LaunchWebAppBrowserAndWait(app_id);
@@ -465,7 +465,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerBrowserTest,
                        MAYBE_SelectActiveBrowser) {
-  AppId app_id =
+  webapps::AppId app_id =
       InstallTestWebApp("/web_apps/basic.html", /*await_metric=*/false);
   EXPECT_EQ(GetLaunchHandler(app_id), absl::nullopt);
 
@@ -512,7 +512,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerDisabledBrowserTest,
                        LaunchQueueNoLaunchHandlers) {
   base::HistogramTester histogram_tester;
-  AppId app_id = InstallWebAppFromPage(
+  webapps::AppId app_id = InstallWebAppFromPage(
       browser(), embedded_test_server()->GetURL("/web_apps/basic.html"));
 
   Browser* app_browser = LaunchWebAppBrowserAndWait(app_id);
@@ -629,7 +629,8 @@
       }));
 
   // Install web app with origin trial token.
-  AppId app_id = InstallWebAppFromPage(browser(), GURL(kTestWebAppUrl));
+  webapps::AppId app_id =
+      InstallWebAppFromPage(browser(), GURL(kTestWebAppUrl));
 
   // Origin trial should grant the app access.
   WebAppProvider& provider = *WebAppProvider::GetForTest(browser()->profile());
diff --git a/chrome/browser/ui/web_applications/web_app_launch_prevent_close_browsertest.cc b/chrome/browser/ui/web_applications/web_app_launch_prevent_close_browsertest.cc
index 03e4e7370..294806e 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_prevent_close_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_prevent_close_browsertest.cc
@@ -53,7 +53,7 @@
 
   const GURL url(kTestApp);
   ApplyPolicySettings(url, /*prevent_close=*/true);
-  const AppId& app_id = InstallPWA(GURL(kTestApp));
+  const webapps::AppId& app_id = InstallPWA(GURL(kTestApp));
 
   Browser* browser = LaunchWebAppBrowser(app_id);
   ++expected_browser_count;
@@ -88,7 +88,7 @@
   size_t expected_browser_count = chrome::GetBrowserCount(profile());
 
   const GURL url(kTestApp);
-  const AppId& app_id = InstallPWA(url);
+  const webapps::AppId& app_id = InstallPWA(url);
   ApplyPolicySettings(url, /*prevent_close=*/false);
   Browser* browser = LaunchWebAppBrowser(app_id);
   ++expected_browser_count;
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.cc b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
index f192a16b..06131993 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
@@ -94,7 +94,7 @@
 
 Browser* ReparentWebContentsIntoAppBrowser(content::WebContents* contents,
                                            Browser* target_browser,
-                                           const AppId& app_id,
+                                           const webapps::AppId& app_id,
                                            bool as_pinned_home_tab) {
   DCHECK(target_browser->is_type_app());
   Browser* source_browser = chrome::FindBrowserWithWebContents(contents);
@@ -153,8 +153,9 @@
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-const ash::SystemWebAppDelegate* GetSystemWebAppDelegate(Browser* browser,
-                                                         const AppId& app_id) {
+const ash::SystemWebAppDelegate* GetSystemWebAppDelegate(
+    Browser* browser,
+    const webapps::AppId& app_id) {
   auto system_app_type =
       ash::GetSystemWebAppTypeForAppId(browser->profile(), app_id);
   if (system_app_type) {
@@ -169,7 +170,7 @@
 std::unique_ptr<AppBrowserController> CreateWebKioskBrowserController(
     Browser* browser,
     WebAppProvider* provider,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   const ash::SystemWebAppDelegate* system_app =
       GetSystemWebAppDelegate(browser, app_id);
@@ -185,7 +186,7 @@
 std::unique_ptr<AppBrowserController> CreateWebAppBrowserController(
     Browser* browser,
     WebAppProvider* provider,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   bool should_have_tab_strip_for_swa = false;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   const ash::SystemWebAppDelegate* system_app =
@@ -206,7 +207,7 @@
 
 std::unique_ptr<AppBrowserController> MaybeCreateHostedAppBrowserController(
     Browser* browser,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   const extensions::Extension* extension =
       extensions::ExtensionRegistry::Get(browser->profile())
@@ -220,7 +221,7 @@
 
 }  // namespace
 
-absl::optional<AppId> GetWebAppForActiveTab(const Browser* browser) {
+absl::optional<webapps::AppId> GetWebAppForActiveTab(const Browser* browser) {
   const WebAppProvider* const provider =
       WebAppProvider::GetForWebApps(browser->profile());
   if (!provider)
@@ -256,7 +257,7 @@
 }
 
 Browser* ReparentWebAppForActiveTab(Browser* browser) {
-  absl::optional<AppId> app_id = GetWebAppForActiveTab(browser);
+  absl::optional<webapps::AppId> app_id = GetWebAppForActiveTab(browser);
   if (!app_id)
     return nullptr;
   return ReparentWebContentsIntoAppBrowser(
@@ -264,7 +265,7 @@
 }
 
 Browser* ReparentWebContentsIntoAppBrowser(content::WebContents* contents,
-                                           const AppId& app_id) {
+                                           const webapps::AppId& app_id) {
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
   // Incognito tabs reparent correctly, but remain incognito without any
   // indication to the user, so disallow it.
@@ -339,7 +340,7 @@
 }
 
 void SetWebContentsActingAsApp(content::WebContents* contents,
-                               const AppId& app_id) {
+                               const webapps::AppId& app_id) {
   auto* helper = WebAppTabHelper::FromWebContents(contents);
   helper->SetAppId(app_id);
   helper->set_acting_as_app(true);
@@ -367,7 +368,8 @@
 std::unique_ptr<AppBrowserController> MaybeCreateAppBrowserController(
     Browser* browser) {
   std::unique_ptr<AppBrowserController> controller;
-  const AppId app_id = GetAppIdFromApplicationName(browser->app_name());
+  const webapps::AppId app_id =
+      GetAppIdFromApplicationName(browser->app_name());
   auto* const provider =
       WebAppProvider::GetForLocalAppsUnchecked(browser->profile());
   if (provider && provider->registrar_unsafe().IsInstalled(app_id)) {
@@ -608,7 +610,7 @@
   }
 }
 
-void RecordLaunchMetrics(const AppId& app_id,
+void RecordLaunchMetrics(const webapps::AppId& app_id,
                          apps::LaunchContainer container,
                          apps::LaunchSource launch_source,
                          const GURL& launch_url,
@@ -636,7 +638,7 @@
 }
 
 void UpdateLaunchStats(content::WebContents* web_contents,
-                       const AppId& app_id,
+                       const webapps::AppId& app_id,
                        const GURL& launch_url) {
   CHECK(web_contents != nullptr);
   Profile* profile =
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.h b/chrome/browser/ui/web_applications/web_app_launch_utils.h
index 15815a6..89b5fd3 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_utils.h
+++ b/chrome/browser/ui/web_applications/web_app_launch_utils.h
@@ -11,6 +11,7 @@
 
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -28,7 +29,7 @@
 
 class AppBrowserController;
 
-absl::optional<AppId> GetWebAppForActiveTab(const Browser* browser);
+absl::optional<webapps::AppId> GetWebAppForActiveTab(const Browser* browser);
 
 // Clears navigation history prior to user entering app scope.
 void PrunePreScopeNavigationHistory(const GURL& scope,
@@ -48,13 +49,13 @@
 // - Otherwise a new browser window is created for |contents| to be reparented
 // into.
 Browser* ReparentWebContentsIntoAppBrowser(content::WebContents* contents,
-                                           const AppId& app_id);
+                                           const webapps::AppId& app_id);
 
 // Tags `contents` with the given app id and marks it as an app. This
 // differentiates it from a `WebContents` which happens to be hosting a page
 // that is part of an app.
 void SetWebContentsActingAsApp(content::WebContents* contents,
-                               const AppId& app_id);
+                               const webapps::AppId& app_id);
 
 // Marks the web contents as being the pinned home tab of a tabbed web app.
 void SetWebContentsIsPinnedHomeTab(content::WebContents* contents);
@@ -92,7 +93,7 @@
 
 // RecordLaunchMetrics methods report UMA metrics. It shouldn't have other
 // side-effects (e.g. updating app launch time).
-void RecordLaunchMetrics(const AppId& app_id,
+void RecordLaunchMetrics(const webapps::AppId& app_id,
                          apps::LaunchContainer container,
                          apps::LaunchSource launch_source,
                          const GURL& launch_url,
@@ -101,7 +102,7 @@
 // Updates statistics about web app launch. For example, app's last launch time
 // (populates recently launched app list) and site engagement stats.
 void UpdateLaunchStats(content::WebContents* web_contents,
-                       const AppId& app_id,
+                       const webapps::AppId& app_id,
                        const GURL& launch_url);
 
 }  // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
index 6330e589..01ffadb 100644
--- a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
@@ -82,13 +82,14 @@
   }
 
   // Returns [app_id, in_scope_1, in_scope_2, scope]
-  std::tuple<AppId, GURL, GURL, GURL> InstallTestApp(const char* path) {
+  std::tuple<webapps::AppId, GURL, GURL, GURL> InstallTestApp(
+      const char* path) {
     GURL start_url = embedded_test_server()->GetURL(path);
     GURL in_scope_1 = start_url.Resolve("page1.html");
     GURL in_scope_2 = start_url.Resolve("page2.html");
     GURL scope = start_url.GetWithoutFilename();
 
-    AppId app_id =
+    webapps::AppId app_id =
         InstallWebAppFromPageAndCloseAppBrowser(browser(), start_url);
     apps::AppReadinessWaiter(profile(), app_id).Await();
     return std::make_tuple(app_id, in_scope_1, in_scope_2, scope);
@@ -103,17 +104,17 @@
     return embedded_test_server()->GetURL("/web_apps/nesting/index.html");
   }
 
-  AppId InstallParentApp() {
+  webapps::AppId InstallParentApp() {
     GURL start_url = GetParentAppUrl();
-    AppId app_id =
+    webapps::AppId app_id =
         InstallWebAppFromPageAndCloseAppBrowser(browser(), start_url);
     apps::AppReadinessWaiter(profile(), app_id).Await();
     return app_id;
   }
 
-  AppId InstallNestedApp() {
+  webapps::AppId InstallNestedApp() {
     GURL start_url = GetNestedAppUrl();
-    AppId app_id =
+    webapps::AppId app_id =
         InstallWebAppFromPageAndCloseAppBrowser(browser(), start_url);
     apps::AppReadinessWaiter(profile(), app_id).Await();
     return app_id;
@@ -194,7 +195,7 @@
     }
   }
 
-  void TurnOnLinkCapturing(AppId app_id) {
+  void TurnOnLinkCapturing(webapps::AppId app_id) {
 #if BUILDFLAG(IS_CHROMEOS)
     apps_util::SetSupportedLinksPreferenceAndWait(profile(), app_id);
 #else
@@ -205,7 +206,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
   }
 
-  absl::optional<LaunchHandler> GetLaunchHandler(const AppId& app_id) {
+  absl::optional<LaunchHandler> GetLaunchHandler(const webapps::AppId& app_id) {
     return provider().registrar_unsafe().GetAppById(app_id)->launch_handler();
   }
 
@@ -368,8 +369,8 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
                        ParentAppWithChildLinks) {
-  AppId parent_app_id = InstallParentApp();
-  AppId nested_app_id = InstallNestedApp();
+  webapps::AppId parent_app_id = InstallParentApp();
+  webapps::AppId nested_app_id = InstallNestedApp();
 
   TurnOnLinkCapturing(parent_app_id);
   AddTab(browser(), about_blank_);
@@ -400,8 +401,8 @@
 #if !BUILDFLAG(IS_CHROMEOS)
 IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
                        ParentAppAndChildAppCapture) {
-  AppId parent_app_id = InstallParentApp();
-  AppId nested_app_id = InstallNestedApp();
+  webapps::AppId parent_app_id = InstallParentApp();
+  webapps::AppId nested_app_id = InstallNestedApp();
 
   TurnOnLinkCapturing(parent_app_id);
   TurnOnLinkCapturing(nested_app_id);
@@ -443,8 +444,8 @@
 // Tests that link capturing works while inside a web app window.
 IN_PROC_BROWSER_TEST_F(WebAppLinkCapturingBrowserTest,
                        LinkCaptureInWebAppWindow) {
-  AppId parent_app_id = InstallParentApp();
-  AppId nested_app_id = InstallNestedApp();
+  webapps::AppId parent_app_id = InstallParentApp();
+  webapps::AppId nested_app_id = InstallNestedApp();
 
   TurnOnLinkCapturing(nested_app_id);
 
@@ -504,7 +505,7 @@
   }
 
   // Returns [app_id, in_scope_1, in_scope_2, scope]
-  std::tuple<AppId, GURL, GURL, GURL> InstallTestTabbedApp() {
+  std::tuple<webapps::AppId, GURL, GURL, GURL> InstallTestTabbedApp() {
     const auto [app_id, in_scope_1, in_scope_2, scope] =
         WebAppLinkCapturingBrowserTest::InstallTestApp("/web_apps/basic.html");
     provider().sync_bridge_unsafe().SetAppUserDisplayMode(
diff --git a/chrome/browser/ui/web_applications/web_app_menu_model_browsertest.cc b/chrome/browser/ui/web_applications/web_app_menu_model_browsertest.cc
index 857d437..7b94454 100644
--- a/chrome/browser/ui/web_applications/web_app_menu_model_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_menu_model_browsertest.cc
@@ -36,7 +36,7 @@
 
 IN_PROC_BROWSER_TEST_F(TestWebAppMenuModelCR2023, ModelHasIcons) {
   const GURL app_url = GetInstallableAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const browser = LaunchWebAppBrowser(app_id);
 
   const auto check_for_icons = [](std::u16string menu_name,
@@ -79,7 +79,7 @@
 
 IN_PROC_BROWSER_TEST_F(TestWebAppMenuModelCR2023, CommandStatusTest) {
   const GURL app_url = GetInstallableAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const browser = LaunchWebAppBrowser(app_id);
 
   {
diff --git a/chrome/browser/ui/web_applications/web_app_metrics.cc b/chrome/browser/ui/web_applications/web_app_metrics.cc
index a4f57ba..404e015 100644
--- a/chrome/browser/ui/web_applications/web_app_metrics.cc
+++ b/chrome/browser/ui/web_applications/web_app_metrics.cc
@@ -86,7 +86,8 @@
   RecordTabOrWindowHistogram(histogram_prefix, in_window, engagement_type);
 }
 
-bool IsPreferredAppForSupportedLinks(const AppId& app_id, Profile* profile) {
+bool IsPreferredAppForSupportedLinks(const webapps::AppId& app_id,
+                                     Profile* profile) {
   if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) {
     return false;
   }
@@ -167,7 +168,7 @@
 
   // A presence of WebAppTabHelper with valid app_id indicates an installed
   // web app.
-  const AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
+  const webapps::AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
   if (!app_id)
     return;
 
@@ -251,7 +252,8 @@
          change.GetRemove()->contents) {
       if (contents.remove_reason ==
           TabStripModelChange::RemoveReason::kDeleted) {
-        const AppId* app_id = WebAppTabHelper::GetAppId(contents.contents);
+        const webapps::AppId* app_id =
+            WebAppTabHelper::GetAppId(contents.contents);
         if (app_id)
           app_last_interacted_time_.erase(*app_id);
         // Newly-selected foreground contents should not be going away.
@@ -269,7 +271,8 @@
 void WebAppMetrics::OnSuspend() {
   // Update current tab as foreground time.
   if (foreground_web_contents_) {
-    const AppId* app_id = WebAppTabHelper::GetAppId(foreground_web_contents_);
+    const webapps::AppId* app_id =
+        WebAppTabHelper::GetAppId(foreground_web_contents_);
     if (app_id && app_last_interacted_time_.contains(*app_id)) {
       UpdateUkmData(foreground_web_contents_, TabSwitching::kFrom);
       app_last_interacted_time_.erase(*app_id);
@@ -282,7 +285,7 @@
     for (int i = 0; i < tab_count; i++) {
       WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(i);
       DCHECK(contents);
-      const AppId* app_id = WebAppTabHelper::GetAppId(contents);
+      const webapps::AppId* app_id = WebAppTabHelper::GetAppId(contents);
       if (app_id && app_last_interacted_time_.contains(*app_id)) {
         UpdateUkmData(contents, TabSwitching::kBackgroundClosing);
       }
@@ -293,8 +296,8 @@
 
 void WebAppMetrics::NotifyOnAssociatedAppChanged(
     content::WebContents* web_contents,
-    const absl::optional<AppId>& previous_app_id,
-    const absl::optional<AppId>& new_app_id) {
+    const absl::optional<webapps::AppId>& previous_app_id,
+    const absl::optional<webapps::AppId>& new_app_id) {
   // Ensure we aren't counting closed app as still open.
   // TODO (crbug.com/1081187): If there were multiple app instances open, this
   // will prevent background time being counted until the app is next active.
@@ -369,7 +372,7 @@
     return;
   DailyInteraction features;
 
-  const AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
+  const webapps::AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
   if (app_id && provider->registrar_unsafe().IsLocallyInstalled(*app_id)) {
     // App is installed
     features.start_url = provider->registrar_unsafe().GetAppStartUrl(*app_id);
diff --git a/chrome/browser/ui/web_applications/web_app_metrics.h b/chrome/browser/ui/web_applications/web_app_metrics.h
index 2a4429a..b17607a8 100644
--- a/chrome/browser/ui/web_applications/web_app_metrics.h
+++ b/chrome/browser/ui/web_applications/web_app_metrics.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/site_engagement/content/site_engagement_observer.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
@@ -74,11 +75,12 @@
   // base::PowerSuspendObserver:
   void OnSuspend() override;
 
-  // Called when a web contents changes associated AppId (may be empty).
+  // Called when a web contents changes associated webapps::AppId (may be
+  // empty).
   void NotifyOnAssociatedAppChanged(
       content::WebContents* web_contents,
-      const absl::optional<AppId>& previous_app_id,
-      const absl::optional<AppId>& new_app_id);
+      const absl::optional<webapps::AppId>& previous_app_id,
+      const absl::optional<webapps::AppId>& new_app_id);
 
   // Notify WebAppMetrics that an installability check has been completed for
   // a WebContents (see AppBannerManager::OnInstallableWebAppStatusUpdated).
@@ -109,7 +111,7 @@
   static constexpr int kNumUserInstalledAppsNotCounted = -1;
   int num_user_installed_apps_ = kNumUserInstalledAppsNotCounted;
 
-  base::flat_map<web_app::AppId, base::Time> app_last_interacted_time_{};
+  base::flat_map<webapps::AppId, base::Time> app_last_interacted_time_{};
   // DanglingUntriaged because it is assigned a DanglingUntriaged pointer.
   raw_ptr<content::WebContents, DanglingUntriaged> foreground_web_contents_ =
       nullptr;
diff --git a/chrome/browser/ui/web_applications/web_app_metrics_browsertest.cc b/chrome/browser/ui/web_applications/web_app_metrics_browsertest.cc
index 9a17942..f2374c8 100644
--- a/chrome/browser/ui/web_applications/web_app_metrics_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_metrics_browsertest.cc
@@ -27,11 +27,11 @@
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom-shared.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/common/chrome_features.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
@@ -75,7 +75,7 @@
     WebAppMetrics::Get(profile())->RemoveBrowserListObserverForTesting();
   }
 
-  AppId InstallWebApp() {
+  webapps::AppId InstallWebApp() {
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GetInstallableAppURL();
     web_app_info->title = u"A Web App";
@@ -251,7 +251,7 @@
   web_app_info->title = u"A Web App";
   web_app_info->display_mode = DisplayMode::kStandalone;
   web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
-  AppId app_id =
+  webapps::AppId app_id =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info));
 
   apps_util::SetSupportedLinksPreferenceAndWait(profile(), app_id);
@@ -324,7 +324,7 @@
                        NavigationsWithinInstalledWebApp_RecordsOneSession) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
 
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   Browser* browser = LaunchWebAppBrowserAndAwaitInstallabilityCheck(app_id);
   NavigateAndAwaitInstallabilityCheck(browser, GetInstallableAppURL());
   NavigateAndAwaitInstallabilityCheck(browser, GetInstallableAppURL());
@@ -342,7 +342,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppMetricsBrowserTest,
                        InstalledWebApp_RecordsTimeAndSessions) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   Browser* app_browser;
 
   // Open the app.
@@ -396,7 +396,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppMetricsBrowserTest,
                        InstalledWebApp_RecordsTimeAndSessionWhenClosed) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   Browser* app_browser;
 
   // Open the app.
@@ -441,7 +441,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppMetricsBrowserTest,
                        MultipleWebAppInstances_StillRecordsTime) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   Browser* app_browser;
 
   // Open the app.
@@ -500,7 +500,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppMetricsBrowserTest,
                        InstalledWebApp_RecordsZeroTimeIfOverLimit) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   Browser* app_browser;
 
   // Open the app.
@@ -541,7 +541,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppMetricsBrowserTest, Suspend_FlushesSessionTimes) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   Browser* app_browser;
 
   // Open the app.
diff --git a/chrome/browser/ui/web_applications/web_app_navigate_browsertest.cc b/chrome/browser/ui/web_applications/web_app_navigate_browsertest.cc
index c3beaf7a..fff13de 100644
--- a/chrome/browser/ui/web_applications/web_app_navigate_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_navigate_browsertest.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
@@ -91,7 +91,7 @@
     Navigate(&params);
   }
   Browser* const app_browser = browser_list->GetLastActive();
-  const AppId app_id = app_browser->app_controller()->app_id();
+  const webapps::AppId app_id = app_browser->app_controller()->app_id();
 
   {
     NavigateParams params(MakeNavigateParams());
diff --git a/chrome/browser/ui/web_applications/web_app_profile_deletion_browsertest.cc b/chrome/browser/ui/web_applications/web_app_profile_deletion_browsertest.cc
index 6b99b23..c352e40 100644
--- a/chrome/browser/ui/web_applications/web_app_profile_deletion_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_profile_deletion_browsertest.cc
@@ -20,9 +20,9 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "url/gurl.h"
 
@@ -53,7 +53,7 @@
             ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
   }
 
-  web_app::AppId InstallAppToProfile(Profile* profile, const GURL& start_url) {
+  webapps::AppId InstallAppToProfile(Profile* profile, const GURL& start_url) {
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
@@ -117,12 +117,12 @@
 IN_PROC_BROWSER_TEST_F(WebAppProfileDeletionBrowserTest,
                        MAYBE_AppRegistrarNotifiesProfileDeletion) {
   GURL app_url(GetInstallableAppURL());
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   base::RunLoop run_loop;
   WebAppTestRegistryObserverAdapter observer(&registrar());
-  observer.SetWebAppProfileWillBeDeletedDelegate(
-      base::BindLambdaForTesting([&](const AppId& app_to_be_uninstalled) {
+  observer.SetWebAppProfileWillBeDeletedDelegate(base::BindLambdaForTesting(
+      [&](const webapps::AppId& app_to_be_uninstalled) {
         EXPECT_EQ(app_to_be_uninstalled, app_id);
         EXPECT_TRUE(registrar().IsInstalled(app_id));
         EXPECT_TRUE(registrar().GetAppById(app_id));
@@ -164,12 +164,13 @@
       profile_manager, profile_path_to_delete);
 #endif
   Browser::Create(Browser::CreateParams(&profile_to_delete, true));
-  const AppId app_id = InstallAppToProfile(&profile_to_delete, app_url);
+  const webapps::AppId app_id =
+      InstallAppToProfile(&profile_to_delete, app_url);
   auto* provider = WebAppProvider::GetForTest(&profile_to_delete);
   auto* web_app = provider->registrar_unsafe().GetAppById(app_id);
   ASSERT_TRUE(web_app);
 
-  base::test::TestFuture<const AppId&> app_id_future;
+  base::test::TestFuture<const webapps::AppId&> app_id_future;
   provider->os_integration_manager().SetForceUnregisterCalledForTesting(
       app_id_future.GetRepeatingCallback());
 
@@ -201,12 +202,13 @@
       profile_manager, profile_path_to_delete);
 #endif
   Browser::Create(Browser::CreateParams(&profile_to_delete, true));
-  const AppId app_id = InstallAppToProfile(&profile_to_delete, app_url);
+  const webapps::AppId app_id =
+      InstallAppToProfile(&profile_to_delete, app_url);
   auto* provider = WebAppProvider::GetForTest(&profile_to_delete);
   auto* web_app = provider->registrar_unsafe().GetAppById(app_id);
   ASSERT_TRUE(web_app);
 
-  base::test::TestFuture<const AppId&> app_id_future;
+  base::test::TestFuture<const webapps::AppId&> app_id_future;
   provider->os_integration_manager().SetForceUnregisterCalledForTesting(
       app_id_future.GetRepeatingCallback());
 
diff --git a/chrome/browser/ui/web_applications/web_app_protocol_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_protocol_handling_browsertest.cc
index fbd286a..e4d8513c 100644
--- a/chrome/browser/ui/web_applications/web_app_protocol_handling_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_protocol_handling_browsertest.cc
@@ -42,14 +42,15 @@
     ASSERT_TRUE(embedded_test_server()->Start());
   }
 
-  AppId InstallTestApp(const char* path, bool await_metric) {
+  webapps::AppId InstallTestApp(const char* path, bool await_metric) {
     GURL start_url = embedded_test_server()->GetURL(path);
     page_load_metrics::PageLoadMetricsTestWaiter metrics_waiter(
         browser()->tab_strip_model()->GetActiveWebContents());
     if (await_metric)
       metrics_waiter.AddWebFeatureExpectation(protocol_handling_feature);
 
-    AppId app_id = web_app::InstallWebAppFromPage(browser(), start_url);
+    webapps::AppId app_id =
+        web_app::InstallWebAppFromPage(browser(), start_url);
     if (await_metric)
       metrics_waiter.Wait();
 
@@ -75,7 +76,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppProtocolHandlingBrowserTest,
                        BasicProtocolHandlers) {
-  AppId app_id = InstallTestApp(
+  webapps::AppId app_id = InstallTestApp(
       "/banners/"
       "manifest_test_page.html?manifest=manifest_protocol_handlers.json",
       /*await_metric=*/true);
@@ -102,7 +103,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppProtocolHandlingBrowserTest, NoProtocolHandlers) {
-  AppId app_id =
+  webapps::AppId app_id =
       InstallTestApp("/banners/manifest_test_page.html?manifest=manifest.json",
                      /*await_metric=*/false);
   std::vector<apps::ProtocolHandlerInfo> protocol_handlers =
diff --git a/chrome/browser/ui/web_applications/web_app_tabbed_utils.h b/chrome/browser/ui/web_applications/web_app_tabbed_utils.h
index 908725f..221a05d 100644
--- a/chrome/browser/ui/web_applications/web_app_tabbed_utils.h
+++ b/chrome/browser/ui/web_applications/web_app_tabbed_utils.h
@@ -9,6 +9,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "components/webapps/common/web_app_id.h"
 #include "url/gurl.h"
 
 namespace web_app {
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
index 90e872f..08074de1 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
@@ -103,7 +103,7 @@
 // ScopedKeepAlive not only keeps the process from terminating early
 // during uninstall, it also ensures the process will terminate when it
 // is destroyed if there is no active browser window.
-void UninstallWebAppWithDialogFromStartupSwitch(const AppId& app_id,
+void UninstallWebAppWithDialogFromStartupSwitch(const webapps::AppId& app_id,
                                                 WebAppProvider* provider) {
   // ScopedKeepAlive does not only keeps the process from early termination,
   // but ensure the process termination when there is no active browser window.
@@ -184,7 +184,7 @@
   return this;
 }
 
-size_t WebAppUiManagerImpl::GetNumWindowsForApp(const AppId& app_id) {
+size_t WebAppUiManagerImpl::GetNumWindowsForApp(const webapps::AppId& app_id) {
   DCHECK(started_);
 
   auto it = num_windows_for_apps_map_.find(app_id);
@@ -195,7 +195,7 @@
   return it->second;
 }
 
-void WebAppUiManagerImpl::CloseAppWindows(const AppId& app_id) {
+void WebAppUiManagerImpl::CloseAppWindows(const webapps::AppId& app_id) {
   DCHECK(started_);
 
   for (auto* browser : *BrowserList::GetInstance()) {
@@ -207,7 +207,7 @@
 }
 
 void WebAppUiManagerImpl::NotifyOnAllAppWindowsClosed(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure callback) {
   DCHECK(started_);
 
@@ -235,7 +235,7 @@
 #endif
 }
 
-void WebAppUiManagerImpl::AddAppToQuickLaunchBar(const AppId& app_id) {
+void WebAppUiManagerImpl::AddAppToQuickLaunchBar(const webapps::AppId& app_id) {
   DCHECK(CanAddAppToQuickLaunchBar());
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // ChromeShelfController does not exist in unit tests.
@@ -246,7 +246,8 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
-bool WebAppUiManagerImpl::IsAppInQuickLaunchBar(const AppId& app_id) const {
+bool WebAppUiManagerImpl::IsAppInQuickLaunchBar(
+    const webapps::AppId& app_id) const {
   DCHECK(CanAddAppToQuickLaunchBar());
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // ChromeShelfController does not exist in unit tests.
@@ -258,7 +259,7 @@
 }
 
 bool WebAppUiManagerImpl::IsInAppWindow(content::WebContents* web_contents,
-                                        const AppId* app_id) const {
+                                        const webapps::AppId* app_id) const {
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
   if (app_id) {
     return AppBrowserController::IsForWebApp(browser, *app_id);
@@ -268,8 +269,8 @@
 
 void WebAppUiManagerImpl::NotifyOnAssociatedAppChanged(
     content::WebContents* web_contents,
-    const absl::optional<AppId>& previous_app_id,
-    const absl::optional<AppId>& new_app_id) const {
+    const absl::optional<webapps::AppId>& previous_app_id,
+    const absl::optional<webapps::AppId>& new_app_id) const {
   WebAppMetrics* web_app_metrics = WebAppMetrics::Get(profile_);
   // Unavailable in guest sessions.
   if (!web_app_metrics) {
@@ -280,7 +281,7 @@
 }
 
 bool WebAppUiManagerImpl::CanReparentAppTabToWindow(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool shortcut_created) const {
 #if BUILDFLAG(IS_MAC)
   // On macOS it is only possible to reparent the window when the shortcut (app
@@ -292,7 +293,7 @@
 }
 
 void WebAppUiManagerImpl::ReparentAppTabToWindow(content::WebContents* contents,
-                                                 const AppId& app_id,
+                                                 const webapps::AppId& app_id,
                                                  bool shortcut_created) {
   DCHECK(CanReparentAppTabToWindow(app_id, shortcut_created));
   // Reparent the tab into an app window immediately.
@@ -301,7 +302,7 @@
 
 void WebAppUiManagerImpl::ShowWebAppFileLaunchDialog(
     const std::vector<base::FilePath>& file_paths,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     WebAppLaunchAcceptanceCallback launch_callback) {
   chrome::ShowWebAppFileLaunchDialog(file_paths, profile_, app_id,
                                      std::move(launch_callback));
@@ -322,7 +323,7 @@
       new_icon, web_contents, std::move(callback));
 }
 
-void WebAppUiManagerImpl::ShowWebAppSettings(const AppId& app_id) {
+void WebAppUiManagerImpl::ShowWebAppSettings(const webapps::AppId& app_id) {
   WebAppProvider* provider = WebAppProvider::GetForWebApps(profile_);
   if (!provider) {
     return;
@@ -347,9 +348,10 @@
 }
 
 #if BUILDFLAG(IS_CHROMEOS)
-void WebAppUiManagerImpl::MigrateLauncherState(const AppId& from_app_id,
-                                               const AppId& to_app_id,
-                                               base::OnceClosure callback) {
+void WebAppUiManagerImpl::MigrateLauncherState(
+    const webapps::AppId& from_app_id,
+    const webapps::AppId& to_app_id,
+    base::OnceClosure callback) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   auto* lacros_service = chromeos::LacrosService::Get();
   if (!lacros_service ||
@@ -403,7 +405,7 @@
 }
 
 void WebAppUiManagerImpl::PresentUserUninstallDialog(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     BrowserWindow* parent_window,
     UninstallCompleteCallback callback) {
@@ -414,7 +416,7 @@
 }
 
 void WebAppUiManagerImpl::PresentUserUninstallDialog(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     gfx::NativeWindow native_window,
     UninstallCompleteCallback callback) {
@@ -423,7 +425,7 @@
 }
 
 void WebAppUiManagerImpl::PresentUserUninstallDialog(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     gfx::NativeWindow parent_window,
     UninstallCompleteCallback uninstall_complete_callback,
@@ -491,7 +493,7 @@
 
 #if BUILDFLAG(IS_WIN)
 void WebAppUiManagerImpl::UninstallWebAppFromStartupSwitch(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   WebAppProvider* provider = WebAppProvider::GetForWebApps(profile_);
   provider->on_registry_ready().Post(
       FROM_HERE, base::BindOnce(&UninstallWebAppWithDialogFromStartupSwitch,
@@ -511,12 +513,12 @@
   return true;
 }
 
-AppId WebAppUiManagerImpl::GetAppIdForBrowser(Browser* browser) {
+webapps::AppId WebAppUiManagerImpl::GetAppIdForBrowser(Browser* browser) {
   return browser->app_controller()->app_id();
 }
 
 void WebAppUiManagerImpl::OnIconsReadForUninstall(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     gfx::NativeWindow parent_window,
     std::unique_ptr<views::NativeWindowTracker> parent_window_tracker,
@@ -539,7 +541,7 @@
 }
 
 void WebAppUiManagerImpl::ScheduleUninstallIfUserRequested(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     UninstallCompleteCallback complete_callback,
     UninstallScheduledCallback uninstall_scheduled_callback,
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.h b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.h
index 4bd6230..308a929 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.h
+++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.h
@@ -22,6 +22,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_ui_manager.h"
 #include "chrome/browser/web_applications/web_app_uninstall_dialog_user_options.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/native_widget_types.h"
@@ -66,27 +67,27 @@
 
   // WebAppUiManager:
   WebAppUiManagerImpl* AsImpl() override;
-  size_t GetNumWindowsForApp(const AppId& app_id) override;
-  void CloseAppWindows(const AppId& app_id) override;
-  void NotifyOnAllAppWindowsClosed(const AppId& app_id,
+  size_t GetNumWindowsForApp(const webapps::AppId& app_id) override;
+  void CloseAppWindows(const webapps::AppId& app_id) override;
+  void NotifyOnAllAppWindowsClosed(const webapps::AppId& app_id,
                                    base::OnceClosure callback) override;
   bool CanAddAppToQuickLaunchBar() const override;
-  void AddAppToQuickLaunchBar(const AppId& app_id) override;
-  bool IsAppInQuickLaunchBar(const AppId& app_id) const override;
+  void AddAppToQuickLaunchBar(const webapps::AppId& app_id) override;
+  bool IsAppInQuickLaunchBar(const webapps::AppId& app_id) const override;
   bool IsInAppWindow(content::WebContents* web_contents,
-                     const AppId* app_id) const override;
+                     const webapps::AppId* app_id) const override;
   void NotifyOnAssociatedAppChanged(
       content::WebContents* web_contents,
-      const absl::optional<AppId>& previous_app_id,
-      const absl::optional<AppId>& new_app_id) const override;
-  bool CanReparentAppTabToWindow(const AppId& app_id,
+      const absl::optional<webapps::AppId>& previous_app_id,
+      const absl::optional<webapps::AppId>& new_app_id) const override;
+  bool CanReparentAppTabToWindow(const webapps::AppId& app_id,
                                  bool shortcut_created) const override;
   void ReparentAppTabToWindow(content::WebContents* contents,
-                              const AppId& app_id,
+                              const webapps::AppId& app_id,
                               bool shortcut_created) override;
   void ShowWebAppFileLaunchDialog(
       const std::vector<base::FilePath>& file_paths,
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppLaunchAcceptanceCallback launch_callback) override;
   void ShowWebAppIdentityUpdateDialog(
       const std::string& app_id,
@@ -98,15 +99,15 @@
       const SkBitmap& new_icon,
       content::WebContents* web_contents,
       web_app::AppIdentityDialogCallback callback) override;
-  void ShowWebAppSettings(const AppId& app_id) override;
+  void ShowWebAppSettings(const webapps::AppId& app_id) override;
   base::Value LaunchWebApp(apps::AppLaunchParams params,
                            LaunchWebAppWindowSetting launch_setting,
                            Profile& profile,
                            LaunchWebAppCallback callback,
                            AppLock& lock) override;
 #if BUILDFLAG(IS_CHROMEOS)
-  void MigrateLauncherState(const AppId& from_app_id,
-                            const AppId& to_app_id,
+  void MigrateLauncherState(const webapps::AppId& from_app_id,
+                            const webapps::AppId& to_app_id,
                             base::OnceClosure callback) override;
 
   void DisplayRunOnOsLoginNotification(
@@ -117,19 +118,19 @@
   void TriggerInstallDialog(content::WebContents* web_contents) override;
 
   void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       BrowserWindow* parent_window,
       UninstallCompleteCallback callback) override;
 
   void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       gfx::NativeWindow parent_window,
       UninstallCompleteCallback callback) override;
 
   void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       gfx::NativeWindow parent_window,
       UninstallCompleteCallback callback,
@@ -142,21 +143,21 @@
 #if BUILDFLAG(IS_WIN)
   // Attempts to uninstall the given web app id. Meant to be used with OS-level
   // uninstallation support/hooks.
-  void UninstallWebAppFromStartupSwitch(const AppId& app_id);
+  void UninstallWebAppFromStartupSwitch(const webapps::AppId& app_id);
 #endif
 
  private:
   // Returns true if Browser is for an installed App.
   bool IsBrowserForInstalledApp(Browser* browser);
 
-  // Returns AppId of the Browser's installed App, |IsBrowserForInstalledApp|
-  // must be true.
-  AppId GetAppIdForBrowser(Browser* browser);
+  // Returns webapps::AppId of the Browser's installed App,
+  // |IsBrowserForInstalledApp| must be true.
+  webapps::AppId GetAppIdForBrowser(Browser* browser);
 
   void OnExtensionSystemReady();
 
   void OnIconsReadForUninstall(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       gfx::NativeWindow parent_window,
       std::unique_ptr<views::NativeWindowTracker> parent_window_tracker,
@@ -165,7 +166,7 @@
       std::map<SquareSizePx, SkBitmap> icon_bitmaps);
 
   void ScheduleUninstallIfUserRequested(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       UninstallCompleteCallback complete_callback,
       UninstallScheduledCallback uninstall_scheduled_callback,
@@ -181,8 +182,9 @@
       webapps::UninstallResultCode uninstall_code);
 
   const raw_ptr<Profile> profile_;
-  std::map<AppId, std::vector<base::OnceClosure>> windows_closed_requests_map_;
-  std::map<AppId, size_t> num_windows_for_apps_map_;
+  std::map<webapps::AppId, std::vector<base::OnceClosure>>
+      windows_closed_requests_map_;
+  std::map<webapps::AppId, size_t> num_windows_for_apps_map_;
   bool started_ = false;
 
   base::WeakPtrFactory<WebAppUiManagerImpl> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc b/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
index ad51795..04e275e 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
@@ -16,12 +16,12 @@
 #include "chrome/browser/web_applications/test/fake_os_integration_manager.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "url/gurl.h"
 
@@ -50,14 +50,14 @@
 
   Profile* profile() { return browser()->profile(); }
 
-  AppId InstallWebApp(const GURL& start_url) {
+  webapps::AppId InstallWebApp(const GURL& start_url) {
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone;
     return web_app::test::InstallWebApp(profile(), std::move(web_app_info));
   }
 
-  Browser* LaunchWebApp(const AppId& app_id) {
+  Browser* LaunchWebApp(const webapps::AppId& app_id) {
     return LaunchWebAppBrowser(profile(), app_id);
   }
 
@@ -90,9 +90,9 @@
 IN_PROC_BROWSER_TEST_F(WebAppUiManagerImplBrowserTest,
                        GetNumWindowsForApp_AppWindowsAdded) {
   // Zero apps on start:
-  EXPECT_EQ(0u, ui_manager().GetNumWindowsForApp(AppId()));
+  EXPECT_EQ(0u, ui_manager().GetNumWindowsForApp(webapps::AppId()));
 
-  AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
+  webapps::AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
   LaunchWebApp(foo_app_id);
   EXPECT_EQ(1u, ui_manager().GetNumWindowsForApp(foo_app_id));
 
@@ -103,8 +103,8 @@
 IN_PROC_BROWSER_TEST_F(WebAppUiManagerImplBrowserTest,
                        UninstallDuringLastBrowserWindow) {
   // Zero apps on start:
-  EXPECT_EQ(0u, ui_manager().GetNumWindowsForApp(AppId()));
-  AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
+  EXPECT_EQ(0u, ui_manager().GetNumWindowsForApp(webapps::AppId()));
+  webapps::AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
   LaunchWebApp(foo_app_id);
   EXPECT_EQ(1u, ui_manager().GetNumWindowsForApp(foo_app_id));
   // It has 2 browser window object.
@@ -123,11 +123,11 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppUiManagerImplBrowserTest,
                        GetNumWindowsForApp_AppWindowsRemoved) {
-  AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
+  webapps::AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
   auto* foo_window1 = LaunchWebApp(foo_app_id);
   auto* foo_window2 = LaunchWebApp(foo_app_id);
 
-  AppId bar_app_id = InstallWebApp(GURL("https://bar.example"));
+  webapps::AppId bar_app_id = InstallWebApp(GURL("https://bar.example"));
   LaunchWebApp(bar_app_id);
 
   EXPECT_EQ(2u, ui_manager().GetNumWindowsForApp(foo_app_id));
@@ -146,8 +146,8 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppUiManagerImplBrowserTest,
                        NotifyOnAllAppWindowsClosed_NoOpenedWindows) {
-  AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
-  AppId bar_app_id = InstallWebApp(GURL("https://bar.example"));
+  webapps::AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
+  webapps::AppId bar_app_id = InstallWebApp(GURL("https://bar.example"));
   LaunchWebApp(bar_app_id);
 
   base::RunLoop run_loop;
@@ -160,8 +160,8 @@
 // app window.
 IN_PROC_BROWSER_TEST_F(WebAppUiManagerImplBrowserTest,
                        NotifyOnAllAppWindowsClosed_MultipleOpenedWindows) {
-  AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
-  AppId bar_app_id = InstallWebApp(GURL("https://bar.example"));
+  webapps::AppId foo_app_id = InstallWebApp(GURL("https://foo.example"));
+  webapps::AppId bar_app_id = InstallWebApp(GURL("https://bar.example"));
 
   // Test that NotifyOnAllAppWindowsClosed can be called more than once for
   // the same app.
@@ -199,15 +199,15 @@
           browser()->profile());
 
   // Install an old app to be replaced.
-  AppId old_app_id = test::InstallDummyWebApp(profile(), "old_app",
-                                              GURL("https://old.app.com"));
+  webapps::AppId old_app_id = test::InstallDummyWebApp(
+      profile(), "old_app", GURL("https://old.app.com"));
   app_list_service->SetPinPosition(old_app_id,
                                    syncer::StringOrdinal("positionold"),
                                    /*pinned_by_policy=*/false);
 
   // Install a new app to migrate the old one to.
-  AppId new_app_id = test::InstallDummyWebApp(profile(), "new_app",
-                                              GURL("https://new.app.com"));
+  webapps::AppId new_app_id = test::InstallDummyWebApp(
+      profile(), "new_app", GURL("https://new.app.com"));
   base::test::TestFuture<void> future;
   ui_manager().MigrateLauncherState(old_app_id, new_app_id,
                                     future.GetCallback());
diff --git a/chrome/browser/ui/web_applications/web_app_ui_utils.cc b/chrome/browser/ui/web_applications/web_app_ui_utils.cc
index 0a93a8b..e22f29b 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_utils.cc
@@ -26,13 +26,13 @@
 
 namespace {
 
-absl::optional<AppId> GetAppIdForManagementLinkInWebContents(
+absl::optional<webapps::AppId> GetAppIdForManagementLinkInWebContents(
     content::WebContents* web_contents) {
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
   if (!browser)
     return absl::nullopt;
 
-  const web_app::AppId* app_id =
+  const webapps::AppId* app_id =
       web_app::WebAppTabHelper::GetAppId(web_contents);
   if (!app_id)
     return absl::nullopt;
@@ -50,7 +50,7 @@
 }
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-void ShowAppManagementPage(const AppId& app_id) {
+void ShowAppManagementPage(const webapps::AppId& app_id) {
   auto* service = chromeos::LacrosService::Get();
   if (!service || !service->IsAvailable<crosapi::mojom::AppServiceProxy>()) {
     LOG(ERROR) << "AppServiceProxy not available.";
@@ -68,7 +68,7 @@
     content::WebContents* web_contents,
     int* link_text_id,
     int* tooltip_text_id) {
-  absl::optional<AppId> app_id =
+  absl::optional<webapps::AppId> app_id =
       GetAppIdForManagementLinkInWebContents(web_contents);
   if (!app_id)
     return false;
@@ -80,7 +80,7 @@
 
 bool HandleAppManagementLinkClickedInPageInfo(
     content::WebContents* web_contents) {
-  absl::optional<AppId> app_id =
+  absl::optional<webapps::AppId> app_id =
       GetAppIdForManagementLinkInWebContents(web_contents);
   if (!app_id)
     return false;
diff --git a/chrome/browser/ui/web_applications/web_app_ui_utils.h b/chrome/browser/ui/web_applications/web_app_ui_utils.h
index ce79f2f2..4f3a87e 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_utils.h
+++ b/chrome/browser/ui/web_applications/web_app_ui_utils.h
@@ -28,7 +28,7 @@
 // Returns an App ID if a link to app settings should be shown in the page info
 // bubble for the given `web_contents`. This will return null when the tab was
 // not launched as an app.
-// absl::optional<AppId> GetAppIdForAppManagementLinkInPageInfo(
+// absl::optional<webapps::AppId> GetAppIdForAppManagementLinkInPageInfo(
 //    content::WebContents* web_contents);
 
 }  // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc b/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
index f95bf45..6350646 100644
--- a/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
@@ -22,13 +22,13 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/sessions/core/tab_restore_service.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -43,7 +43,7 @@
     return https_server()->GetURL("app.com", "/ssl/google.html");
   }
 
-  void UninstallWebApp(const AppId& app_id) {
+  void UninstallWebApp(const webapps::AppId& app_id) {
     WebAppProvider* const provider = WebAppProvider::GetForTest(profile());
 
     base::test::TestFuture<webapps::UninstallResultCode> future;
@@ -60,7 +60,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppUninstallBrowserTest,
                        RestoreAppWindowForUninstalledApp) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   {
     Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
@@ -92,7 +92,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   EXPECT_TRUE(IsBrowserOpen(app_browser));
@@ -108,7 +108,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
   Browser* const app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   EXPECT_TRUE(IsBrowserOpen(app_browser));
@@ -131,7 +131,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppUninstallBrowserTest, CannotLaunchAfterUninstall) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   apps::AppLaunchParams params(
       app_id, apps::LaunchContainer::kLaunchContainerWindow,
@@ -147,7 +147,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppUninstallBrowserTest, TwoUninstallCalls) {
   const GURL app_url = GetSecureAppURL();
-  const AppId app_id = InstallPWA(app_url);
+  const webapps::AppId app_id = InstallPWA(app_url);
 
   base::RunLoop run_loop;
   bool quit_run_loop = false;
@@ -181,7 +181,7 @@
   WebAppInstallManagerObserverAdapter install_observer(
       &provider->install_manager());
   install_observer.SetWebAppWillBeUninstalledDelegate(
-      base::BindLambdaForTesting([&](const AppId& uninstall_app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& uninstall_app_id) {
         EXPECT_EQ(app_id, uninstall_app_id);
         EXPECT_FALSE(uninstall_delegate_called);
 
diff --git a/chrome/browser/ui/web_applications/web_app_url_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_url_handling_browsertest.cc
index c14479c72..0046cf5 100644
--- a/chrome/browser/ui/web_applications/web_app_url_handling_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_url_handling_browsertest.cc
@@ -38,14 +38,15 @@
     ASSERT_TRUE(embedded_test_server()->Start());
   }
 
-  AppId InstallTestApp(const char* path, bool await_metric) {
+  webapps::AppId InstallTestApp(const char* path, bool await_metric) {
     GURL start_url = embedded_test_server()->GetURL(path);
     page_load_metrics::PageLoadMetricsTestWaiter metrics_waiter(
         browser()->tab_strip_model()->GetActiveWebContents());
     if (await_metric)
       metrics_waiter.AddWebFeatureExpectation(url_handling_feature);
 
-    AppId app_id = web_app::InstallWebAppFromPage(browser(), start_url);
+    webapps::AppId app_id =
+        web_app::InstallWebAppFromPage(browser(), start_url);
     if (await_metric)
       metrics_waiter.Wait();
 
@@ -68,7 +69,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(WebAppUrlHandlingBrowserTest, BasicUrlHandlers) {
-  AppId app_id = InstallTestApp(
+  webapps::AppId app_id = InstallTestApp(
       "/banners/"
       "manifest_test_page.html?manifest=manifest_url_handlers.json",
       /*await_metric=*/true);
@@ -95,7 +96,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppUrlHandlingBrowserTest, NoUrlHandlers) {
-  AppId app_id =
+  webapps::AppId app_id =
       InstallTestApp("/banners/manifest_test_page.html?manifest=manifest.json",
                      /*await_metric=*/false);
   apps::UrlHandlers url_handlers =
diff --git a/chrome/browser/ui/web_applications/web_app_window_controls_overlay_browsertest.cc b/chrome/browser/ui/web_applications/web_app_window_controls_overlay_browsertest.cc
index 64c01276..3fd88a9 100644
--- a/chrome/browser/ui/web_applications/web_app_window_controls_overlay_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_window_controls_overlay_browsertest.cc
@@ -37,14 +37,15 @@
     ASSERT_TRUE(embedded_test_server()->Start());
   }
 
-  AppId InstallTestApp(const char* path, bool await_metric) {
+  webapps::AppId InstallTestApp(const char* path, bool await_metric) {
     GURL start_url = embedded_test_server()->GetURL(path);
     page_load_metrics::PageLoadMetricsTestWaiter metrics_waiter(
         browser()->tab_strip_model()->GetActiveWebContents());
     if (await_metric)
       metrics_waiter.AddWebFeatureExpectation(window_controls_overlay_feature);
 
-    AppId app_id = web_app::InstallWebAppFromPage(browser(), start_url);
+    webapps::AppId app_id =
+        web_app::InstallWebAppFromPage(browser(), start_url);
     if (await_metric)
       metrics_waiter.Wait();
 
@@ -66,7 +67,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppWindowControlsOverlayBrowserTest,
                        BasicDisplayOverride) {
-  AppId app_id = InstallTestApp(
+  webapps::AppId app_id = InstallTestApp(
       "/banners/"
       "manifest_test_page.html?manifest=manifest_window_controls_overlay.json",
       /*await_metric=*/true);
@@ -82,7 +83,7 @@
 
 IN_PROC_BROWSER_TEST_F(WebAppWindowControlsOverlayBrowserTest,
                        NoDisplayOverride) {
-  AppId app_id =
+  webapps::AppId app_id =
       InstallTestApp("/banners/manifest_test_page.html?manifest=manifest.json",
                      /*await_metric=*/false);
 
diff --git a/chrome/browser/ui/web_applications/web_share_target_browsertest.cc b/chrome/browser/ui/web_applications/web_share_target_browsertest.cc
index ed99ebcb..94a65a1b 100644
--- a/chrome/browser/ui/web_applications/web_share_target_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_share_target_browsertest.cc
@@ -93,7 +93,7 @@
 }
 
 content::WebContents* LaunchWebAppWithIntent(Profile* profile,
-                                             const web_app::AppId& app_id,
+                                             const webapps::AppId& app_id,
                                              apps::IntentPtr&& intent) {
   apps::AppLaunchParams params = apps::CreateAppLaunchParamsForIntent(
       app_id,
@@ -126,7 +126,7 @@
 
   void set_profile(Profile* profile) { profile_ = profile; }
 
-  void set_selected_app_id(const web_app::AppId& app_id) {
+  void set_selected_app_id(const webapps::AppId& app_id) {
     selected_app_id_ = app_id;
   }
 
@@ -150,7 +150,7 @@
   void CloseBubble(const std::string& window_id) override {}
 
   raw_ptr<Profile, DanglingUntriaged> profile_ = nullptr;
-  web_app::AppId selected_app_id_;
+  webapps::AppId selected_app_id_;
 };
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
@@ -164,7 +164,7 @@
     return embedded_test_server()->GetURL("/web_share_target/share.html");
   }
 
-  content::WebContents* LaunchAppWithIntent(const AppId& app_id,
+  content::WebContents* LaunchAppWithIntent(const webapps::AppId& app_id,
                                             apps::IntentPtr&& intent,
                                             const GURL& expected_url) {
     DCHECK(intent);
@@ -224,7 +224,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url =
       embedded_test_server()->GetURL("/web_share_target/charts.html");
-  const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id =
+      web_app::InstallWebAppFromManifest(browser(), app_url);
 
   base::ScopedAllowBlockingForTesting allow_blocking;
   base::ScopedTempDir scoped_temp_dir;
@@ -263,7 +264,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url =
       embedded_test_server()->GetURL("/web_share_target/charts.html");
-  const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id =
+      web_app::InstallWebAppFromManifest(browser(), app_url);
   const base::FilePath directory = PrepareWebShareDirectory(profile());
 
   apps::IntentPtr intent;
@@ -295,7 +297,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url =
       embedded_test_server()->GetURL("/web_share_target/charts.html");
-  const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id =
+      web_app::InstallWebAppFromManifest(browser(), app_url);
   const base::FilePath directory = PrepareWebShareDirectory(profile());
 
   apps::IntentPtr intent;
@@ -329,7 +332,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url =
       embedded_test_server()->GetURL("/web_share_target/poster.html");
-  const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id =
+      web_app::InstallWebAppFromManifest(browser(), app_url);
 
   apps::IntentPtr intent = apps_util::MakeShareIntent(
       /*text=*/std::string(),
@@ -347,7 +351,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url =
       embedded_test_server()->GetURL("/web_share_target/poster.html");
-  const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id =
+      web_app::InstallWebAppFromManifest(browser(), app_url);
   const apps::ShareTarget* share_target =
       WebAppProvider::GetForTest(browser()->profile())
           ->registrar_unsafe()
@@ -378,7 +383,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url =
       embedded_test_server()->GetURL("/web_share_target/gatherer.html");
-  const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id =
+      web_app::InstallWebAppFromManifest(browser(), app_url);
   const apps::ShareTarget* share_target =
       WebAppProvider::GetForTest(browser()->profile())
           ->registrar_unsafe()
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
index e1be7268..086966d 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
@@ -87,12 +87,12 @@
 void AcquireAppLockAndScheduleCallback(
     const std::string& operation_name,
     web_app::WebAppProvider& provider,
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceCallback<void(web_app::AppLock& lock)> callback) {
   provider.scheduler().ScheduleCallbackWithLock<web_app::AppLock>(
       operation_name,
       std::make_unique<web_app::AppLockDescription,
-                       base::flat_set<web_app::AppId>>({app_id}),
+                       base::flat_set<webapps::AppId>>({app_id}),
       std::move(callback));
 }
 
@@ -304,7 +304,7 @@
   AcquireAppLockAndScheduleCallback(
       "AppHomePageHandler::SetWebAppDisplayMode", *web_app_provider_, app_id,
       base::BindOnce(
-          [](const web_app::AppId& app_id,
+          [](const webapps::AppId& app_id,
              web_app::mojom::UserDisplayMode user_display_mode,
              web_app::AppLock& lock) {
             if (lock.registrar().IsLocallyInstalled(app_id)) {
@@ -317,7 +317,7 @@
 }
 
 app_home::mojom::AppInfoPtr AppHomePageHandler::GetApp(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   std::vector<app_home::mojom::AppInfoPtr> all_apps;
   FillWebAppInfoList(&all_apps);
   FillExtensionInfoList(&all_apps);
@@ -367,7 +367,7 @@
 }
 
 app_home::mojom::AppInfoPtr AppHomePageHandler::CreateAppInfoPtrFromWebApp(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   auto& registrar = web_app_provider_->registrar_unsafe();
 
   auto app_info = app_home::mojom::AppInfo::New();
@@ -457,7 +457,7 @@
     std::vector<app_home::mojom::AppInfoPtr>* result) {
   web_app::WebAppRegistrar& registrar = web_app_provider_->registrar_unsafe();
 
-  for (const web_app::AppId& web_app_id : registrar.GetAppIds()) {
+  for (const webapps::AppId& web_app_id : registrar.GetAppIds()) {
     if (IsYoutubeExtension(web_app_id))
       continue;
     result->emplace_back(CreateAppInfoPtrFromWebApp(web_app_id));
@@ -572,13 +572,13 @@
 }
 
 void AppHomePageHandler::OnWebAppWillBeUninstalled(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   auto app_info = app_home::mojom::AppInfo::New();
   app_info->id = app_id;
   page_->RemoveApp(std::move(app_info));
 }
 
-void AppHomePageHandler::OnWebAppInstalled(const web_app::AppId& app_id) {
+void AppHomePageHandler::OnWebAppInstalled(const webapps::AppId& app_id) {
   page_->AddApp(CreateAppInfoPtrFromWebApp(app_id));
 }
 
@@ -662,19 +662,19 @@
 }
 
 void AppHomePageHandler::OnWebAppRunOnOsLoginModeChanged(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     web_app::RunOnOsLoginMode run_on_os_login_mode) {
   page_->AddApp(CreateAppInfoPtrFromWebApp(app_id));
 }
 
 void AppHomePageHandler::OnWebAppUserDisplayModeChanged(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     web_app::mojom::UserDisplayMode user_display_mode) {
   page_->AddApp(CreateAppInfoPtrFromWebApp(app_id));
 }
 
 void AppHomePageHandler::OnWebAppInstalledWithOsHooks(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   page_->AddApp(CreateAppInfoPtrFromWebApp(app_id));
 }
 
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.h b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
index 4a24ef0..8b3cd85 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.h
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registrar_observer.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "components/webapps/common/web_app_id.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/common/constants.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -67,9 +68,9 @@
   // some type of installs, e.g. sync install only trigger `OnWebAppInstalled`.
   // `OnWebAppInstalledWithOsHooks` also gets fired when an installed app gets
   // locally installed.
-  void OnWebAppInstalled(const web_app::AppId& app_id) override;
-  void OnWebAppInstalledWithOsHooks(const web_app::AppId& app_id) override;
-  void OnWebAppWillBeUninstalled(const web_app::AppId& app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& app_id) override;
+  void OnWebAppInstalledWithOsHooks(const webapps::AppId& app_id) override;
+  void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
 
   // extensions::ExtensionRegistryObserver:
@@ -84,10 +85,10 @@
 
   // web_app::WebAppRegistrarObserver:
   void OnWebAppRunOnOsLoginModeChanged(
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       web_app::RunOnOsLoginMode run_on_os_login_mode) override;
   void OnWebAppUserDisplayModeChanged(
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       web_app::mojom::UserDisplayMode user_display_mode) override;
   void OnAppRegistrarDestroyed() override;
 
@@ -110,7 +111,7 @@
       const std::string& app_id,
       web_app::mojom::UserDisplayMode display_mode) override;
 
-  app_home::mojom::AppInfoPtr GetApp(const web_app::AppId& app_id);
+  app_home::mojom::AppInfoPtr GetApp(const webapps::AppId& app_id);
 
  private:
   Browser* GetCurrentBrowser();
@@ -135,7 +136,7 @@
   void OnExtensionUninstallDialogClosed(bool did_start_uninstall,
                                         const std::u16string& error) override;
 
-  void InstallOsHooks(const web_app::AppId& app_id, web_app::AppLock* lock);
+  void InstallOsHooks(const webapps::AppId& app_id, web_app::AppLock* lock);
   void LaunchAppInternal(const std::string& app_id,
                          extension_misc::AppLaunchBucket bucket,
                          app_home::mojom::ClickEventPtr click_event,
@@ -154,7 +155,7 @@
   void FillWebAppInfoList(std::vector<app_home::mojom::AppInfoPtr>* result);
   void FillExtensionInfoList(std::vector<app_home::mojom::AppInfoPtr>* result);
   app_home::mojom::AppInfoPtr CreateAppInfoPtrFromWebApp(
-      const web_app::AppId& app_id);
+      const webapps::AppId& app_id);
   app_home::mojom::AppInfoPtr CreateAppInfoPtrFromExtension(
       const extensions::Extension* extension);
 
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
index 9d4658b..948eb8a 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
@@ -43,7 +43,7 @@
 #include "base/test/scoped_path_override.h"
 #endif  // BUILDFLAG(IS_WIN)
 
-using web_app::AppId;
+using webapps::AppId;
 using GetAppsCallback =
     base::OnceCallback<void(std::vector<app_home::mojom::AppInfoPtr>)>;
 
@@ -110,12 +110,12 @@
   }
 
  private:
-  void OnWebAppInstalled(const web_app::AppId& app_id) override {
+  void OnWebAppInstalled(const webapps::AppId& app_id) override {
     run_loop_->Quit();
     AppHomePageHandler::OnWebAppInstalled(app_id);
   }
 
-  void OnWebAppWillBeUninstalled(const web_app::AppId& app_id) override {
+  void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) override {
     run_loop_->Quit();
     AppHomePageHandler::OnWebAppWillBeUninstalled(app_id);
   }
@@ -135,7 +135,7 @@
   }
 
   void OnWebAppRunOnOsLoginModeChanged(
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       web_app::RunOnOsLoginMode run_on_os_login_mode) override {
     std::move(run_on_os_login_mode_changed_handle_).Run();
     AppHomePageHandler::OnWebAppRunOnOsLoginModeChanged(app_id,
@@ -195,10 +195,11 @@
     return extensions::ExtensionSystem::Get(profile())->extension_service();
   }
 
-  AppId InstallTestWebApp(WebappInstallSource install_source =
-                              WebappInstallSource::OMNIBOX_INSTALL_ICON,
-                          std::string test_app_name = kTestAppName) {
-    AppId installed_app_id = web_app::test::InstallWebApp(
+  webapps::AppId InstallTestWebApp(
+      WebappInstallSource install_source =
+          WebappInstallSource::OMNIBOX_INSTALL_ICON,
+      std::string test_app_name = kTestAppName) {
+    webapps::AppId installed_app_id = web_app::test::InstallWebApp(
         profile(), BuildWebAppInfo(test_app_name),
         /*overwrite_existing_manifest_fields=*/false, install_source);
 
@@ -207,7 +208,7 @@
 
   Profile* profile() { return browser()->profile(); }
 
-  void UninstallTestWebApp(const web_app::AppId& app_id) {
+  void UninstallTestWebApp(const webapps::AppId& app_id) {
     web_app::test::UninstallWebApp(profile(), app_id);
   }
 
@@ -293,7 +294,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(AppHomePageHandlerTest, GetApps) {
-  AppId installed_app_id = InstallTestWebApp();
+  webapps::AppId installed_app_id = InstallTestWebApp();
 
   std::unique_ptr<TestAppHomePageHandler> page_handler =
       GetAppHomePageHandler();
@@ -308,7 +309,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(AppHomePageHandlerTest, ForceInstalledApp) {
-  AppId installed_app_id =
+  webapps::AppId installed_app_id =
       InstallTestWebApp(WebappInstallSource::EXTERNAL_POLICY);
 
   std::unique_ptr<TestAppHomePageHandler> page_handler =
@@ -325,7 +326,7 @@
   std::unique_ptr<TestAppHomePageHandler> page_handler =
       GetAppHomePageHandler();
   EXPECT_CALL(page_, AddApp(MatchAppName(kTestAppName)));
-  AppId installed_app_id = InstallTestWebApp();
+  webapps::AppId installed_app_id = InstallTestWebApp();
   page_handler->Wait();
 }
 
@@ -345,7 +346,7 @@
 
   // First, install a web app for test.
   EXPECT_CALL(page_, AddApp(MatchAppName(kTestAppName)));
-  AppId installed_app_id = InstallTestWebApp();
+  webapps::AppId installed_app_id = InstallTestWebApp();
   page_handler->Wait();
 
   // Check uninstall previous web app will call `RemoveApp` API.
@@ -378,7 +379,7 @@
 
   // First, install a test web app for test.
   EXPECT_CALL(page_, AddApp(MatchAppName(kTestAppName)));
-  AppId installed_app_id = InstallTestWebApp();
+  webapps::AppId installed_app_id = InstallTestWebApp();
   page_handler->Wait();
 
   // Then, check uninstalling previous web app via using
@@ -417,7 +418,7 @@
 
   // First, install a test web app for test.
   EXPECT_CALL(page_, AddApp(MatchAppName(kTestAppName)));
-  AppId installed_app_id = InstallTestWebApp();
+  webapps::AppId installed_app_id = InstallTestWebApp();
   page_handler->Wait();
 
   content::WebContentsAddedObserver nav_observer;
@@ -434,7 +435,7 @@
 
   // First, install a test web app for test.
   EXPECT_CALL(page_, AddApp(MatchAppName(kTestAppName)));
-  AppId installed_app_id = InstallTestWebApp();
+  webapps::AppId installed_app_id = InstallTestWebApp();
   page_handler->Wait();
 
 #if BUILDFLAG(IS_MAC)
@@ -489,7 +490,7 @@
       GetAppHomePageHandler();
   EXPECT_CALL(page_, AddApp(MatchAppName(kTestAppName)))
       .Times(testing::AtLeast(1));
-  AppId installed_app_id = InstallTestWebApp();
+  webapps::AppId installed_app_id = InstallTestWebApp();
   page_handler->Wait();
 
   page_handler->SetRunOnOsLoginMode(installed_app_id,
diff --git a/chrome/browser/ui/webui/app_settings/web_app_settings_navigation_throttle.cc b/chrome/browser/ui/webui/app_settings/web_app_settings_navigation_throttle.cc
index 0c1144b..780a19b 100644
--- a/chrome/browser/ui/webui/app_settings/web_app_settings_navigation_throttle.cc
+++ b/chrome/browser/ui/webui/app_settings/web_app_settings_navigation_throttle.cc
@@ -50,7 +50,7 @@
     return content::NavigationThrottle::PROCEED;
   }
 
-  const web_app::AppId app_id =
+  const webapps::AppId app_id =
       web_app::GetAppIdFromAppSettingsUrl(navigation_handle()->GetURL());
   if (app_id.empty()) {
     return content::NavigationThrottle::BLOCK_REQUEST;
@@ -84,7 +84,7 @@
 }
 
 void WebAppSettingsNavigationThrottle::ContinueCheckForApp(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   content::WebContents* web_contents = navigation_handle()->GetWebContents();
   Profile* profile =
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
diff --git a/chrome/browser/ui/webui/app_settings/web_app_settings_navigation_throttle.h b/chrome/browser/ui/webui/app_settings/web_app_settings_navigation_throttle.h
index 090145a..c30184e 100644
--- a/chrome/browser/ui/webui/app_settings/web_app_settings_navigation_throttle.h
+++ b/chrome/browser/ui/webui/app_settings/web_app_settings_navigation_throttle.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/navigation_throttle.h"
 
 namespace content {
@@ -33,7 +34,7 @@
   const char* GetNameForLogging() override;
 
  private:
-  void ContinueCheckForApp(const web_app::AppId& app_id);
+  void ContinueCheckForApp(const webapps::AppId& app_id);
 
   base::WeakPtrFactory<WebAppSettingsNavigationThrottle> weak_factory_{this};
 };
diff --git a/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc b/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
index e514987..a7d3a76d 100644
--- a/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
+++ b/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
@@ -145,10 +145,10 @@
 }
 
 void WebAppSettingsUI::OnWebAppUninstalled(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   auto* web_contents = web_ui()->GetWebContents();
-  const web_app::AppId current_app_id =
+  const webapps::AppId current_app_id =
       web_app::GetAppIdFromAppSettingsUrl(web_contents->GetURL());
 
   if (app_id == current_app_id)
diff --git a/chrome/browser/ui/webui/app_settings/web_app_settings_ui.h b/chrome/browser/ui/webui/app_settings/web_app_settings_ui.h
index a540214..0d06dcb 100644
--- a/chrome/browser/ui/webui/app_settings/web_app_settings_ui.h
+++ b/chrome/browser/ui/webui/app_settings/web_app_settings_ui.h
@@ -11,6 +11,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
+#include "components/webapps/common/web_app_id.h"
 #include "ui/webui/mojo_web_ui_controller.h"
 #include "ui/webui/resources/cr_components/app_management/app_management.mojom-forward.h"
 
@@ -36,7 +37,7 @@
 
   // WebAppInstallManagerObserver:
   void OnWebAppUninstalled(
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
   void OnWebAppInstallManagerDestroyed() override;
 
diff --git a/chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.cc b/chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.cc
new file mode 100644
index 0000000..bfc826b
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.cc
@@ -0,0 +1,32 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h"
+
+#include "base/logging.h"
+#include "chrome/browser/ash/login/oobe_screen.h"
+#include "chrome/browser/ash/login/screens/online_authentication_screen.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/login/localized_values_builder.h"
+
+namespace ash {
+
+OnlineAuthenticationScreenHandler::OnlineAuthenticationScreenHandler()
+    : BaseScreenHandler(kScreenId) {}
+
+OnlineAuthenticationScreenHandler::~OnlineAuthenticationScreenHandler() =
+    default;
+
+void OnlineAuthenticationScreenHandler::DeclareLocalizedValues(
+    ::login::LocalizedValuesBuilder* builder) {}
+
+void OnlineAuthenticationScreenHandler::DeclareJSCallbacks() {}
+
+void OnlineAuthenticationScreenHandler::Show() {
+  ShowInWebUI();
+}
+
+void OnlineAuthenticationScreenHandler::Hide() {}
+
+}  // namespace ash
diff --git a/chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h b/chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h
new file mode 100644
index 0000000..713dd22
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h
@@ -0,0 +1,52 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_ASH_LOGIN_ONLINE_AUTHENTICATION_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_ASH_LOGIN_ONLINE_AUTHENTICATION_SCREEN_HANDLER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/webui/ash/login/base_screen_handler.h"
+
+namespace ash {
+
+class OnlineAuthenticationScreenView
+    : public base::SupportsWeakPtr<OnlineAuthenticationScreenView> {
+ public:
+  inline constexpr static StaticOobeScreenId kScreenId{
+      "online-authentication-screen", "OnlineAuthenticationScreen"};
+
+  virtual void Show() = 0;
+  virtual void Hide() = 0;
+};
+
+// A class that handles WebUI hooks in Gaia screen.
+class OnlineAuthenticationScreenHandler : public OnlineAuthenticationScreenView,
+                                          public BaseScreenHandler {
+ public:
+  using TView = OnlineAuthenticationScreenView;
+
+  OnlineAuthenticationScreenHandler();
+
+  OnlineAuthenticationScreenHandler(const OnlineAuthenticationScreenHandler&) =
+      delete;
+  OnlineAuthenticationScreenHandler& operator=(
+      const OnlineAuthenticationScreenHandler&) = delete;
+
+  ~OnlineAuthenticationScreenHandler() override;
+
+  void Show() override;
+  void Hide() override;
+
+ private:
+  // BaseScreenHandler implementation:
+  void DeclareLocalizedValues(
+      ::login::LocalizedValuesBuilder* builder) override;
+  void DeclareJSCallbacks() override;
+
+  base::WeakPtrFactory<OnlineAuthenticationScreenHandler> weak_factory_{this};
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_UI_WEBUI_ASH_LOGIN_GAIA_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/ash/login/oobe_ui.cc b/chrome/browser/ui/webui/ash/login/oobe_ui.cc
index 2f31c76b..28c048d 100644
--- a/chrome/browser/ui/webui/ash/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/ash/login/oobe_ui.cc
@@ -91,6 +91,7 @@
 #include "chrome/browser/ui/webui/ash/login/network_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/network_state_informer.h"
 #include "chrome/browser/ui/webui/ash/login/offline_login_screen_handler.h"
+#include "chrome/browser/ui/webui/ash/login/online_authentication_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/oobe_display_chooser.h"
 #include "chrome/browser/ui/webui/ash/login/os_install_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/os_trial_screen_handler.h"
@@ -483,6 +484,8 @@
   AddScreenHandler(std::make_unique<GaiaScreenHandler>(network_state_informer_,
                                                        error_screen));
 
+  AddScreenHandler(std::make_unique<OnlineAuthenticationScreenHandler>());
+
   AddScreenHandler(std::make_unique<UserAllowlistCheckScreenHandler>());
 
   AddScreenHandler(std::make_unique<SamlConfirmPasswordHandler>());
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 1db8e9b..12ba4ff4 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -147,7 +147,7 @@
   return extension_id == extension_misc::kYoutubeAppId;
 }
 
-void GetWebAppBasicInfo(const web_app::AppId& app_id,
+void GetWebAppBasicInfo(const webapps::AppId& app_id,
                         const web_app::WebAppRegistrar& app_registrar,
                         base::Value::Dict* info) {
   info->Set(kInfoIdKey, app_id);
@@ -197,7 +197,7 @@
 }
 
 base::Value::Dict AppLauncherHandler::CreateWebAppInfo(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   base::Value::Dict dict;
 
   // Communicate the kiosk flag so the apps page can disable showing the
@@ -545,7 +545,7 @@
   ExtensionRemoved(extension, /*is_uninstall=*/true);
 }
 
-void AppLauncherHandler::OnWebAppInstalled(const web_app::AppId& app_id) {
+void AppLauncherHandler::OnWebAppInstalled(const webapps::AppId& app_id) {
   if (attempting_web_app_install_page_ordinal_.has_value()) {
     AppSorting* sorting =
         ExtensionSystem::Get(Profile::FromWebUI(web_ui()))->app_sorting();
@@ -561,7 +561,7 @@
 }
 
 void AppLauncherHandler::OnWebAppFirstInstallTimeChanged(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     const base::Time& time) {
   // Use the appAdded to update the app icon's color to no longer be
   // greyscale.
@@ -570,7 +570,7 @@
 }
 
 void AppLauncherHandler::OnWebAppWillBeUninstalled(
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   base::Value::Dict app_info;
   // Since `isUninstall` is true below, the only item needed in the app_info
   // dictionary is the id.
@@ -582,7 +582,7 @@
 }
 
 void AppLauncherHandler::OnWebAppUninstalled(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   // This can be redundant in most cases, however it is not uncommon for the
   // chrome://apps page to be loaded, or reloaded, during the uninstallation of
@@ -600,7 +600,7 @@
 }
 
 void AppLauncherHandler::OnWebAppRunOnOsLoginModeChanged(
-    const web_app::AppId& app_id,
+    const webapps::AppId& app_id,
     web_app::RunOnOsLoginMode run_on_os_login_mode) {
   CallJavascriptFunction("ntp.appAdded", base::Value(CreateWebAppInfo(app_id)));
 }
@@ -627,9 +627,9 @@
   Profile* profile = Profile::FromWebUI(web_ui());
   PrefService* prefs = profile->GetPrefs();
 
-  std::set<web_app::AppId> web_app_ids;
+  std::set<webapps::AppId> web_app_ids;
   web_app::WebAppRegistrar& registrar = web_app_provider_->registrar_unsafe();
-  for (const web_app::AppId& web_app_id : registrar.GetAppIds()) {
+  for (const webapps::AppId& web_app_id : registrar.GetAppIds()) {
     // The Youtube app is harded to be a 'bookmark app', however it is not, it
     // is a platform app.
     // TODO(crbug.com/1065748): Remove this hack once the youtube app is fixed.
@@ -1273,7 +1273,7 @@
 
   web_app::OnceInstallCallback install_complete_callback = base::BindOnce(
       [](base::WeakPtr<AppLauncherHandler> app_launcher_handler,
-         const web_app::AppId& app_id,
+         const webapps::AppId& app_id,
          webapps::InstallResultCode install_result) {
         if (!app_launcher_handler)
           return;
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.h b/chrome/browser/ui/webui/ntp/app_launcher_handler.h
index 57a3ade..9ab3a31 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.h
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.h
@@ -28,6 +28,7 @@
 #include "components/favicon/core/favicon_service.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/sync/model/string_ordinal.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "extensions/browser/extension_registry_observer.h"
@@ -75,7 +76,7 @@
 
   ~AppLauncherHandler() override;
 
-  base::Value::Dict CreateWebAppInfo(const web_app::AppId& app_id);
+  base::Value::Dict CreateWebAppInfo(const webapps::AppId& app_id);
 
   base::Value::Dict CreateExtensionInfo(const extensions::Extension* extension);
 
@@ -105,19 +106,19 @@
                               extensions::UninstallReason reason) override;
 
   // web_app::OnWebAppInstallManagerObserver:
-  void OnWebAppInstalled(const web_app::AppId& app_id) override;
-  void OnWebAppWillBeUninstalled(const web_app::AppId& app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& app_id) override;
+  void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) override;
   void OnWebAppUninstalled(
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
   void OnWebAppInstallManagerDestroyed() override;
 
   // web_app::WebAppRegistrarObserver:
-  void OnWebAppFirstInstallTimeChanged(const web_app::AppId& app_id,
+  void OnWebAppFirstInstallTimeChanged(const webapps::AppId& app_id,
                                        const base::Time& time) override;
   void OnAppRegistrarDestroyed() override;
   void OnWebAppRunOnOsLoginModeChanged(
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       web_app::RunOnOsLoginMode run_on_os_login_mode) override;
   void OnWebAppSettingsPolicyChanged() override;
 
@@ -128,7 +129,7 @@
   base::Value::Dict GetExtensionInfo(const extensions::Extension* extension);
 
   // Create a dictionary value for the given web app.
-  base::Value::Dict GetWebAppInfo(const web_app::AppId& app_id);
+  base::Value::Dict GetWebAppInfo(const webapps::AppId& app_id);
 
   // Handles the "launchApp" message with unused |args|.
   void HandleGetApps(const base::Value::List& args);
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler_unittest.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler_unittest.cc
index 52539e3..80f7763 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler_unittest.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler_unittest.cc
@@ -30,7 +30,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using OsIntegrationSubManagersState = web_app::OsIntegrationSubManagersState;
-using AppId = web_app::AppId;
+using AppId = webapps::AppId;
 using WebAppProvider = web_app::WebAppProvider;
 
 namespace {
@@ -119,8 +119,8 @@
 
   // Install a web app and sets the locally installed property based on
   // |is_locally_installed|.
-  AppId InstallWebApp(bool is_locally_installed = true) {
-    AppId installed_app_id =
+  webapps::AppId InstallWebApp(bool is_locally_installed = true) {
+    webapps::AppId installed_app_id =
         web_app::test::InstallWebApp(profile(), BuildWebAppInfo());
     if (is_locally_installed)
       return installed_app_id;
@@ -136,7 +136,7 @@
   // web app.
   void ValidateLocallyInstalledCallData(
       TestAppLauncherHandler* app_launcher_handler,
-      const AppId& installed_app_id) {
+      const webapps::AppId& installed_app_id) {
     ASSERT_EQ(1U, app_launcher_handler->call_data().size());
     EXPECT_EQ(kMethodNameAppAdded,
               app_launcher_handler->call_data()[0]->function_name());
@@ -188,7 +188,8 @@
 // Tests that AppLauncherHandler::HandleInstallAppLocally calls the JS method
 // "ntp.appAdded" for the locally installed app.
 TEST_P(AppLauncherHandlerTest, HandleInstallAppLocally) {
-  AppId installed_app_id = InstallWebApp(/*is_locally_installed=*/false);
+  webapps::AppId installed_app_id =
+      InstallWebApp(/*is_locally_installed=*/false);
 
   // Initialize the web_ui instance.
   std::unique_ptr<content::WebContents> test_web_contents =
@@ -215,7 +216,8 @@
 // Tests that AppLauncherHandler::HandleInstallAppLocally calls the JS method
 // "ntp.appAdded" for the all the running instances of chrome://apps page.
 TEST_P(AppLauncherHandlerTest, HandleInstallAppLocally_MultipleWebUI) {
-  AppId installed_app_id = InstallWebApp(/*is_locally_installed=*/false);
+  webapps::AppId installed_app_id =
+      InstallWebApp(/*is_locally_installed=*/false);
 
   // Initialize the first web_ui instance.
   std::unique_ptr<content::WebContents> test_web_contents_1 =
diff --git a/chrome/browser/ui/webui/realbox/realbox_handler.cc b/chrome/browser/ui/webui/realbox/realbox_handler.cc
index ddd929a9..6b161d4 100644
--- a/chrome/browser/ui/webui/realbox/realbox_handler.cc
+++ b/chrome/browser/ui/webui/realbox/realbox_handler.cc
@@ -587,6 +587,10 @@
   source->AddBoolean(
       "realboxLensDirectUpload",
       base::FeatureList::IsEnabled(ntp_features::kNtpLensDirectUpload));
+
+  source->AddBoolean(
+      "omniboxActionsUISimplification",
+      base::FeatureList::IsEnabled(omnibox::kOmniboxActionsUISimplification));
 }
 
 // static
diff --git a/chrome/browser/ui/webui/settings/ash/device_section.cc b/chrome/browser/ui/webui/settings/ash/device_section.cc
index abb67a2..0b13783f 100644
--- a/chrome/browser/ui/webui/settings/ash/device_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/device_section.cc
@@ -49,7 +49,11 @@
 using ::chromeos::settings::mojom::kCustomizeTabletButtonsSubpagePath;
 using ::chromeos::settings::mojom::kDeviceSectionPath;
 using ::chromeos::settings::mojom::kDisplaySubpagePath;
+using ::chromeos::settings::mojom::kEditDictionarySubpagePath;
 using ::chromeos::settings::mojom::kGraphicsTabletSubpagePath;
+using ::chromeos::settings::mojom::kInputMethodOptionsSubpagePath;
+using ::chromeos::settings::mojom::kInputSubpagePath;
+using ::chromeos::settings::mojom::kJapaneseManageUserDictionarySubpagePath;
 using ::chromeos::settings::mojom::kKeyboardSubpagePath;
 using ::chromeos::settings::mojom::kPerDeviceKeyboardRemapKeysSubpagePath;
 using ::chromeos::settings::mojom::kPerDeviceKeyboardSubpagePath;
@@ -1158,6 +1162,9 @@
 }
 
 void DeviceSection::RegisterHierarchy(HierarchyGenerator* generator) const {
+  const bool kIsRevampEnabled =
+      ash::features::IsOsSettingsRevampWayfindingEnabled();
+
   // Pointers.
   generator->RegisterTopLevelSubpage(
       IDS_SETTINGS_MOUSE_AND_TOUCHPAD_TITLE, mojom::Subpage::kPointers,
@@ -1185,9 +1192,8 @@
                             generator);
 
   const int kKeyboardTitleStringID =
-      ash::features::IsOsSettingsRevampWayfindingEnabled()
-          ? IDS_OS_SETTINGS_REVAMP_KEYBOARD_AND_INPUTS_TITLE
-          : IDS_SETTINGS_KEYBOARD_TITLE;
+      kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_KEYBOARD_AND_INPUTS_TITLE
+                       : IDS_SETTINGS_KEYBOARD_TITLE;
   if (base::FeatureList::IsEnabled(ash::features::kInputDeviceSettingsSplit)) {
     // Per-device Keyboard.
     generator->RegisterTopLevelSubpage(kKeyboardTitleStringID,
@@ -1281,6 +1287,52 @@
   RegisterNestedSettingBulk(mojom::Subpage::kKeyboard, kKeyboardSettings,
                             generator);
 
+  if (kIsRevampEnabled) {
+    // Input subpage
+    generator->RegisterTopLevelSubpage(
+        IDS_OS_SETTINGS_LANGUAGES_INPUT_PAGE_TITLE_V2, mojom::Subpage::kInput,
+        mojom::SearchResultIcon::kGlobe,
+        mojom::SearchResultDefaultRank::kMedium, mojom::kInputSubpagePath);
+    static constexpr mojom::Setting kInputSubpageSettings[] = {
+        mojom::Setting::kAddInputMethod,
+        mojom::Setting::kShowEmojiSuggestions,
+        mojom::Setting::kShowInputOptionsInShelf,
+        mojom::Setting::kSpellCheck,
+    };
+    RegisterNestedSettingBulk(mojom::Subpage::kInput, kInputSubpageSettings,
+                              generator);
+
+    // Edit dictionary subpage
+    generator->RegisterNestedSubpage(
+        IDS_OS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_LABEL,
+        mojom::Subpage::kEditDictionary, mojom::Subpage::kInput,
+        mojom::SearchResultIcon::kGlobe,
+        mojom::SearchResultDefaultRank::kMedium,
+        mojom::kEditDictionarySubpagePath);
+
+    // Japanese Manage User Dictionary subpage
+    generator->RegisterNestedSubpage(
+        IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL,
+        mojom::Subpage::kJapaneseManageUserDictionary, mojom::Subpage::kInput,
+        mojom::SearchResultIcon::kGlobe,
+        mojom::SearchResultDefaultRank::kMedium,
+        mojom::kJapaneseManageUserDictionarySubpagePath);
+
+    // Input method options subpage
+    generator->RegisterNestedSubpage(
+        IDS_SETTINGS_LANGUAGES_INPUT_METHOD_OPTIONS_TITLE,
+        mojom::Subpage::kInputMethodOptions, mojom::Subpage::kInput,
+        mojom::SearchResultIcon::kGlobe,
+        mojom::SearchResultDefaultRank::kMedium,
+        mojom::kInputMethodOptionsSubpagePath);
+    static constexpr mojom::Setting kInputMethodOptionsSubpageSettings[] = {
+        mojom::Setting::kShowPKAutoCorrection,
+        mojom::Setting::kShowVKAutoCorrection,
+    };
+    RegisterNestedSettingBulk(mojom::Subpage::kInputMethodOptions,
+                              kInputMethodOptionsSubpageSettings, generator);
+  }
+
   // Stylus.
   generator->RegisterTopLevelSubpage(
       IDS_SETTINGS_STYLUS_TITLE, mojom::Subpage::kStylus,
diff --git a/chrome/browser/ui/webui/settings/ash/languages_section.cc b/chrome/browser/ui/webui/settings/ash/languages_section.cc
index 610942c..cf7b470 100644
--- a/chrome/browser/ui/webui/settings/ash/languages_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/languages_section.cc
@@ -641,57 +641,60 @@
       mojom::Subpage::kLanguages, mojom::SearchResultIcon::kGlobe,
       mojom::SearchResultDefaultRank::kMedium, mojom::kLanguagesSubpagePath);
   static constexpr mojom::Setting kLanguagesPageSettings[] = {
+      mojom::Setting::kAddLanguage,
       mojom::Setting::kChangeDeviceLanguage,
       mojom::Setting::kOfferTranslation,
   };
   RegisterNestedSettingBulk(mojom::Subpage::kLanguages, kLanguagesPageSettings,
                             generator);
 
-  // Input.
-  generator->RegisterTopLevelSubpage(
-      ash::features::IsOsSettingsRevampWayfindingEnabled()
-          ? IDS_OS_SETTINGS_LANGUAGES_INPUT_PAGE_TITLE
-          : IDS_OS_SETTINGS_LANGUAGES_INPUT_PAGE_TITLE_V2,
-      mojom::Subpage::kInput, mojom::SearchResultIcon::kGlobe,
-      mojom::SearchResultDefaultRank::kMedium, mojom::kInputSubpagePath);
-  static constexpr mojom::Setting kInputPageSettings[] = {
-      mojom::Setting::kAddInputMethod,
-      mojom::Setting::kShowEmojiSuggestions,
-      mojom::Setting::kSpellCheck,
-  };
-  RegisterNestedSettingBulk(mojom::Subpage::kInput, kInputPageSettings,
-                            generator);
+  // Input settings subpages are associated with the Device section when
+  // OsSettingsRevampWayfinding is enabled.
+  if (!ash::features::IsOsSettingsRevampWayfindingEnabled()) {
+    // Input subpage
+    generator->RegisterTopLevelSubpage(
+        IDS_OS_SETTINGS_LANGUAGES_INPUT_PAGE_TITLE_V2, mojom::Subpage::kInput,
+        mojom::SearchResultIcon::kGlobe,
+        mojom::SearchResultDefaultRank::kMedium, mojom::kInputSubpagePath);
+    static constexpr mojom::Setting kInputSubpageSettings[] = {
+        mojom::Setting::kAddInputMethod,
+        mojom::Setting::kShowEmojiSuggestions,
+        mojom::Setting::kShowInputOptionsInShelf,
+        mojom::Setting::kSpellCheck,
+    };
+    RegisterNestedSettingBulk(mojom::Subpage::kInput, kInputSubpageSettings,
+                              generator);
 
-  // Edit dictionary.
-  generator->RegisterNestedSubpage(
-      IDS_OS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_LABEL,
-      mojom::Subpage::kEditDictionary, mojom::Subpage::kInput,
-      mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium,
-      mojom::kEditDictionarySubpagePath);
+    // Edit dictionary subpage
+    generator->RegisterNestedSubpage(
+        IDS_OS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_LABEL,
+        mojom::Subpage::kEditDictionary, mojom::Subpage::kInput,
+        mojom::SearchResultIcon::kGlobe,
+        mojom::SearchResultDefaultRank::kMedium,
+        mojom::kEditDictionarySubpagePath);
 
-  // Japanese Manage User Dictionary
-  generator->RegisterNestedSubpage(
-      IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL,
-      mojom::Subpage::kJapaneseManageUserDictionary, mojom::Subpage::kInput,
-      mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium,
-      mojom::kJapaneseManageUserDictionarySubpagePath);
+    // Japanese Manage User Dictionary subpage
+    generator->RegisterNestedSubpage(
+        IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL,
+        mojom::Subpage::kJapaneseManageUserDictionary, mojom::Subpage::kInput,
+        mojom::SearchResultIcon::kGlobe,
+        mojom::SearchResultDefaultRank::kMedium,
+        mojom::kJapaneseManageUserDictionarySubpagePath);
 
-  generator->RegisterNestedSetting(mojom::Setting::kAddLanguage,
-                                   mojom::Subpage::kLanguages);
-  generator->RegisterNestedSetting(mojom::Setting::kShowInputOptionsInShelf,
-                                   mojom::Subpage::kInput);
-
-  // Input method options.
-  generator->RegisterNestedSubpage(
-      IDS_SETTINGS_LANGUAGES_INPUT_METHOD_OPTIONS_TITLE,
-      mojom::Subpage::kInputMethodOptions, mojom::Subpage::kInput,
-      mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium,
-      mojom::kInputMethodOptionsSubpagePath);
-
-  generator->RegisterNestedSetting(mojom::Setting::kShowPKAutoCorrection,
-                                   mojom::Subpage::kInputMethodOptions);
-  generator->RegisterNestedSetting(mojom::Setting::kShowVKAutoCorrection,
-                                   mojom::Subpage::kInputMethodOptions);
+    // Input method options subpage
+    generator->RegisterNestedSubpage(
+        IDS_SETTINGS_LANGUAGES_INPUT_METHOD_OPTIONS_TITLE,
+        mojom::Subpage::kInputMethodOptions, mojom::Subpage::kInput,
+        mojom::SearchResultIcon::kGlobe,
+        mojom::SearchResultDefaultRank::kMedium,
+        mojom::kInputMethodOptionsSubpagePath);
+    static constexpr mojom::Setting kInputMethodOptionsSubpageSettings[] = {
+        mojom::Setting::kShowPKAutoCorrection,
+        mojom::Setting::kShowVKAutoCorrection,
+    };
+    RegisterNestedSettingBulk(mojom::Subpage::kInputMethodOptions,
+                              kInputMethodOptionsSubpageSettings, generator);
+  }
 }
 
 bool LanguagesSection::IsEmojiSuggestionAllowed() const {
diff --git a/chrome/browser/ui/webui/settings/ash/personalization_section.cc b/chrome/browser/ui/webui/settings/ash/personalization_section.cc
index ab19450..f589d4a 100644
--- a/chrome/browser/ui/webui/settings/ash/personalization_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/personalization_section.cc
@@ -36,6 +36,8 @@
       {"personalizationPageTitle", isRevampEnabled_
                                        ? IDS_OS_SETTINGS_REVAMP_PERSONALIZATION
                                        : IDS_OS_SETTINGS_PERSONALIZATION},
+      {"personalizationMenuItemDescription",
+       IDS_OS_SETTINGS_PERSONALIZATION_MENU_ITEM_DESCRIPTION},
       {"personalizationHubTitle",
        isRevampEnabled_ ? IDS_OS_SETTINGS_REVAMP_OPEN_PERSONALIZATION_HUB
                         : IDS_OS_SETTINGS_OPEN_PERSONALIZATION_HUB},
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index 6a572aa..0ae55230 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -1057,6 +1057,7 @@
   // gets set automatically.
   service->SetSyncFeatureRequested();
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // If the first-time setup is already complete, there's nothing else to do.
   if (service->GetUserSettings()->IsInitialSyncFeatureSetupComplete()) {
     return;
@@ -1070,6 +1071,7 @@
   service->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
       syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM);
   FireWebUIListener("sync-settings-saved");
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void PeopleHandler::MaybeMarkSyncConfiguring() {
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index df1d9a7..c7b7189 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -1127,14 +1127,6 @@
 
   handler_->HandleShowSyncSetupUI(base::Value::List());
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  // Now sync gets reset from the dashboard (the user clicked the "Manage synced
-  // data" link), which results in the first-setup-complete bit being cleared.
-  // While first-setup isn't completed, IsSyncFeatureDisabledViaDashboard() also
-  // returns false.
-  ON_CALL(*mock_sync_service_, IsSyncFeatureDisabledViaDashboard())
-      .WillByDefault(Return(false));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   ON_CALL(*mock_sync_service_->GetMockUserSettings(),
           IsInitialSyncFeatureSetupComplete())
       .WillByDefault(Return(false));
@@ -1154,6 +1146,7 @@
                 Return(syncer::SyncService::TransportState::INITIALIZING));
         NotifySyncStateChanged();
       });
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(),
               SetInitialSyncFeatureSetupComplete(
                   syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM))
@@ -1163,6 +1156,7 @@
             .WillByDefault(Return(true));
         NotifySyncStateChanged();
       });
+#endif
 
   base::Value::List did_abort;
   did_abort.Append(false);
@@ -1179,15 +1173,16 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Now sync gets reset from the dashboard (the user clicked the "Manage synced
-  // data" link), which results in the first-setup-complete bit being cleared.
-  // While first-setup isn't completed, IsSyncFeatureDisabledViaDashboard() also
-  // returns false.
+  // data" link), which results in IsSyncFeatureDisabledViaDashboard() returning
+  // true.
   ON_CALL(*mock_sync_service_, IsSyncFeatureDisabledViaDashboard())
-      .WillByDefault(Return(false));
-#endif
+      .WillByDefault(Return(true));
+#else
   ON_CALL(*mock_sync_service_->GetMockUserSettings(),
           IsInitialSyncFeatureSetupComplete())
       .WillByDefault(Return(false));
+#endif
+
   // Sync will eventually start again in transport mode.
   ON_CALL(*mock_sync_service_, GetTransportState())
       .WillByDefault(
@@ -1200,7 +1195,7 @@
   ON_CALL(*mock_sync_service_, GetTransportState())
       .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE));
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  // The first-setup-complete bit gets set automatically during engine startup.
+  // The first-setup-complete bit is always true on ChromeOS Ash.
   ON_CALL(*mock_sync_service_->GetMockUserSettings(),
           IsInitialSyncFeatureSetupComplete())
       .WillByDefault(Return(true));
@@ -1208,8 +1203,8 @@
   NotifySyncStateChanged();
 
   // Now the user confirms sync again. This should set the sync-requested bit
-  // and (if it wasn't automatically set above already) also the
-  // first-setup-complete bit.
+  // and also the first-setup-complete bit (except on ChromeOS Ash where it is
+  // always true).
   EXPECT_CALL(*mock_sync_service_, SetSyncFeatureRequested())
       .WillOnce([&]() {
         ON_CALL(*mock_sync_service_, GetTransportState())
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc
index 9a7c40e..2c1f20ee 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -2324,14 +2324,14 @@
                          [](const url::Origin& origin) { return origin; }},
         *entry.data_owner);
 
-    // If the storage is backed by a StorageKey we need to ensure the grouping
-    // key matches the top-site and doesn't default to the origin in the UI.
+    // If the storage is partitioned on a third party we need to ensure the
+    // grouping key matches the top-site and doesn't default to the origin
+    // in the UI.
     absl::optional<GroupingKey> partition_grouping_key = absl::nullopt;
-    const blink::StorageKey* storage_key =
-        absl::get_if<blink::StorageKey>(&entry.data_key.get());
-    if (storage_key != nullptr && storage_key->IsThirdPartyContext()) {
-      partition_grouping_key = GroupingKey::Create(
-          url::Origin::Create(GURL(storage_key->top_level_site().Serialize())));
+    auto third_party_partitioning_site = entry.GetThirdPartyPartitioningSite();
+    if (third_party_partitioning_site) {
+      partition_grouping_key = GroupingKey::Create(url::Origin::Create(
+          GURL(third_party_partitioning_site->Serialize())));
     }
     UpdateDataFromModel(all_sites_map, origin_size_map, origin,
                         entry.data_details->storage_size,
diff --git a/chrome/browser/ui/webui/side_panel/performance_controls/performance_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/performance_controls/performance_page_handler_unittest.cc
new file mode 100644
index 0000000..56ca8bcf
--- /dev/null
+++ b/chrome/browser/ui/webui/side_panel/performance_controls/performance_page_handler_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "chrome/browser/ui/webui/side_panel/performance_controls/performance_page_handler.h"
+
+#include "chrome/browser/ui/webui/side_panel/performance_controls/performance_side_panel_ui.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+
+namespace {
+
+class TestPerformancePageHandler : public PerformancePageHandler {
+ public:
+  TestPerformancePageHandler()
+      : PerformancePageHandler(
+            mojo::PendingReceiver<side_panel::mojom::PerformancePageHandler>(),
+            mojo::PendingRemote<side_panel::mojom::PerformancePage>(),
+            static_cast<PerformanceSidePanelUI*>(nullptr)) {}
+};
+
+class PerformancePageHandlerTest : public BrowserWithTestWindowTest {
+ public:
+  void SetUp() override {
+    BrowserWithTestWindowTest::SetUp();
+    handler_ = std::make_unique<TestPerformancePageHandler>();
+  }
+
+  void TearDown() override {
+    handler_.reset();
+    BrowserWithTestWindowTest::TearDown();
+  }
+
+  TestPerformancePageHandler* handler() { return handler_.get(); }
+
+ private:
+  std::unique_ptr<TestPerformancePageHandler> handler_;
+};
+
+TEST_F(PerformancePageHandlerTest, ConstructsHandler) {
+  ASSERT_NE(handler(), nullptr);
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
index cb842544..a18b78af 100644
--- a/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
@@ -274,11 +274,14 @@
   }
 
   service->SetSyncFeatureRequested();
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   // If the service was previously stopped via StopAndClear(), then the
   // "first-setup-complete" bit was also cleared, and now the service wouldn't
   // fully start up. So set that too.
   service->GetUserSettings()->SetInitialSyncFeatureSetupComplete(
       syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 void SyncInternalsMessageHandler::HandleRequestStopClearData(
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 6a663f3..9551462 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -240,7 +240,6 @@
     "web_app_icon_generator.h",
     "web_app_icon_manager.cc",
     "web_app_icon_manager.h",
-    "web_app_id.h",
     "web_app_id_constants.h",
     "web_app_install_finalizer.cc",
     "web_app_install_finalizer.h",
diff --git a/chrome/browser/web_applications/alternative_error_page_override_info_browsertest.cc b/chrome/browser/web_applications/alternative_error_page_override_info_browsertest.cc
index bcc95bd..b376c97 100644
--- a/chrome/browser/web_applications/alternative_error_page_override_info_browsertest.cc
+++ b/chrome/browser/web_applications/alternative_error_page_override_info_browsertest.cc
@@ -9,12 +9,12 @@
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
 #include "chrome/browser/web_applications/test/web_app_icon_waiter.h"
 #include "chrome/browser/web_applications/test/web_app_test_utils.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/url_formatter/url_formatter.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/common/alternative_error_page_override_info.mojom.h"
 #include "content/public/common/content_client.h"
 #include "content/public/test/browser_test.h"
@@ -170,7 +170,7 @@
   Profile* profile = browser()->profile();
   web_app::WebAppProvider* web_app_provider =
       web_app::WebAppProvider::GetForTest(profile);
-  const absl::optional<web_app::AppId> app_id =
+  const absl::optional<webapps::AppId> app_id =
       web_app_provider->registrar_unsafe().FindAppWithUrlInScope(app_url);
   WebAppIconWaiter(profile, app_id.value()).Wait();
   content::mojom::AlternativeErrorPageOverrideInfoPtr info =
diff --git a/chrome/browser/web_applications/app_service/BUILD.gn b/chrome/browser/web_applications/app_service/BUILD.gn
index 282abf7..4ed08ed 100644
--- a/chrome/browser/web_applications/app_service/BUILD.gn
+++ b/chrome/browser/web_applications/app_service/BUILD.gn
@@ -33,6 +33,7 @@
     "//components/services/app_service",
     "//components/sessions",
     "//components/webapps/browser",
+    "//components/webapps/common",
     "//url",
   ]
 
diff --git a/chrome/browser/web_applications/app_service/browser_shortcuts.cc b/chrome/browser/web_applications/app_service/browser_shortcuts.cc
index f44e7137..c323ca7e 100644
--- a/chrome/browser/web_applications/app_service/browser_shortcuts.cc
+++ b/chrome/browser/web_applications/app_service/browser_shortcuts.cc
@@ -70,7 +70,8 @@
   // Register publisher for shortcuts created from browser.
   RegisterShortcutPublisher(apps::AppType::kChromeApp);
 
-  for (const AppId& web_app_id : provider_->registrar_unsafe().GetAppIds()) {
+  for (const webapps::AppId& web_app_id :
+       provider_->registrar_unsafe().GetAppIds()) {
     MaybePublishBrowserShortcut(web_app_id);
   }
 
@@ -81,7 +82,7 @@
   }
 }
 
-bool BrowserShortcuts::IsShortcut(const AppId& app_id) {
+bool BrowserShortcuts::IsShortcut(const webapps::AppId& app_id) {
   if (base::FeatureList::IsEnabled(features::kCrosWebAppShortcutUiUpdate)) {
     return provider_->registrar_unsafe().IsShortcutApp(app_id);
   } else {
@@ -89,7 +90,7 @@
   }
 }
 
-void BrowserShortcuts::MaybePublishBrowserShortcut(const AppId& app_id,
+void BrowserShortcuts::MaybePublishBrowserShortcut(const webapps::AppId& app_id,
                                                    bool raw_icon_updated) {
   if (!IsShortcut(app_id)) {
     return;
@@ -155,11 +156,12 @@
                                     scale_factor, std::move(callback));
 }
 
-void BrowserShortcuts::OnWebAppInstalled(const AppId& app_id) {
+void BrowserShortcuts::OnWebAppInstalled(const webapps::AppId& app_id) {
   MaybePublishBrowserShortcut(app_id);
 }
 
-void BrowserShortcuts::OnWebAppInstalledWithOsHooks(const AppId& app_id) {
+void BrowserShortcuts::OnWebAppInstalledWithOsHooks(
+    const webapps::AppId& app_id) {
   MaybePublishBrowserShortcut(app_id);
 }
 
@@ -168,7 +170,7 @@
 }
 
 void BrowserShortcuts::OnWebAppUninstalled(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   if (!IsShortcut(app_id)) {
     return;
diff --git a/chrome/browser/web_applications/app_service/browser_shortcuts.h b/chrome/browser/web_applications/app_service/browser_shortcuts.h
index a58c681..05c364f 100644
--- a/chrome/browser/web_applications/app_service/browser_shortcuts.h
+++ b/chrome/browser/web_applications/app_service/browser_shortcuts.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "components/webapps/common/web_app_id.h"
 
 static_assert(BUILDFLAG(IS_CHROMEOS_ASH), "For ash only");
 
@@ -46,13 +47,13 @@
 
   void InitBrowserShortcuts();
 
-  bool IsShortcut(const AppId& app_id);
+  bool IsShortcut(const webapps::AppId& app_id);
 
   // Publish web app identified by `app_id` as browser shortcut to the
   // AppService if the web app is considered as shortcut in ChromeOS.
   // `raw_icon_updated` should be set when the manifest raw icon has
   // changed to allow AppService icon directory to clear the old icons.
-  void MaybePublishBrowserShortcut(const AppId& app_id,
+  void MaybePublishBrowserShortcut(const webapps::AppId& app_id,
                                    bool raw_icon_updated = false);
 
   // apps::ShortcutPublisher:
@@ -68,11 +69,11 @@
                              apps::LoadIconCallback callback) override;
 
   // WebAppInstallManagerObserver:
-  void OnWebAppInstalled(const AppId& app_id) override;
-  void OnWebAppInstalledWithOsHooks(const AppId& app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& app_id) override;
+  void OnWebAppInstalledWithOsHooks(const webapps::AppId& app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
   void OnWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
 
   const raw_ptr<Profile> profile_;
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 df49268..52c0478 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
@@ -381,7 +381,8 @@
   std::move(callback).Run(std::move(menu_items));
 }
 
-const WebApp* LacrosWebAppsController::GetWebApp(const AppId& app_id) const {
+const WebApp* LacrosWebAppsController::GetWebApp(
+    const webapps::AppId& app_id) const {
   return registrar().GetAppById(app_id);
 }
 
diff --git a/chrome/browser/web_applications/app_service/lacros_web_apps_controller.h b/chrome/browser/web_applications/app_service/lacros_web_apps_controller.h
index b4ae238..44e9fa3 100644
--- a/chrome/browser/web_applications/app_service/lacros_web_apps_controller.h
+++ b/chrome/browser/web_applications/app_service/lacros_web_apps_controller.h
@@ -22,6 +22,7 @@
 #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/permission.h"
+#include "components/webapps/common/web_app_id.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -114,7 +115,7 @@
       base::OnceCallback<void(crosapi::mojom::LaunchResultPtr)> callback,
       const std::vector<content::WebContents*>& web_contents);
 
-  const WebApp* GetWebApp(const AppId& app_id) const;
+  const WebApp* GetWebApp(const webapps::AppId& app_id) const;
 
   void OnShortcutsMenuIconsRead(
       const std::string& app_id,
diff --git a/chrome/browser/web_applications/app_service/lacros_web_apps_controller_browsertest.cc b/chrome/browser/web_applications/app_service/lacros_web_apps_controller_browsertest.cc
index 7161f83..c31bc4c 100644
--- a/chrome/browser/web_applications/app_service/lacros_web_apps_controller_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/lacros_web_apps_controller_browsertest.cc
@@ -53,7 +53,6 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
@@ -78,6 +77,7 @@
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/cpp/permission.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/desktop_media_id.h"
 #include "content/public/browser/media_stream_request.h"
 #include "content/public/browser/web_contents.h"
@@ -236,7 +236,7 @@
   mock_app_publisher.Wait();
   EXPECT_EQ(mock_app_publisher.get_deltas().size(), 2U);
 
-  AppId app_id = InstallWebAppFromManifest(
+  webapps::AppId app_id = InstallWebAppFromManifest(
       browser(),
       embedded_test_server()->GetURL("/banners/manifest_test_page.html"));
   mock_app_publisher.Wait();
@@ -269,7 +269,7 @@
 
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, LaunchTime) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  AppId app_id = InstallWebAppFromManifest(
+  webapps::AppId app_id = InstallWebAppFromManifest(
       browser(), embedded_test_server()->GetURL("/web_apps/basic.html"));
 
   MockAppPublisher mock_app_publisher;
@@ -301,7 +301,7 @@
   lacros_web_apps_controller.SetPublisherForTesting(&mock_app_publisher);
   lacros_web_apps_controller.Init();
 
-  AppId app_id;
+  webapps::AppId app_id;
   {
     const std::u16string original_description = u"Original Web App";
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
@@ -327,7 +327,7 @@
     base::RunLoop run_loop;
     provider().install_finalizer().FinalizeUpdate(
         *web_app_info,
-        base::BindLambdaForTesting([&run_loop](const AppId& app_id,
+        base::BindLambdaForTesting([&run_loop](const webapps::AppId& app_id,
                                                webapps::InstallResultCode code,
                                                OsHooksErrors os_hooks_errors) {
           EXPECT_EQ(code, webapps::InstallResultCode::kSuccessAlreadyInstalled);
@@ -348,7 +348,7 @@
   const GURL app_url =
       embedded_test_server()->GetURL("app.site.com", "/simple.html");
 
-  AppId app_id;
+  webapps::AppId app_id;
   {
     const std::u16string description = u"Web App";
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
@@ -386,7 +386,7 @@
   const GURL app_url = embedded_test_server()->GetURL("/web_apps/basic.html");
   const GURL install_url =
       embedded_test_server()->GetURL("/web_apps/get_manifest.html?basic.json");
-  AppId app_id = InstallWebAppFromPage(browser(), install_url);
+  webapps::AppId app_id = InstallWebAppFromPage(browser(), install_url);
   MockAppPublisher mock_app_publisher;
   LacrosWebAppsController lacros_web_apps_controller(profile());
   lacros_web_apps_controller.SetPublisherForTesting(&mock_app_publisher);
@@ -420,7 +420,7 @@
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, ContentSettings) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
 
   // Install an additional app from a different host.
   {
@@ -464,7 +464,7 @@
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, MediaRequest) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   Browser* browser = LaunchWebAppBrowserAndWait(app_id);
   content::WebContents* web_contents =
       browser->tab_strip_model()->GetActiveWebContents();
@@ -518,7 +518,7 @@
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, Launch) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
 
   MockAppPublisher mock_app_publisher;
   LacrosWebAppsController lacros_web_apps_controller(profile());
@@ -544,7 +544,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url =
       embedded_test_server()->GetURL("/web_apps/file_handler_index.html");
-  AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   EXPECT_EQ(provider().registrar_unsafe().GetAppStartUrl(app_id), app_url);
 
   MockAppPublisher mock_app_publisher;
@@ -603,7 +603,7 @@
   lacros_web_apps_controller.SetPublisherForTesting(&mock_app_publisher);
   lacros_web_apps_controller.Init();
 
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   LaunchWebAppBrowserAndWait(app_id);
   mock_app_publisher.Wait();
 
@@ -654,7 +654,7 @@
   lacros_web_apps_controller.Init();
   mock_app_publisher.Wait();
 
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   Browser* app_browser = LaunchWebAppBrowserAndWait(app_id);
 
   AsAppController(lacros_web_apps_controller).StopApp(app_id);
@@ -676,7 +676,7 @@
 
   const GURL app_url =
       https_server()->GetURL("/web_app_shortcuts/shortcuts.html");
-  const AppId app_id = InstallWebAppFromPage(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromPage(browser(), app_url);
   crosapi::mojom::AppController& lacros_web_apps_controller =
       *apps::AppServiceProxyFactory::GetForProfile(profile())
            ->LacrosWebAppsControllerForTesting();
@@ -708,7 +708,7 @@
                        ExecuteContextMenuCommand) {
   const GURL app_url =
       https_server()->GetURL("/web_app_shortcuts/shortcuts.html");
-  const AppId app_id = InstallWebAppFromPage(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromPage(browser(), app_url);
   LacrosWebAppsController& lacros_web_apps_controller =
       *apps::AppServiceProxyFactory::GetForProfile(profile())
            ->LacrosWebAppsControllerForTesting();
@@ -742,7 +742,7 @@
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, OpenNativeSettings) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
 
   MockAppPublisher mock_app_publisher;
   LacrosWebAppsController lacros_web_apps_controller(profile());
@@ -761,7 +761,7 @@
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, WindowMode) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
 
   MockAppPublisher mock_app_publisher;
   LacrosWebAppsController lacros_web_apps_controller(profile());
@@ -785,7 +785,7 @@
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, Notification) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
 
   MockAppPublisher mock_app_publisher;
   LacrosWebAppsController lacros_web_apps_controller(profile());
@@ -819,10 +819,10 @@
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, DisabledState) {
   ASSERT_TRUE(embedded_test_server()->Start());
   WebAppSyncBridge& web_app_sync_bridge = provider().sync_bridge_unsafe();
-  const AppId app_id = InstallWebAppFromManifest(
+  const webapps::AppId app_id = InstallWebAppFromManifest(
       browser(), embedded_test_server()->GetURL("/web_apps/basic.html"));
 
-  AppId app2_id;
+  webapps::AppId app2_id;
   {
     const std::u16string description = u"Uninstalled Web App";
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
@@ -901,7 +901,7 @@
 
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, GetLink) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const AppId app_id = InstallWebAppFromManifest(
+  const webapps::AppId app_id = InstallWebAppFromManifest(
       browser(),
       embedded_test_server()->GetURL("/web_share_target/gatherer.html"));
   const GURL share_target_url =
@@ -950,7 +950,7 @@
 
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, ShareImage) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const AppId app_id = InstallWebAppFromManifest(
+  const webapps::AppId app_id = InstallWebAppFromManifest(
       browser(),
       embedded_test_server()->GetURL("/web_share_target/multimedia.html"));
   const std::string kData(12, '*');
@@ -1003,7 +1003,7 @@
 
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, ShareMultimedia) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const AppId app_id = InstallWebAppFromManifest(
+  const webapps::AppId app_id = InstallWebAppFromManifest(
       browser(),
       embedded_test_server()->GetURL("/web_share_target/multimedia.html"));
   const std::string kAudioContent(345, '*');
diff --git a/chrome/browser/web_applications/app_service/lacros_web_apps_controller_lacros_browsertest.cc b/chrome/browser/web_applications/app_service/lacros_web_apps_controller_lacros_browsertest.cc
index 3e72e0a..7729934 100644
--- a/chrome/browser/web_applications/app_service/lacros_web_apps_controller_lacros_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/lacros_web_apps_controller_lacros_browsertest.cc
@@ -33,7 +33,7 @@
 // Test that the default context menu for a web app has the correct items.
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, DefaultContextMenu) {
   InstallTestWebApp();
-  const AppId app_id = test_web_app_id();
+  const webapps::AppId app_id = test_web_app_id();
 
   // No item should exist in the shelf before the web app is launched.
   ASSERT_TRUE(browser_test_util::WaitForShelfItem(app_id, /*exists=*/false));
@@ -70,7 +70,7 @@
 // Test that ShowSiteSettings() launches the Settings SWA.
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, AppManagement) {
   InstallTestWebApp();
-  const AppId app_id = test_web_app_id();
+  const webapps::AppId app_id = test_web_app_id();
   apps::AppReadinessWaiter(profile(), kOsSettingsAppId).Await();
 
   Browser* browser = OpenTestWebApp();
@@ -119,7 +119,7 @@
   }
 
   InstallTestWebApp();
-  const AppId app_id = test_web_app_id();
+  const webapps::AppId app_id = test_web_app_id();
 
   // No item should exist in the shelf before the web app is launched.
   ASSERT_TRUE(browser_test_util::WaitForShelfItem(app_id, /*exists=*/false));
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 b77d6f4..3def943 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
@@ -487,7 +487,7 @@
 WebAppPublisherHelper::BadgeManagerDelegate::~BadgeManagerDelegate() = default;
 
 void WebAppPublisherHelper::BadgeManagerDelegate::OnAppBadgeUpdated(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (!publisher_helper_) {
     return;
   }
@@ -787,7 +787,7 @@
 }
 
 apps::AppPtr WebAppPublisherHelper::ConvertUninstalledWebApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   auto app = std::make_unique<apps::App>(app_type(), app_id);
   app->readiness = ConvertWebappUninstallSourceToReadiness(uninstall_source);
@@ -1246,7 +1246,7 @@
       "WebAppPublisherHelper::SetWindowMode",
       std::make_unique<AppLockDescription>(app_id),
       base::BindOnce(
-          [](AppId app_id, mojom::UserDisplayMode user_display_mode,
+          [](webapps::AppId app_id, mojom::UserDisplayMode user_display_mode,
              AppLock& lock) {
             lock.sync_bridge().SetAppUserDisplayMode(app_id, user_display_mode,
                                                      /*is_user_action=*/true);
@@ -1363,28 +1363,30 @@
 }
 
 void WebAppPublisherHelper::OnWebAppFileHandlerApprovalStateChanged(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   const WebApp* web_app = GetWebApp(app_id);
   if (web_app) {
     delegate_->PublishWebApp(CreateWebApp(web_app));
   }
 }
 
-void WebAppPublisherHelper::OnWebAppInstalled(const AppId& app_id) {
+void WebAppPublisherHelper::OnWebAppInstalled(const webapps::AppId& app_id) {
   const WebApp* web_app = GetWebApp(app_id);
   if (web_app) {
     delegate_->PublishWebApp(CreateWebApp(web_app));
   }
 }
 
-void WebAppPublisherHelper::OnWebAppInstalledWithOsHooks(const AppId& app_id) {
+void WebAppPublisherHelper::OnWebAppInstalledWithOsHooks(
+    const webapps::AppId& app_id) {
   const WebApp* web_app = GetWebApp(app_id);
   if (web_app) {
     delegate_->PublishWebApp(CreateWebApp(web_app));
   }
 }
 
-void WebAppPublisherHelper::OnWebAppManifestUpdated(const AppId& app_id) {
+void WebAppPublisherHelper::OnWebAppManifestUpdated(
+    const webapps::AppId& app_id) {
   const WebApp* web_app = GetWebApp(app_id);
   if (web_app) {
     auto app = CreateWebApp(web_app);
@@ -1398,9 +1400,8 @@
 }
 
 void WebAppPublisherHelper::OnWebAppUninstalled(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
-
 #if BUILDFLAG(IS_CHROMEOS)
   paused_apps_.MaybeRemoveApp(app_id);
 
@@ -1434,14 +1435,14 @@
 }
 
 void WebAppPublisherHelper::OnWebAppUserDisplayModeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     mojom::UserDisplayMode user_display_mode) {
   PublishWindowModeUpdate(app_id,
                           registrar().GetAppEffectiveDisplayMode(app_id));
 }
 
 void WebAppPublisherHelper::OnWebAppRunOnOsLoginModeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     RunOnOsLoginMode run_on_os_login_mode) {
   PublishRunOnOsLoginModeUpdate(app_id, run_on_os_login_mode);
 }
@@ -1449,8 +1450,9 @@
 #if BUILDFLAG(IS_CHROMEOS)
 // If is_disabled is set, the app backed by |app_id| is published with readiness
 // kDisabledByPolicy, otherwise it's published with readiness kReady.
-void WebAppPublisherHelper::OnWebAppDisabledStateChanged(const AppId& app_id,
-                                                         bool is_disabled) {
+void WebAppPublisherHelper::OnWebAppDisabledStateChanged(
+    const webapps::AppId& app_id,
+    bool is_disabled) {
   const WebApp* web_app = GetWebApp(app_id);
   if (!web_app) {
     return;
@@ -1473,7 +1475,7 @@
 
 void WebAppPublisherHelper::OnWebAppsDisabledModeChanged() {
   std::vector<apps::AppPtr> apps;
-  std::vector<AppId> app_ids = registrar().GetAppIds();
+  std::vector<webapps::AppId> app_ids = registrar().GetAppIds();
   for (const auto& id : app_ids) {
     // We only update visibility of disabled apps in this method. When enabling
     // previously disabled app, OnWebAppDisabledStateChanged() method will be
@@ -1531,7 +1533,7 @@
 void WebAppPublisherHelper::OnIsCapturingVideoChanged(
     content::WebContents* web_contents,
     bool is_capturing_video) {
-  const AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
+  const webapps::AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
   if (!app_id) {
     return;
   }
@@ -1545,7 +1547,7 @@
 void WebAppPublisherHelper::OnIsCapturingAudioChanged(
     content::WebContents* web_contents,
     bool is_capturing_audio) {
-  const AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
+  const webapps::AppId* app_id = WebAppTabHelper::GetAppId(web_contents);
   if (!app_id) {
     return;
   }
@@ -1656,7 +1658,8 @@
   return icon_effects;
 }
 
-const WebApp* WebAppPublisherHelper::GetWebApp(const AppId& app_id) const {
+const WebApp* WebAppPublisherHelper::GetWebApp(
+    const webapps::AppId& app_id) const {
   return registrar().GetAppById(app_id);
 }
 
@@ -1735,7 +1738,7 @@
     return policy_ids;
   }
 
-  base::flat_map<AppId, base::flat_set<GURL>> installed_apps =
+  base::flat_map<webapps::AppId, base::flat_set<GURL>> installed_apps =
       registrar().GetExternallyInstalledApps(
           ExternalInstallSource::kExternalPolicy);
   if (auto it = installed_apps.find(app_id); it != installed_apps.end()) {
@@ -1804,7 +1807,7 @@
 
   if (persistent_metadata) {
     // For persistent notifications, find the web app with the SW scope url.
-    absl::optional<AppId> app_id = FindInstalledAppWithUrlInScope(
+    absl::optional<webapps::AppId> app_id = FindInstalledAppWithUrlInScope(
         profile(), persistent_metadata->service_worker_scope,
         /*window_only=*/false);
     if (app_id.has_value()) {
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.h b/chrome/browser/web_applications/app_service/web_app_publisher_helper.h
index e1aa379..9ad3acb1f 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.h
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.h
@@ -34,6 +34,7 @@
 #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/permission.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/native_widget_types.h"
 
@@ -168,7 +169,7 @@
   // Constructs an App with only the information required to identify an
   // uninstallation.
   apps::AppPtr ConvertUninstalledWebApp(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source);
 
   // Constructs an App with only the information required to update
@@ -300,7 +301,7 @@
 
     ~BadgeManagerDelegate() override;
 
-    void OnAppBadgeUpdated(const AppId& app_id) override;
+    void OnAppBadgeUpdated(const webapps::AppId& app_id) override;
 
    private:
     base::WeakPtr<WebAppPublisherHelper> publisher_helper_;
@@ -308,30 +309,31 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
   // WebAppInstallManagerObserver:
-  void OnWebAppInstalled(const AppId& app_id) override;
-  void OnWebAppInstalledWithOsHooks(const AppId& app_id) override;
-  void OnWebAppManifestUpdated(const AppId& app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& app_id) override;
+  void OnWebAppInstalledWithOsHooks(const webapps::AppId& app_id) override;
+  void OnWebAppManifestUpdated(const webapps::AppId& app_id) override;
   void OnWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
   void OnWebAppInstallManagerDestroyed() override;
 
   // WebAppRegistrarObserver:
   void OnAppRegistrarDestroyed() override;
-  void OnWebAppFileHandlerApprovalStateChanged(const AppId& app_id) override;
+  void OnWebAppFileHandlerApprovalStateChanged(
+      const webapps::AppId& app_id) override;
   void OnWebAppLastLaunchTimeChanged(
       const std::string& app_id,
       const base::Time& last_launch_time) override;
   void OnWebAppUserDisplayModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       mojom::UserDisplayMode user_display_mode) override;
   void OnWebAppRunOnOsLoginModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       RunOnOsLoginMode run_on_os_login_mode) override;
   void OnWebAppSettingsPolicyChanged() override;
 
 #if BUILDFLAG(IS_CHROMEOS)
-  void OnWebAppDisabledStateChanged(const AppId& app_id,
+  void OnWebAppDisabledStateChanged(const webapps::AppId& app_id,
                                     bool is_disabled) override;
   void OnWebAppsDisabledModeChanged() override;
 
@@ -364,7 +366,7 @@
 
   apps::IconEffects GetIconEffects(const WebApp* web_app);
 
-  const WebApp* GetWebApp(const AppId& app_id) const;
+  const WebApp* GetWebApp(const webapps::AppId& app_id) const;
 
   // Returns all the WebContents instances launched via `callback`. This value
   // may be empty if the launch fails. There may be more than one `WebContents`
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper_browsertest.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper_browsertest.cc
index 7485dd8..983db6b 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper_browsertest.cc
@@ -11,11 +11,11 @@
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
 #include "chrome/browser/web_applications/web_app.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/gurl.h"
@@ -133,7 +133,7 @@
   apps::IntentFilters filters;
   {
     auto& provider = *web_app::WebAppProvider::GetForTest(browser()->profile());
-    const web_app::AppId app_id =
+    const webapps::AppId app_id =
         web_app::InstallWebAppFromManifest(browser(), app_url);
     filters = WebAppPublisherHelper::CreateIntentFiltersForWebApp(
         provider, *provider.registrar_unsafe().GetAppById(app_id));
@@ -164,7 +164,7 @@
   apps::IntentFilters filters;
   {
     auto& provider = *web_app::WebAppProvider::GetForTest(browser()->profile());
-    const web_app::AppId app_id =
+    const webapps::AppId app_id =
         web_app::InstallWebAppFromManifest(browser(), app_url);
     filters = WebAppPublisherHelper::CreateIntentFiltersForWebApp(
         provider, *provider.registrar_unsafe().GetAppById(app_id));
@@ -193,7 +193,7 @@
   apps::IntentFilters filters;
   {
     auto& provider = *web_app::WebAppProvider::GetForTest(browser()->profile());
-    const web_app::AppId app_id =
+    const webapps::AppId app_id =
         web_app::InstallWebAppFromManifest(browser(), app_url);
     filters = WebAppPublisherHelper::CreateIntentFiltersForWebApp(
         provider, *provider.registrar_unsafe().GetAppById(app_id));
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc
index 5c4027d..f1b7f76 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc
@@ -103,7 +103,7 @@
   info->title = base::UTF8ToUTF16(name);
   info->start_url = start_url;
 
-  AppId app_id = test::InstallWebApp(profile(), std::move(info));
+  webapps::AppId app_id = test::InstallWebApp(profile(), std::move(info));
   const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   apps::AppPtr app = publisher_->CreateWebApp(web_app);
 
@@ -127,7 +127,7 @@
 
     // Unable to install a randomly generated web app struct, so just copy
     // necessary fields into the installation flow.
-    AppId app_id = test::InstallWebApp(profile(), std::move(info));
+    webapps::AppId app_id = test::InstallWebApp(profile(), std::move(info));
     EXPECT_EQ(app_id, random_app->app_id());
     apps::AppPtr app = publisher_->CreateWebApp(random_app.get());
 
@@ -147,7 +147,7 @@
   info->start_url = start_url;
   info->note_taking_new_note_url = new_note_url;
 
-  AppId app_id = test::InstallWebApp(profile(), std::move(info));
+  webapps::AppId app_id = test::InstallWebApp(profile(), std::move(info));
   const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   apps::AppPtr app = publisher_->CreateWebApp(web_app);
 
@@ -164,7 +164,7 @@
   info->start_url = start_url;
   info->lock_screen_start_url = lock_screen_url;
 
-  AppId app_id = test::InstallWebApp(profile(), std::move(info));
+  webapps::AppId app_id = test::InstallWebApp(profile(), std::move(info));
   const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   apps::AppPtr app = publisher_->CreateWebApp(web_app);
 
@@ -346,7 +346,7 @@
   info->start_url = start_url;
   info->lock_screen_start_url = lock_screen_url;
 
-  AppId app_id = test::InstallWebApp(profile(), std::move(info));
+  webapps::AppId app_id = test::InstallWebApp(profile(), std::move(info));
   const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   apps::AppPtr app = publisher_->CreateWebApp(web_app);
 
diff --git a/chrome/browser/web_applications/app_service/web_apps.cc b/chrome/browser/web_applications/app_service/web_apps.cc
index 8c19ca1..ffe78f2 100644
--- a/chrome/browser/web_applications/app_service/web_apps.cc
+++ b/chrome/browser/web_applications/app_service/web_apps.cc
@@ -62,7 +62,7 @@
   }
 }
 
-const WebApp* WebApps::GetWebApp(const AppId& app_id) const {
+const WebApp* WebApps::GetWebApp(const webapps::AppId& app_id) const {
   DCHECK(provider_);
   return provider_->registrar_unsafe().GetAppById(app_id);
 }
@@ -342,7 +342,7 @@
                               /*should_notify_initialized=*/true);
 }
 
-void WebApps::OnGetAppSize(AppId app_id,
+void WebApps::OnGetAppSize(webapps::AppId app_id,
                            absl::optional<ComputeAppSizeCommand::Size> size) {
   auto app = std::make_unique<apps::App>(app_type(), app_id);
   if (!size.has_value()) {
diff --git a/chrome/browser/web_applications/app_service/web_apps.h b/chrome/browser/web_applications/app_service/web_apps.h
index b8a6808f..9ce8fd5b 100644
--- a/chrome/browser/web_applications/app_service/web_apps.h
+++ b/chrome/browser/web_applications/app_service/web_apps.h
@@ -25,6 +25,7 @@
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/menu.h"
 #include "components/services/app_service/public/cpp/permission.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/resource/resource_scale_factor.h"
 #include "url/gurl.h"
@@ -62,7 +63,7 @@
   virtual void Shutdown();
 
  protected:
-  const WebApp* GetWebApp(const AppId& app_id) const;
+  const WebApp* GetWebApp(const webapps::AppId& app_id) const;
 
   Profile* profile() const { return profile_; }
   WebAppProvider* provider() const { return provider_; }
@@ -137,7 +138,7 @@
 
   std::vector<apps::AppPtr> CreateWebApps();
   void InitWebApps();
-  void OnGetAppSize(AppId app_id,
+  void OnGetAppSize(webapps::AppId app_id,
                     absl::optional<ComputeAppSizeCommand::Size> size);
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
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 7559f96c..7ea8b2a2 100644
--- a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
 #include "chrome/browser/ui/web_applications/web_app_launch_process.h"
 #include "chrome/browser/web_applications/web_app.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -26,6 +25,7 @@
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/base/window_open_disposition.h"
@@ -41,7 +41,7 @@
   const GURL app_url(
       embedded_test_server()->GetURL("/web_share_target/charts.html"));
   Profile* const profile = browser()->profile();
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
 
   base::RunLoop run_loop;
   WebAppLaunchProcess::SetOpenApplicationCallbackForTesting(
@@ -75,7 +75,7 @@
   const GURL app_url(
       embedded_test_server()->GetURL("/web_share_target/poster.html"));
   Profile* const profile = browser()->profile();
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
 
   base::RunLoop run_loop;
   WebAppLaunchProcess::SetOpenApplicationCallbackForTesting(
@@ -111,7 +111,7 @@
   const GURL app_url(embedded_test_server()->GetURL("/web_apps/basic.html"));
 
   // Install file handling web app.
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   const WebAppRegistrar& registrar =
       WebAppProvider::GetForTest(browser()->profile())->registrar_unsafe();
   const WebApp* web_app = registrar.GetAppById(app_id);
@@ -128,7 +128,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppsBrowserTest, LaunchAppIconKeyUnchanged) {
   ASSERT_TRUE(embedded_test_server()->Start());
   const GURL app_url(embedded_test_server()->GetURL("/web_apps/basic.html"));
-  const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   auto* proxy =
       apps::AppServiceProxyFactory::GetForProfile(browser()->profile());
 
diff --git a/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc b/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc
index 7771d199..066cf98 100644
--- a/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc
@@ -16,8 +16,8 @@
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -63,7 +63,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppsChromeOsBrowserTest, ShortcutIcons) {
   const GURL app_url =
       https_server()->GetURL("/web_app_shortcuts/shortcuts.html");
-  const web_app::AppId app_id =
+  const webapps::AppId app_id =
       web_app::InstallWebAppFromPage(browser(), app_url);
   LaunchWebAppBrowser(app_id);
 
diff --git a/chrome/browser/web_applications/chromeos_web_app_experiments.cc b/chrome/browser/web_applications/chromeos_web_app_experiments.cc
index 2fb826bc..c8931a93 100644
--- a/chrome/browser/web_applications/chromeos_web_app_experiments.cc
+++ b/chrome/browser/web_applications/chromeos_web_app_experiments.cc
@@ -31,7 +31,7 @@
 
 bool g_always_enabled_for_testing = false;
 
-bool IsExperimentEnabled(const AppId& app_id) {
+bool IsExperimentEnabled(const webapps::AppId& app_id) {
   return g_always_enabled_for_testing || app_id == kMicrosoft365AppId;
 }
 
@@ -45,7 +45,7 @@
 }  // namespace
 
 base::span<const char* const> ChromeOsWebAppExperiments::GetScopeExtensions(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   DCHECK(chromeos::features::IsUploadOfficeToCloudEnabled());
 
   if (!IsExperimentEnabled(app_id))
@@ -58,7 +58,7 @@
 }
 
 size_t ChromeOsWebAppExperiments::GetExtendedScopeScore(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::StringPiece url_spec) {
   DCHECK(chromeos::features::IsUploadOfficeToCloudEnabled());
 
@@ -80,7 +80,8 @@
   return best_score;
 }
 
-bool ChromeOsWebAppExperiments::IgnoreManifestColor(const AppId& app_id) {
+bool ChromeOsWebAppExperiments::IgnoreManifestColor(
+    const webapps::AppId& app_id) {
   DCHECK(chromeos::features::IsUploadOfficeToCloudEnabled());
   return IsExperimentEnabled(app_id);
 }
diff --git a/chrome/browser/web_applications/chromeos_web_app_experiments.h b/chrome/browser/web_applications/chromeos_web_app_experiments.h
index 7deabc02..1422022 100644
--- a/chrome/browser/web_applications/chromeos_web_app_experiments.h
+++ b/chrome/browser/web_applications/chromeos_web_app_experiments.h
@@ -10,6 +10,7 @@
 #include "base/containers/span.h"
 #include "base/strings/string_piece.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "url/gurl.h"
@@ -33,17 +34,18 @@
   // https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-explainer.md.
   // At the moment, we are enabling testing of the proposed feature for
   // certain hard-coded web apps.
-  static base::span<const char* const> GetScopeExtensions(const AppId& app_id);
+  static base::span<const char* const> GetScopeExtensions(
+      const webapps::AppId& app_id);
 
   // Returns the max scope score (similar to
   // WebAppRegistrar::GetUrlInAppScopeScore()) for the experimental extended
   // scopes.
-  static size_t GetExtendedScopeScore(const AppId& app_id,
+  static size_t GetExtendedScopeScore(const webapps::AppId& app_id,
                                       base::StringPiece url_spec);
 
   // Whether the manifest theme_color and background_color should be ignored for
   // `app_id`.
-  static bool IgnoreManifestColor(const AppId& app_id);
+  static bool IgnoreManifestColor(const webapps::AppId& app_id);
 
   static void SetAlwaysEnabledForTesting();
   static void SetScopeExtensionsForTesting(
diff --git a/chrome/browser/web_applications/chromeos_web_app_experiments_browsertest.cc b/chrome/browser/web_applications/chromeos_web_app_experiments_browsertest.cc
index 145e8ee..759ea007 100644
--- a/chrome/browser/web_applications/chromeos_web_app_experiments_browsertest.cc
+++ b/chrome/browser/web_applications/chromeos_web_app_experiments_browsertest.cc
@@ -69,7 +69,7 @@
   }
 
  protected:
-  AppId app_id_;
+  webapps::AppId app_id_;
   GURL extended_scope_;
   GURL extended_scope_page_;
   std::vector<const char* const> extended_scopes_;
diff --git a/chrome/browser/web_applications/commands/clear_browsing_data_command.cc b/chrome/browser/web_applications/commands/clear_browsing_data_command.cc
index 17bb493..e901f997 100644
--- a/chrome/browser/web_applications/commands/clear_browsing_data_command.cc
+++ b/chrome/browser/web_applications/commands/clear_browsing_data_command.cc
@@ -9,11 +9,11 @@
 #include "chrome/browser/web_applications/locks/all_apps_lock.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -25,8 +25,8 @@
 
   WebAppSyncBridge* sync_bridge = &lock.sync_bridge();
   WebAppRegistrar* registrar = &lock.registrar();
-  std::vector<AppId> ids_to_notify_last_launch_time;
-  std::vector<AppId> ids_to_notify_last_badging_time;
+  std::vector<webapps::AppId> ids_to_notify_last_launch_time;
+  std::vector<webapps::AppId> ids_to_notify_last_badging_time;
   {
     ScopedRegistryUpdate update = sync_bridge->BeginUpdate();
     for (const WebApp& web_app : registrar->GetApps()) {
@@ -51,10 +51,10 @@
       }
     }
   }
-  for (const AppId& app_id : ids_to_notify_last_launch_time) {
+  for (const webapps::AppId& app_id : ids_to_notify_last_launch_time) {
     registrar->NotifyWebAppLastLaunchTimeChanged(app_id, base::Time());
   }
-  for (const AppId& app_id : ids_to_notify_last_badging_time) {
+  for (const webapps::AppId& app_id : ids_to_notify_last_badging_time) {
     registrar->NotifyWebAppLastBadgingTimeChanged(app_id, base::Time());
   }
 
diff --git a/chrome/browser/web_applications/commands/compute_app_size_command.cc b/chrome/browser/web_applications/commands/compute_app_size_command.cc
index 899a103d..57671a4 100644
--- a/chrome/browser/web_applications/commands/compute_app_size_command.cc
+++ b/chrome/browser/web_applications/commands/compute_app_size_command.cc
@@ -19,11 +19,11 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/dom_storage_context.h"
 #include "content/public/browser/storage_partition.h"
@@ -32,7 +32,7 @@
 namespace web_app {
 
 ComputeAppSizeCommand::ComputeAppSizeCommand(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     Profile* profile,
     base::OnceCallback<void(absl::optional<Size>)> callback)
     : WebAppCommandTemplate<AppLock>("ComputeAppSizeCommand"),
diff --git a/chrome/browser/web_applications/commands/compute_app_size_command.h b/chrome/browser/web_applications/commands/compute_app_size_command.h
index 34578711..a2cc733 100644
--- a/chrome/browser/web_applications/commands/compute_app_size_command.h
+++ b/chrome/browser/web_applications/commands/compute_app_size_command.h
@@ -18,6 +18,7 @@
 #include "components/browsing_data/content/browsing_data_quota_helper.h"
 #include "components/browsing_data/content/local_storage_helper.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/storage_usage_info.h"
 
 namespace web_app {
@@ -36,7 +37,7 @@
   };
 
   ComputeAppSizeCommand(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       Profile* profile,
       base::OnceCallback<void(absl::optional<Size>)> callback);
 
@@ -66,7 +67,7 @@
   AppLockDescription lock_description_;
   std::unique_ptr<AppLock> lock_;
 
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   const raw_ptr<Profile> profile_;
   base::OnceCallback<void(absl::optional<Size>)> callback_;
   url::Origin origin_;
diff --git a/chrome/browser/web_applications/commands/compute_app_size_command_browsertest.cc b/chrome/browser/web_applications/commands/compute_app_size_command_browsertest.cc
index 08502a4..8acf952 100644
--- a/chrome/browser/web_applications/commands/compute_app_size_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/compute_app_size_command_browsertest.cc
@@ -21,7 +21,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL app_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = InstallWebAppFromPage(browser(), app_url);
+  webapps::AppId app_id = InstallWebAppFromPage(browser(), app_url);
   NavigateToURLAndWait(browser(), app_url);
 
   const char* script = R"(
diff --git a/chrome/browser/web_applications/commands/dedupe_install_urls_command.cc b/chrome/browser/web_applications/commands/dedupe_install_urls_command.cc
index dc90556..c6af7234 100644
--- a/chrome/browser/web_applications/commands/dedupe_install_urls_command.cc
+++ b/chrome/browser/web_applications/commands/dedupe_install_urls_command.cc
@@ -30,9 +30,9 @@
 
 bool g_suppress_for_testing = false;
 
-base::flat_map<GURL, base::flat_set<AppId>> BuildInstallUrlToAppIdsMap(
+base::flat_map<GURL, base::flat_set<webapps::AppId>> BuildInstallUrlToAppIdsMap(
     const WebAppRegistrar& registrar) {
-  base::flat_map<GURL, base::flat_set<AppId>> result;
+  base::flat_map<GURL, base::flat_set<webapps::AppId>> result;
 
   for (const WebApp& app : registrar.GetApps()) {
     for (const auto& [install_source, config] :
@@ -46,16 +46,16 @@
   return result;
 }
 
-const AppId& SelectWebAppToDedupeInto(
+const webapps::AppId& SelectWebAppToDedupeInto(
     const WebAppRegistrar& registrar,
-    const base::flat_set<AppId>& app_ids_with_common_install_url) {
+    const base::flat_set<webapps::AppId>& app_ids_with_common_install_url) {
   CHECK(app_ids_with_common_install_url.size() > 1);
 
-  const AppId* best = nullptr;
+  const webapps::AppId* best = nullptr;
   bool best_looks_like_placeholder = false;
   base::Time best_install_time;
 
-  for (const AppId& app_id : app_ids_with_common_install_url) {
+  for (const webapps::AppId& app_id : app_ids_with_common_install_url) {
     const WebApp& candidate = *registrar.GetAppById(app_id);
     bool candidate_looks_like_placeholder = LooksLikePlaceholder(candidate);
 
@@ -83,13 +83,14 @@
     const WebAppRegistrar& registrar,
     ScopedRegistryUpdate& update,
     const GURL& install_url,
-    const base::flat_set<AppId>& app_ids_with_common_install_url,
-    const AppId& id_to_dedupe_into) {
+    const base::flat_set<webapps::AppId>& app_ids_with_common_install_url,
+    const webapps::AppId& id_to_dedupe_into) {
   std::vector<std::unique_ptr<RemoveInstallUrlJob>> result;
 
   WebApp& app_to_dedupe_into = *update->UpdateApp(id_to_dedupe_into);
 
-  for (const AppId& id_to_dedupe_out_of : app_ids_with_common_install_url) {
+  for (const webapps::AppId& id_to_dedupe_out_of :
+       app_ids_with_common_install_url) {
     if (id_to_dedupe_out_of == id_to_dedupe_into) {
       continue;
     }
@@ -124,14 +125,14 @@
 
 struct DedupeOperations {
   std::vector<std::unique_ptr<RemoveInstallUrlJob>> remove_install_url_jobs;
-  base::flat_map<GURL, AppId> dedupe_choices;
+  base::flat_map<GURL, webapps::AppId> dedupe_choices;
 };
 
 DedupeOperations BuildOperationsToHaveOneAppPerInstallUrl(
     Profile& profile,
     const WebAppRegistrar& registrar,
     ScopedRegistryUpdate& update,
-    base::flat_map<GURL, base::flat_set<AppId>> install_url_to_apps) {
+    base::flat_map<GURL, base::flat_set<webapps::AppId>> install_url_to_apps) {
   DedupeOperations result;
 
   for (const auto& [install_url, app_ids] : install_url_to_apps) {
@@ -139,7 +140,7 @@
       continue;
     }
 
-    const AppId& id_to_dedupe_into =
+    const webapps::AppId& id_to_dedupe_into =
         SelectWebAppToDedupeInto(registrar, app_ids);
     result.dedupe_choices[install_url] = id_to_dedupe_into;
 
@@ -209,7 +210,7 @@
       dict.EnsureDict("duplicate_install_urls");
   for (const auto& [install_url, app_ids] : install_url_to_apps_) {
     base::Value::List* list = duplicates_dict->EnsureList(install_url.spec());
-    for (const AppId& app_id : app_ids) {
+    for (const webapps::AppId& app_id : app_ids) {
       list->Append(app_id);
     }
   }
diff --git a/chrome/browser/web_applications/commands/dedupe_install_urls_command.h b/chrome/browser/web_applications/commands/dedupe_install_urls_command.h
index dc1ed7b..6f15661 100644
--- a/chrome/browser/web_applications/commands/dedupe_install_urls_command.h
+++ b/chrome/browser/web_applications/commands/dedupe_install_urls_command.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -50,8 +51,8 @@
   const AllAppsLockDescription lock_description_;
   std::unique_ptr<AllAppsLock> lock_;
 
-  base::flat_map<GURL, base::flat_set<AppId>> install_url_to_apps_;
-  base::flat_map<GURL, AppId> dedupe_choices_;
+  base::flat_map<GURL, base::flat_set<webapps::AppId>> install_url_to_apps_;
+  base::flat_map<GURL, webapps::AppId> dedupe_choices_;
   base::Value::List completed_job_debug_values_;
 
   std::vector<std::unique_ptr<RemoveInstallUrlJob>> pending_jobs_;
diff --git a/chrome/browser/web_applications/commands/dedupe_install_urls_command_unittest.cc b/chrome/browser/web_applications/commands/dedupe_install_urls_command_unittest.cc
index 6fb51257..2993a37 100644
--- a/chrome/browser/web_applications/commands/dedupe_install_urls_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/dedupe_install_urls_command_unittest.cc
@@ -65,7 +65,7 @@
     CHECK(future.Wait());
   }
 
-  void AddBuggyDefaultInstallToApp(const AppId& app_id,
+  void AddBuggyDefaultInstallToApp(const webapps::AppId& app_id,
                                    const GURL& install_url) {
     ScopedRegistryUpdate update = provider().sync_bridge_unsafe().BeginUpdate();
     WebApp& placeholder_app = *update->UpdateApp(app_id);
@@ -102,9 +102,10 @@
     CHECK(future.Wait());
   }
 
-  AppId ExternallyInstallWebApp(webapps::WebappInstallSource install_surface,
-                                const GURL& install_url,
-                                const GURL& start_url) {
+  webapps::AppId ExternallyInstallWebApp(
+      webapps::WebappInstallSource install_surface,
+      const GURL& install_url,
+      const GURL& start_url) {
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->title = u"Test app";
@@ -140,9 +141,9 @@
   GURL install_url("https://example.com/install_url");
   GURL manifest_url("https://example.com/manifest.json");
   GURL start_url("https://example.com/start_url");
-  AppId placeholder_app_id = GenerateAppIdFromManifestId(
+  webapps::AppId placeholder_app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(install_url));
-  AppId real_app_id = GenerateAppIdFromManifestId(
+  webapps::AppId real_app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(start_url));
 
   // Set up buggy state.
@@ -217,9 +218,9 @@
   GURL install_url("https://example.com/install_url");
   GURL manifest_url("https://example.com/manifest.json");
   GURL start_url("https://example.com/start_url");
-  AppId placeholder_app_id = GenerateAppIdFromManifestId(
+  webapps::AppId placeholder_app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(install_url));
-  AppId real_app_id = GenerateAppIdFromManifestId(
+  webapps::AppId real_app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(start_url));
 
   // Set up buggy state.
@@ -294,9 +295,9 @@
   GURL install_url("https://example.com/install_url");
   GURL manifest_url("https://example.com/manifest.json");
   GURL start_url("https://example.com/start_url");
-  AppId placeholder_app_id = GenerateAppIdFromManifestId(
+  webapps::AppId placeholder_app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(install_url));
-  AppId real_app_id = GenerateAppIdFromManifestId(
+  webapps::AppId real_app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(start_url));
 
   // Set up buggy state.
@@ -403,9 +404,9 @@
       "https://example.com/install_url?with_query_param");
   GURL manifest_url("https://example.com/manifest.json");
   GURL start_url("https://example.com/start_url");
-  AppId placeholder_app_id = GenerateAppIdFromManifestId(
+  webapps::AppId placeholder_app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(install_url));
-  AppId real_app_id = GenerateAppIdFromManifestId(
+  webapps::AppId real_app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(start_url));
 
   // Set up buggy state.
@@ -487,30 +488,30 @@
 
   // Set up duplicate apps.
   GURL install_url_a("https://www.a.com/");
-  AppId app_id_a1 =
+  webapps::AppId app_id_a1 =
       ExternallyInstallWebApp(webapps::WebappInstallSource::EXTERNAL_DEFAULT,
                               install_url_a, install_url_a.Resolve("default"));
-  AppId app_id_a2 =
+  webapps::AppId app_id_a2 =
       ExternallyInstallWebApp(webapps::WebappInstallSource::KIOSK,
                               install_url_a, install_url_a.Resolve("kiosk"));
-  AppId app_id_a3 =
+  webapps::AppId app_id_a3 =
       ExternallyInstallWebApp(webapps::WebappInstallSource::EXTERNAL_POLICY,
                               install_url_a, install_url_a.Resolve("policy"));
 
   GURL install_url_b("https://www.b.com/");
-  AppId app_id_b1 =
+  webapps::AppId app_id_b1 =
       ExternallyInstallWebApp(webapps::WebappInstallSource::ARC, install_url_b,
                               install_url_b.Resolve("arc"));
-  AppId app_id_b2 =
+  webapps::AppId app_id_b2 =
       ExternallyInstallWebApp(webapps::WebappInstallSource::PRELOADED_OEM,
                               install_url_b, install_url_b.Resolve("oem"));
-  AppId app_id_b3 =
+  webapps::AppId app_id_b3 =
       ExternallyInstallWebApp(webapps::WebappInstallSource::MICROSOFT_365_SETUP,
                               install_url_b, install_url_b.Resolve("ms365"));
 
   // All app IDs must be unique.
-  ASSERT_EQ(base::flat_set<AppId>({app_id_a1, app_id_a2, app_id_a3, app_id_b1,
-                                   app_id_b2, app_id_b3})
+  ASSERT_EQ(base::flat_set<webapps::AppId>({app_id_a1, app_id_a2, app_id_a3,
+                                            app_id_b1, app_id_b2, app_id_b3})
                 .size(),
             6u);
 
diff --git a/chrome/browser/web_applications/commands/externally_managed_install_command_browsertest.cc b/chrome/browser/web_applications/commands/externally_managed_install_command_browsertest.cc
index 01b656f..9507692 100644
--- a/chrome/browser/web_applications/commands/externally_managed_install_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/externally_managed_install_command_browsertest.cc
@@ -79,7 +79,7 @@
 
   const ExternallyManagedAppManager::InstallResult& result =
       future.Get<ExternallyManagedAppManager::InstallResult>();
-  const AppId& app_id = *result.app_id;
+  const webapps::AppId& app_id = *result.app_id;
   webapps::InstallResultCode install_code = result.code;
   EXPECT_EQ(install_code, webapps::InstallResultCode::kSuccessNewInstall);
   EXPECT_TRUE(provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -102,7 +102,7 @@
 
   const ExternallyManagedAppManager::InstallResult& result =
       future.Get<ExternallyManagedAppManager::InstallResult>();
-  const AppId& app_id = *result.app_id;
+  const webapps::AppId& app_id = *result.app_id;
   webapps::InstallResultCode install_code = result.code;
   EXPECT_EQ(install_code, webapps::InstallResultCode::kSuccessNewInstall);
   EXPECT_TRUE(provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -129,7 +129,7 @@
 
   const ExternallyManagedAppManager::InstallResult& result =
       future.Get<ExternallyManagedAppManager::InstallResult>();
-  const AppId& app_id = *result.app_id;
+  const webapps::AppId& app_id = *result.app_id;
   webapps::InstallResultCode install_code = result.code;
   EXPECT_EQ(install_code, webapps::InstallResultCode::kSuccessNewInstall);
   EXPECT_TRUE(provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -155,7 +155,7 @@
 
   const ExternallyManagedAppManager::InstallResult& result =
       future.Get<ExternallyManagedAppManager::InstallResult>();
-  const AppId& app_id = *result.app_id;
+  const webapps::AppId& app_id = *result.app_id;
   webapps::InstallResultCode install_code = result.code;
   EXPECT_EQ(install_code, webapps::InstallResultCode::kSuccessNewInstall);
   EXPECT_TRUE(provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -183,7 +183,7 @@
 
   const ExternallyManagedAppManager::InstallResult& result =
       future.Get<ExternallyManagedAppManager::InstallResult>();
-  const AppId& app_id = GenerateAppId(absl::nullopt, kWebAppUrl);
+  const webapps::AppId& app_id = GenerateAppId(absl::nullopt, kWebAppUrl);
   webapps::InstallResultCode install_code = result.code;
   EXPECT_EQ(install_code,
             webapps::InstallResultCode::kNotValidManifestForWebApp);
@@ -210,7 +210,7 @@
 
   const ExternallyManagedAppManager::InstallResult& first_result =
       future_first_install.Get<0>();
-  const AppId& first_app_id = *first_result.app_id;
+  const webapps::AppId& first_app_id = *first_result.app_id;
   webapps::InstallResultCode first_install_code = first_result.code;
   EXPECT_EQ(first_install_code, webapps::InstallResultCode::kSuccessNewInstall);
   EXPECT_TRUE(provider().registrar_unsafe().IsLocallyInstalled(first_app_id));
@@ -241,7 +241,7 @@
 
   const ExternallyManagedAppManager::InstallResult& second_result =
       future_second_install.Get<0>();
-  const AppId& second_app_id = *second_result.app_id;
+  const webapps::AppId& second_app_id = *second_result.app_id;
   webapps::InstallResultCode second_install_code = second_result.code;
   EXPECT_EQ(first_app_id, second_app_id);
   EXPECT_EQ(second_install_code,
@@ -282,7 +282,7 @@
   EXPECT_TRUE(NavigateAndAwaitInstallabilityCheck(browser(), kWebAppUrl));
 
   // Mock an user installing an app by clicking on the omnibox.
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode>
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
       future_first_install;
   provider().scheduler().FetchManifestAndInstall(
       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
@@ -292,7 +292,7 @@
       future_first_install.GetCallback(),
       /*use_fallback=*/false);
 
-  const AppId& first_app_id = future_first_install.Get<0>();
+  const webapps::AppId& first_app_id = future_first_install.Get<0>();
   webapps::InstallResultCode first_install_code = future_first_install.Get<1>();
   EXPECT_EQ(first_install_code, webapps::InstallResultCode::kSuccessNewInstall);
   EXPECT_TRUE(provider().registrar_unsafe().IsLocallyInstalled(first_app_id));
@@ -318,7 +318,7 @@
 
   const ExternallyManagedAppManager::InstallResult& second_result =
       future_second_install.Get<0>();
-  const AppId& second_app_id = *second_result.app_id;
+  const webapps::AppId& second_app_id = *second_result.app_id;
   webapps::InstallResultCode second_install_code = second_result.code;
   EXPECT_EQ(first_app_id, second_app_id);
   EXPECT_EQ(second_install_code,
diff --git a/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command.cc b/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command.cc
index 3bcd3df..e292545 100644
--- a/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command.cc
+++ b/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command.cc
@@ -57,7 +57,7 @@
 }
 
 FetchInstallInfoFromInstallUrlCommand::FetchInstallInfoFromInstallUrlCommand(
-    ManifestId manifest_id,
+    webapps::ManifestId manifest_id,
     GURL install_url,
     base::OnceCallback<void(std::unique_ptr<WebAppInstallInfo>)> callback)
     : WebAppCommandTemplate<SharedWebContentsLock>(
@@ -170,8 +170,10 @@
                                  web_app_info.get());
   }
 
-  AppId app_id = GenerateAppIdFromManifestId(web_app_info->manifest_id);
-  const AppId expected_app_id = GenerateAppIdFromManifestId(manifest_id_);
+  webapps::AppId app_id =
+      GenerateAppIdFromManifestId(web_app_info->manifest_id);
+  const webapps::AppId expected_app_id =
+      GenerateAppIdFromManifestId(manifest_id_);
   if (app_id != expected_app_id) {
     install_error_log_entry_.LogExpectedAppIdError(
         "OnManifestRetrieved", web_app_info->start_url.spec(), app_id,
diff --git a/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command.h b/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command.h
index 9b2223a6..c19ad51c 100644
--- a/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command.h
+++ b/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command.h
@@ -37,7 +37,7 @@
     : public WebAppCommandTemplate<SharedWebContentsLock> {
  public:
   FetchInstallInfoFromInstallUrlCommand(
-      ManifestId manifest_id,
+      webapps::ManifestId manifest_id,
       GURL install_url,
       base::OnceCallback<void(std::unique_ptr<WebAppInstallInfo>)> callback);
   ~FetchInstallInfoFromInstallUrlCommand() override;
@@ -75,7 +75,7 @@
   std::unique_ptr<SharedWebContentsLockDescription> lock_description_;
   std::unique_ptr<SharedWebContentsLock> lock_;
 
-  ManifestId manifest_id_;
+  webapps::ManifestId manifest_id_;
   GURL install_url_;
   base::OnceCallback<void(std::unique_ptr<WebAppInstallInfo>)>
       web_app_install_info_callback_;
diff --git a/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command_unittest.cc b/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command_unittest.cc
index f5726cca8..11f2fe6e 100644
--- a/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/fetch_install_info_from_install_url_command_unittest.cc
@@ -38,7 +38,7 @@
  protected:
   std::unique_ptr<WebAppInstallInfo> CreateAndRunCommand(
       GURL install_url,
-      ManifestId manifest_id,
+      webapps::ManifestId manifest_id,
       bool disable_web_app_info = false,
       bool valid_manifest = true,
       WebAppUrlLoader::Result url_load_result =
diff --git a/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management.cc b/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management.cc
index 0f58fea..6f731677 100644
--- a/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management.cc
+++ b/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management.cc
@@ -15,10 +15,10 @@
 #include "chrome/browser/web_applications/locks/web_app_lock_manager.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h"
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
 #include "components/webapps/browser/installable/installable_logging.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management.h b/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management.h
index c39b30e..83f132d 100644
--- a/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management.h
+++ b/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/installable/installable_logging.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 #include "url/gurl.h"
 
@@ -38,10 +39,10 @@
 };
 using FetchInstallabilityForChromeManagementCallback =
     base::OnceCallback<void(InstallableCheckResult result,
-                            absl::optional<AppId> app_id)>;
+                            absl::optional<webapps::AppId> app_id)>;
 
 // Given a url and web contents, this command determines if the given url is
-// installable, what the AppId is, and if it is already installed.
+// installable, what the webapps::AppId is, and if it is already installed.
 class FetchInstallabilityForChromeManagement
     : public WebAppCommandTemplate<NoopLock> {
  public:
@@ -77,7 +78,7 @@
   std::unique_ptr<NoopLock> noop_lock_;
 
   const GURL url_;
-  AppId app_id_;
+  webapps::AppId app_id_;
 
   base::WeakPtr<content::WebContents> web_contents_;
   const std::unique_ptr<WebAppUrlLoader> url_loader_;
diff --git a/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management_unittest.cc b/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management_unittest.cc
index a7f3ae6..fcf7a20 100644
--- a/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management_unittest.cc
+++ b/chrome/browser/web_applications/commands/fetch_installability_for_chrome_management_unittest.cc
@@ -16,12 +16,12 @@
 #include "chrome/browser/web_applications/test/web_app_test.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h"
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
 #include "components/webapps/browser/installable/installable_logging.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -39,7 +39,7 @@
   const GURL kWebAppUrl = GURL("https://example.com/path/index.html");
   const GURL kWebAppScope = GURL("https://example.com/path/");
   const std::string kWebAppName = "Example App";
-  const AppId kWebAppId =
+  const webapps::AppId kWebAppId =
       GenerateAppId(/*manifest_id=*/absl::nullopt, kWebAppUrl);
 
   FetchInstallabilityForChromeManagementTest() = default;
@@ -64,7 +64,7 @@
 
   struct FetchResult {
     InstallableCheckResult result = InstallableCheckResult::kInstallable;
-    absl::optional<AppId> app_id = absl::nullopt;
+    absl::optional<webapps::AppId> app_id = absl::nullopt;
   };
 
   FetchResult ScheduleCommandAndWait(
@@ -79,12 +79,13 @@
         std::make_unique<FetchInstallabilityForChromeManagement>(
             url, std::move(web_contents), std::move(url_loader),
             std::move(data_retriever),
-            base::BindLambdaForTesting([&](InstallableCheckResult result,
-                                           absl::optional<AppId> app_id) {
-              output.result = result;
-              output.app_id = app_id;
-              run_loop.Quit();
-            })));
+            base::BindLambdaForTesting(
+                [&](InstallableCheckResult result,
+                    absl::optional<webapps::AppId> app_id) {
+                  output.result = result;
+                  output.app_id = app_id;
+                  run_loop.Quit();
+                })));
     run_loop.Run();
     return output;
   }
diff --git a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc
index 733d825..585435ac 100644
--- a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc
+++ b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc
@@ -22,7 +22,6 @@
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
@@ -31,6 +30,7 @@
 #include "components/webapps/browser/features.h"
 #include "components/webapps/browser/installable/installable_logging.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
@@ -246,7 +246,7 @@
   Observe(nullptr);
   SignalCompletionAndSelfDestruct(
       CommandResult::kFailure,
-      base::BindOnce(std::move(install_callback_), AppId(), code));
+      base::BindOnce(std::move(install_callback_), webapps::AppId(), code));
 }
 
 bool FetchManifestAndInstallCommand::IsWebContentsDestroyed() {
@@ -530,7 +530,7 @@
 }
 
 void FetchManifestAndInstallCommand::OnInstallFinalizedMaybeReparentTab(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code,
     OsHooksErrors os_hooks_errors) {
   if (IsWebContentsDestroyed()) {
@@ -563,7 +563,7 @@
 }
 
 void FetchManifestAndInstallCommand::OnInstallCompleted(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code) {
   if (base::FeatureList::IsEnabled(features::kRecordWebAppDebugInfo)) {
     if (install_error_log_entry_.HasErrorDict()) {
diff --git a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h
index 6191be51..f7bf86ea8 100644
--- a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h
+++ b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h
@@ -19,6 +19,7 @@
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_logging.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 
@@ -114,11 +115,12 @@
       DownloadedIconsHttpResults icons_http_results);
   void OnDialogCompleted(bool user_accepted,
                          std::unique_ptr<WebAppInstallInfo> web_app_info);
-  void OnInstallFinalizedMaybeReparentTab(const AppId& app_id,
+  void OnInstallFinalizedMaybeReparentTab(const webapps::AppId& app_id,
                                           webapps::InstallResultCode code,
                                           OsHooksErrors os_hooks_errors);
 
-  void OnInstallCompleted(const AppId& app_id, webapps::InstallResultCode code);
+  void OnInstallCompleted(const webapps::AppId& app_id,
+                          webapps::InstallResultCode code);
 
   void LogInstallInfo();
 
@@ -140,7 +142,7 @@
 
   InstallErrorLogEntry install_error_log_entry_;
 
-  AppId app_id_;
+  webapps::AppId app_id_;
   std::unique_ptr<WebAppInstallInfo> web_app_info_;
   blink::mojom::ManifestPtr opt_manifest_;
   base::Value::Dict debug_log_;
diff --git a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command_browsertest.cc b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command_browsertest.cc
index 09817a91..01fe3373 100644
--- a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command_browsertest.cc
@@ -57,7 +57,7 @@
       browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
       /*bypass_service_worker_check=*/false, CreateDialogCallback(),
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             EXPECT_TRUE(
                 provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -80,7 +80,7 @@
       browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
       /*bypass_service_worker_check=*/false, CreateDialogCallback(),
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             EXPECT_TRUE(
                 provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -92,7 +92,7 @@
       browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
       /*bypass_service_worker_check=*/false, CreateDialogCallback(),
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             EXPECT_TRUE(
                 provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -114,7 +114,7 @@
       browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
       /*bypass_service_worker_check=*/false, CreateDialogCallback(),
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code,
                       webapps::InstallResultCode::kNotValidManifestForWebApp);
             EXPECT_FALSE(
@@ -138,7 +138,7 @@
       /*bypass_service_worker_check=*/false,
       CreateDialogCallback(/*accept=*/false),
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kUserInstallDeclined);
             EXPECT_FALSE(
                 provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -163,7 +163,7 @@
       web_contents->GetWeakPtr(),
       /*bypass_service_worker_check=*/false, CreateDialogCallback(),
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kWebContentsDestroyed);
             EXPECT_FALSE(
                 provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -194,7 +194,7 @@
       web_contents->GetWeakPtr(),
       /*bypass_service_worker_check=*/false, CreateDialogCallback(),
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             EXPECT_TRUE(
                 provider().registrar_unsafe().IsLocallyInstalled(app_id));
@@ -210,7 +210,7 @@
       "/banners/"
       "no_manifest_test_page.html");
   auto web_app = test::CreateWebApp(test_url);
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   {
     ScopedRegistryUpdate update = provider().sync_bridge_unsafe().BeginUpdate();
@@ -237,7 +237,7 @@
           /*accept=*/true,
           /*user_display_mode=*/mojom::UserDisplayMode::kStandalone),
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             loop.Quit();
           }),
@@ -254,7 +254,7 @@
   GURL test_url = https_server()->GetURL("/banners/app_with_nested/index.html");
   EXPECT_TRUE(NavigateAndAwaitInstallabilityCheck(browser(), test_url));
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode>
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
       install_future;
   provider().scheduler().FetchManifestAndInstall(
       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
@@ -265,7 +265,7 @@
   ASSERT_TRUE(install_future.Wait());
   EXPECT_EQ(install_future.Get<webapps::InstallResultCode>(),
             webapps::InstallResultCode::kSuccessNewInstall);
-  AppId app_id = install_future.Get<AppId>();
+  webapps::AppId app_id = install_future.Get<webapps::AppId>();
   EXPECT_TRUE(provider().registrar_unsafe().IsLocallyInstalled(app_id));
   EXPECT_EQ(provider().registrar_unsafe().GetAppUserDisplayMode(app_id),
             mojom::UserDisplayMode::kStandalone);
diff --git a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command_unittest.cc b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command_unittest.cc
index 7d87da3..e0868d8c 100644
--- a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command_unittest.cc
@@ -61,7 +61,7 @@
 class FetchManifestAndInstallCommandTest : public WebAppTest {
  public:
   const GURL kWebAppUrl = GURL("https://example.com/path/index.html");
-  const AppId kWebAppId =
+  const webapps::AppId kWebAppId =
       GenerateAppId(/*manifest_id=*/absl::nullopt, kWebAppUrl);
   const GURL kWebAppManifestUrl =
       GURL("https://example.com/path/manifest.json");
@@ -173,11 +173,11 @@
   }
 
   webapps::InstallResultCode InstallAndWait(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappInstallSource install_surface,
       WebAppInstallDialogCallback dialog_callback,
       bool use_fallback = false) {
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode>
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
         install_future;
     provider()->scheduler().FetchManifestAndInstall(
         install_surface, web_contents()->GetWeakPtr(),
@@ -312,7 +312,7 @@
       web_contents()->GetWeakPtr(),
       /*bypass_service_worker_check=*/false, std::move(dialog_callback),
       base::BindLambdaForTesting(
-          [&](const AppId& id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& id, webapps::InstallResultCode code) {
             result_populated = true;
             result = code;
           }),
@@ -329,7 +329,7 @@
 TEST_F(FetchManifestAndInstallCommandTest, WebContentsDestroyed) {
   SetupPageState();
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode>
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
       install_future;
   provider()->scheduler().FetchManifestAndInstall(
       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
@@ -349,7 +349,7 @@
   SetupPageState();
 
   base::test::TestFuture<void> manifest_fetch_future;
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode>
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
       install_future;
 
   auto& page_state = web_contents_manager().GetOrCreatePageState(kWebAppUrl);
@@ -381,7 +381,7 @@
 
   SetupPageState();
   base::test::TestFuture<void> manifest_fetch_future;
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode>
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
       install_future;
 
   auto& page_state = web_contents_manager().GetOrCreatePageState(kWebAppUrl);
diff --git a/chrome/browser/web_applications/commands/generated_icon_fix_command.cc b/chrome/browser/web_applications/commands/generated_icon_fix_command.cc
index 23e6a086..9872924 100644
--- a/chrome/browser/web_applications/commands/generated_icon_fix_command.cc
+++ b/chrome/browser/web_applications/commands/generated_icon_fix_command.cc
@@ -25,7 +25,7 @@
 namespace web_app {
 
 GeneratedIconFixCommand::GeneratedIconFixCommand(
-    AppId app_id,
+    webapps::AppId app_id,
     base::OnceCallback<void(GeneratedIconFixResult)> callback)
     : WebAppCommandTemplate<SharedWebContentsWithAppLock>(
           "GeneratedIconFixCommand"),
diff --git a/chrome/browser/web_applications/commands/generated_icon_fix_command.h b/chrome/browser/web_applications/commands/generated_icon_fix_command.h
index 0112160..012396e 100644
--- a/chrome/browser/web_applications/commands/generated_icon_fix_command.h
+++ b/chrome/browser/web_applications/commands/generated_icon_fix_command.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -33,7 +34,7 @@
     : public WebAppCommandTemplate<SharedWebContentsWithAppLock> {
  public:
   explicit GeneratedIconFixCommand(
-      AppId app_id,
+      webapps::AppId app_id,
       base::OnceCallback<void(GeneratedIconFixResult)> callback);
   ~GeneratedIconFixCommand() override;
 
@@ -51,7 +52,7 @@
   void OnIconsWritten(bool success);
   void Stop(GeneratedIconFixResult result, base::Location location);
 
-  AppId app_id_;
+  webapps::AppId app_id_;
   base::OnceCallback<void(GeneratedIconFixResult)> callback_;
   SharedWebContentsWithAppLockDescription lock_description_;
   std::unique_ptr<SharedWebContentsWithAppLock> lock_;
diff --git a/chrome/browser/web_applications/commands/install_app_locally_command.cc b/chrome/browser/web_applications/commands/install_app_locally_command.cc
index e2e1794..1841444 100644
--- a/chrome/browser/web_applications/commands/install_app_locally_command.cc
+++ b/chrome/browser/web_applications/commands/install_app_locally_command.cc
@@ -17,16 +17,16 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
 InstallAppLocallyCommand::InstallAppLocallyCommand(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure install_callback)
     : WebAppCommandTemplate<AppLock>("InstallAppLocallyCommand"),
       app_lock_description_(std::make_unique<AppLockDescription>(app_id)),
diff --git a/chrome/browser/web_applications/commands/install_app_locally_command.h b/chrome/browser/web_applications/commands/install_app_locally_command.h
index 4dccc38..219224c 100644
--- a/chrome/browser/web_applications/commands/install_app_locally_command.h
+++ b/chrome/browser/web_applications/commands/install_app_locally_command.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -22,7 +23,7 @@
 
 class InstallAppLocallyCommand : public WebAppCommandTemplate<AppLock> {
  public:
-  InstallAppLocallyCommand(const AppId& app_id,
+  InstallAppLocallyCommand(const webapps::AppId& app_id,
                            base::OnceClosure install_callback);
   ~InstallAppLocallyCommand() override;
 
@@ -41,7 +42,7 @@
   std::unique_ptr<AppLockDescription> app_lock_description_;
   std::unique_ptr<AppLock> app_lock_;
 
-  AppId app_id_;
+  webapps::AppId app_id_;
   base::OnceClosure install_callback_;
   base::Value::Dict debug_log_;
 
diff --git a/chrome/browser/web_applications/commands/install_app_locally_command_unittest.cc b/chrome/browser/web_applications/commands/install_app_locally_command_unittest.cc
index 895323c..b83d71b 100644
--- a/chrome/browser/web_applications/commands/install_app_locally_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/install_app_locally_command_unittest.cc
@@ -92,7 +92,7 @@
     WebAppTest::TearDown();
   }
 
-  AppId InstallNonLocallyInstalledAppWithIcons(
+  webapps::AppId InstallNonLocallyInstalledAppWithIcons(
       std::map<SquareSizePx, SkBitmap> icon_map) {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
@@ -100,7 +100,8 @@
     info->title = u"Test App";
     info->user_display_mode = mojom::UserDisplayMode::kStandalone;
     info->icon_bitmaps.any = std::move(icon_map);
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
 
     // InstallFromInfo does not trigger OS integration.
     provider().scheduler().InstallFromInfo(
@@ -110,11 +111,11 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    const AppId app_id = result.Get<AppId>();
+    const webapps::AppId app_id = result.Get<webapps::AppId>();
     provider().sync_bridge_unsafe().SetAppIsLocallyInstalledForTesting(
         app_id, /*is_locally_installed=*/false);
     return app_id;
@@ -137,7 +138,8 @@
     return bitmap;
   }
 
-  SkColor GetShortcutColor(const AppId& app_id, const std::string& app_name) {
+  SkColor GetShortcutColor(const webapps::AppId& app_id,
+                           const std::string& app_name) {
     if (!HasShortcutsOsIntegration()) {
       return SK_ColorTRANSPARENT;
     }
@@ -189,7 +191,7 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallNonLocallyInstalledAppWithIcons(std::move(icon_map));
 
   auto state =
@@ -231,7 +233,7 @@
 }
 
 TEST_P(InstallAppLocallyCommandTest, NoAppInRegistrarCorrectLog) {
-  const AppId app_id = "abcde";
+  const webapps::AppId app_id = "abcde";
 
   base::test::TestFuture<void> test_future;
   provider().scheduler().InstallAppLocally(app_id, test_future.GetCallback());
diff --git a/chrome/browser/web_applications/commands/install_from_info_command.cc b/chrome/browser/web_applications/commands/install_from_info_command.cc
index 6aa0361..5131aef 100644
--- a/chrome/browser/web_applications/commands/install_from_info_command.cc
+++ b/chrome/browser/web_applications/commands/install_from_info_command.cc
@@ -15,11 +15,11 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -38,7 +38,7 @@
       app_id_(GenerateAppIdFromManifestId(manifest_id_)),
       install_callback_(base::BindOnce(
           [](OnceInstallCallback install_callback,
-             const AppId& app_id,
+             const webapps::AppId& app_id,
              webapps::InstallResultCode code,
              bool _) { std::move(install_callback).Run(app_id, code); },
           std::move(install_callback))),
@@ -66,7 +66,7 @@
       app_id_(GenerateAppIdFromManifestId(manifest_id_)),
       install_callback_(base::BindOnce(
           [](OnceInstallCallback install_callback,
-             const AppId& app_id,
+             const webapps::AppId& app_id,
              webapps::InstallResultCode code,
              bool _) { std::move(install_callback).Run(app_id, code); },
           std::move(install_callback))),
@@ -85,7 +85,7 @@
     webapps::WebappInstallSource install_surface,
     InstallAndReplaceCallback install_callback,
     const WebAppInstallParams& install_params,
-    const std::vector<AppId>& apps_or_extensions_to_uninstall)
+    const std::vector<webapps::AppId>& apps_or_extensions_to_uninstall)
     : WebAppCommandTemplate<AppLock>("InstallFromInfoCommand"),
       profile_(*profile),
       manifest_id_(
@@ -131,7 +131,7 @@
 }
 
 void InstallFromInfoCommand::OnInstallFromInfoJobCompleted(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code,
     OsHooksErrors os_hook_errors) {
   webapps::InstallableMetrics::TrackInstallResult(webapps::IsSuccess(code));
diff --git a/chrome/browser/web_applications/commands/install_from_info_command.h b/chrome/browser/web_applications/commands/install_from_info_command.h
index 09e9e5b8..8fd5e245 100644
--- a/chrome/browser/web_applications/commands/install_from_info_command.h
+++ b/chrome/browser/web_applications/commands/install_from_info_command.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 
@@ -46,7 +47,7 @@
 class InstallFromInfoCommand : public WebAppCommandTemplate<AppLock> {
  public:
   using InstallAndReplaceCallback =
-      base::OnceCallback<void(const AppId& app_id,
+      base::OnceCallback<void(const webapps::AppId& app_id,
                               webapps::InstallResultCode code,
                               bool did_uninstall_and_replace)>;
 
@@ -73,7 +74,7 @@
       webapps::WebappInstallSource install_surface,
       InstallAndReplaceCallback install_callback,
       const WebAppInstallParams& install_params,
-      const std::vector<AppId>& apps_or_extensions_to_uninstall);
+      const std::vector<webapps::AppId>& apps_or_extensions_to_uninstall);
 
   ~InstallFromInfoCommand() override;
 
@@ -83,7 +84,7 @@
   void OnShutdown() override;
   base::Value ToDebugValue() const override;
 
-  void OnInstallFromInfoJobCompleted(const AppId& app_id,
+  void OnInstallFromInfoJobCompleted(const webapps::AppId& app_id,
                                      webapps::InstallResultCode code,
                                      OsHooksErrors os_hook_errors);
   void OnUninstallAndReplaced(webapps::InstallResultCode code,
@@ -94,10 +95,10 @@
 
   raw_ref<Profile> profile_;
 
-  ManifestId manifest_id_;
-  AppId app_id_;
+  webapps::ManifestId manifest_id_;
+  webapps::AppId app_id_;
   InstallAndReplaceCallback install_callback_;
-  std::vector<AppId> apps_or_extensions_to_uninstall_;
+  std::vector<webapps::AppId> apps_or_extensions_to_uninstall_;
 
   std::unique_ptr<AppLockDescription> lock_description_;
   std::unique_ptr<AppLock> lock_;
diff --git a/chrome/browser/web_applications/commands/install_from_info_command_browsertest.cc b/chrome/browser/web_applications/commands/install_from_info_command_browsertest.cc
index db160bd..bf8a701 100644
--- a/chrome/browser/web_applications/commands/install_from_info_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/install_from_info_command_browsertest.cc
@@ -37,7 +37,7 @@
         });
   }
 
-  std::map<SquareSizePx, SkBitmap> ReadIcons(const AppId& app_id,
+  std::map<SquareSizePx, SkBitmap> ReadIcons(const webapps::AppId& app_id,
                                              IconPurpose purpose,
                                              const SortedSizesPx& sizes_px) {
     std::map<SquareSizePx, SkBitmap> result;
@@ -71,12 +71,12 @@
 #endif
 
   base::RunLoop loop;
-  AppId result_app_id;
+  webapps::AppId result_app_id;
   provider().scheduler().InstallFromInfo(
       std::move(info),
       /*overwrite_existing_manifest_fields=*/false, install_source,
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             result_app_id = app_id;
             loop.Quit();
@@ -109,13 +109,13 @@
   install_params.add_to_desktop = true;
 
   base::RunLoop loop;
-  AppId result_app_id;
+  webapps::AppId result_app_id;
   provider().scheduler().InstallFromInfoWithParams(
       std::move(info),
       /*overwrite_existing_manifest_fields=*/false,
       webapps::WebappInstallSource::MENU_BROWSER_TAB,
       base::BindLambdaForTesting(
-          [&](const AppId& app_id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& app_id, webapps::InstallResultCode code) {
             EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
             EXPECT_TRUE(
                 provider().registrar_unsafe().IsActivelyInstalled(app_id));
@@ -148,7 +148,7 @@
   os_integration_manager()->SetShortcutManager(std::move(shortcut_manager));
 
   GURL old_app_url("http://old-app.com");
-  const AppId old_app =
+  const webapps::AppId old_app =
       test::InstallDummyWebApp(profile(), "old_app", old_app_url);
   auto shortcut_info = std::make_unique<ShortcutInfo>();
   shortcut_info->url = old_app_url;
@@ -171,12 +171,12 @@
   install_params.add_to_desktop = true;
 
   base::RunLoop loop;
-  AppId result_app_id;
+  webapps::AppId result_app_id;
   provider().scheduler().InstallFromInfoWithParams(
       std::move(info),
       /*overwrite_existing_manifest_fields=*/false,
       webapps::WebappInstallSource::MENU_BROWSER_TAB,
-      base::BindLambdaForTesting([&](const AppId& app_id,
+      base::BindLambdaForTesting([&](const webapps::AppId& app_id,
                                      webapps::InstallResultCode code,
                                      bool did_uninstall_and_replace) {
         EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command.cc b/chrome/browser/web_applications/commands/install_from_sync_command.cc
index fe5be60..10a3c31 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command.cc
@@ -56,8 +56,8 @@
 InstallFromSyncCommand::Params::~Params() = default;
 
 InstallFromSyncCommand::Params::Params(
-    const AppId& app_id,
-    const ManifestId& manifest_id,
+    const webapps::AppId& app_id,
+    const webapps::ManifestId& manifest_id,
     const GURL& start_url,
     const std::string& title,
     const GURL& scope,
@@ -87,7 +87,7 @@
           "InstallFromSyncCommand"),
       lock_description_(
           std::make_unique<SharedWebContentsWithAppLockDescription,
-                           base::flat_set<AppId>>({params.app_id})),
+                           base::flat_set<webapps::AppId>>({params.app_id})),
       profile_(profile),
       params_(params),
       install_callback_(std::move(install_callback)),
@@ -223,7 +223,7 @@
   }
 
   // Ensure that the manifest linked is the right one.
-  AppId generated_app_id =
+  webapps::AppId generated_app_id =
       GenerateAppIdFromManifestId(install_info_->manifest_id);
   if (params_.app_id != generated_app_id) {
     // Add the error to the log.
@@ -280,7 +280,7 @@
 }
 
 void InstallFromSyncCommand::OnInstallFinalized(FinalizeMode mode,
-                                                const AppId& app_id,
+                                                const webapps::AppId& app_id,
                                                 webapps::InstallResultCode code,
                                                 OsHooksErrors os_hooks_errors) {
   if (mode == FinalizeMode::kNormalWebAppInfo && !IsSuccess(code)) {
@@ -319,7 +319,7 @@
 }
 
 void InstallFromSyncCommand::ReportResultAndDestroy(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code) {
   bool success = IsSuccess(code);
   debug_value_.Set("result_code", base::ToString(code));
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command.h b/chrome/browser/web_applications/commands/install_from_sync_command.h
index 7c4a8c7..88172e4 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command.h
+++ b/chrome/browser/web_applications/commands/install_from_sync_command.h
@@ -43,16 +43,16 @@
     Params() = delete;
     ~Params();
     Params(const Params&);
-    Params(const AppId& app_id,
-           const ManifestId& manifest_id,
+    Params(const webapps::AppId& app_id,
+           const webapps::ManifestId& manifest_id,
            const GURL& start_url,
            const std::string& title,
            const GURL& scope,
            const absl::optional<SkColor>& theme_color,
            const absl::optional<mojom::UserDisplayMode>& user_display_mode,
            const std::vector<apps::IconInfo>& icons);
-    const AppId app_id;
-    const ManifestId manifest_id;
+    const webapps::AppId app_id;
+    const webapps::ManifestId manifest_id;
     const GURL start_url;
     const std::string title;
     const GURL scope;
@@ -97,13 +97,13 @@
       DownloadedIconsHttpResults icons_http_results);
 
   void OnInstallFinalized(FinalizeMode mode,
-                          const AppId& app_id,
+                          const webapps::AppId& app_id,
                           webapps::InstallResultCode code,
                           OsHooksErrors os_hooks_errors);
 
   void InstallFallback(webapps::InstallResultCode error_code);
 
-  void ReportResultAndDestroy(const AppId& app_id,
+  void ReportResultAndDestroy(const webapps::AppId& app_id,
                               webapps::InstallResultCode code);
 
   std::unique_ptr<SharedWebContentsWithAppLockDescription> lock_description_;
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc b/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
index aadde63..8e45863 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command_browsertest.cc
@@ -33,7 +33,7 @@
   GURL test_url = https_server()->GetURL(
       "/banners/"
       "manifest_test_page.html");
-  AppId id = GenerateAppId(absl::nullopt, test_url);
+  webapps::AppId id = GenerateAppId(absl::nullopt, test_url);
 
   auto* provider = WebAppProvider::GetForTest(profile());
   base::RunLoop loop;
@@ -47,12 +47,12 @@
   provider->command_manager().ScheduleCommand(
       std::make_unique<InstallFromSyncCommand>(
           profile(), params,
-          base::BindLambdaForTesting(
-              [&](const AppId& app_id, webapps::InstallResultCode code) {
-                EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
-                EXPECT_EQ(app_id, id);
-                loop.Quit();
-              })));
+          base::BindLambdaForTesting([&](const webapps::AppId& app_id,
+                                         webapps::InstallResultCode code) {
+            EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
+            EXPECT_EQ(app_id, id);
+            loop.Quit();
+          })));
   loop.Run();
   EXPECT_TRUE(provider->registrar_unsafe().IsInstalled(id));
   EXPECT_EQ(AreAppsLocallyInstalledBySync(),
@@ -67,11 +67,11 @@
   GURL test_url = https_server()->GetURL(
       "/banners/"
       "manifest_test_page.html");
-  AppId id = GenerateAppId(absl::nullopt, test_url);
+  webapps::AppId id = GenerateAppId(absl::nullopt, test_url);
   GURL other_test_url = https_server()->GetURL(
       "/banners/"
       "manifest_no_service_worker.html");
-  AppId other_id = GenerateAppId(absl::nullopt, test_url);
+  webapps::AppId other_id = GenerateAppId(absl::nullopt, test_url);
 
   auto* provider = WebAppProvider::GetForTest(profile());
   base::RunLoop loop;
@@ -86,7 +86,7 @@
     provider->command_manager().ScheduleCommand(
         std::make_unique<InstallFromSyncCommand>(
             profile(), params,
-            base::BindLambdaForTesting([&](const AppId& app_id,
+            base::BindLambdaForTesting([&](const webapps::AppId& app_id,
                                            webapps::InstallResultCode code) {
               EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
               EXPECT_EQ(app_id, id);
@@ -103,7 +103,7 @@
     provider->command_manager().ScheduleCommand(
         std::make_unique<InstallFromSyncCommand>(
             profile(), params,
-            base::BindLambdaForTesting([&](const AppId& app_id,
+            base::BindLambdaForTesting([&](const webapps::AppId& app_id,
                                            webapps::InstallResultCode code) {
               EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
               EXPECT_EQ(app_id, other_id);
diff --git a/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc b/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
index 3a9d862..a4d8961 100644
--- a/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/install_from_sync_command_unittest.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -35,6 +34,7 @@
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_logging.h"
 #include "components/webapps/browser/installable/installable_manager.h"
+#include "components/webapps/common/web_app_id.h"
 #include "components/webapps/common/web_page_metadata.mojom-forward.h"
 #include "components/webapps/common/web_page_metadata.mojom.h"
 #include "content/public/browser/web_contents_user_data.h"
@@ -71,12 +71,12 @@
  public:
   const int kIconSize = 96;
   const GURL kWebAppStartUrl = GURL("https://example.com/path/index.html");
-  const ManifestId kWebAppManifestId =
+  const webapps::ManifestId kWebAppManifestId =
       GURL("https://example.com/path/index.html");
 
   const GURL kOtherWebAppStartUrl =
       GURL("https://example.com/path2/index.html");
-  const ManifestId kOtherWebAppManifestId =
+  const webapps::ManifestId kOtherWebAppManifestId =
       GURL("https://example.com/path2/index.html");
 
   const std::u16string kManifestName = u"Manifest Name";
@@ -112,13 +112,13 @@
  protected:
   struct InstallResult {
     bool callback_triggered = false;
-    AppId installed_app_id;
+    webapps::AppId installed_app_id;
     webapps::InstallResultCode install_code;
     absl::optional<webapps::InstallResultCode> install_code_before_fallback;
   };
 
-  InstallFromSyncCommand::Params CreateParams(AppId app_id,
-                                              ManifestId manifest_id,
+  InstallFromSyncCommand::Params CreateParams(webapps::AppId app_id,
+                                              webapps::ManifestId manifest_id,
                                               GURL start_url) {
     return InstallFromSyncCommand::Params(
         app_id, manifest_id, start_url, kFallbackTitle,
@@ -127,10 +127,12 @@
         {apps::IconInfo(kFallbackIconUrl, kIconSize)});
   }
 
-  InstallResult InstallFromSyncAndWait(GURL start_url, ManifestId manifest_id) {
-    const AppId app_id = GenerateAppIdFromManifestId(manifest_id);
+  InstallResult InstallFromSyncAndWait(GURL start_url,
+                                       webapps::ManifestId manifest_id) {
+    const webapps::AppId app_id = GenerateAppIdFromManifestId(manifest_id);
     InstallResult result;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> future;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        future;
     std::unique_ptr<InstallFromSyncCommand> command =
         std::make_unique<InstallFromSyncCommand>(
             profile(), CreateParams(app_id, manifest_id, start_url),
@@ -144,7 +146,7 @@
     if (!result.callback_triggered) {
       return result;
     }
-    result.installed_app_id = future.Get<AppId>();
+    result.installed_app_id = future.Get<webapps::AppId>();
     result.install_code = future.Get<webapps::InstallResultCode>();
     return result;
   }
@@ -163,7 +165,7 @@
   }
 
   blink::mojom::ManifestPtr CreateManifest(GURL start_url,
-                                           ManifestId manifest_id,
+                                           webapps::ManifestId manifest_id,
                                            bool icons) {
     blink::mojom::ManifestPtr manifest = blink::mojom::Manifest::New();
     manifest->name = kManifestName;
@@ -181,13 +183,13 @@
     return manifest;
   }
 
-  std::u16string GetAppName(const AppId& app_id) {
+  std::u16string GetAppName(const webapps::AppId& app_id) {
     return base::UTF8ToUTF16(registrar().GetAppShortName(app_id));
   }
 };
 
 TEST_F(InstallFromSyncTest, SuccessWithManifest) {
-  const AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
 
   // Page with manifest.
   auto& fake_page_state =
@@ -223,7 +225,7 @@
 }
 
 TEST_F(InstallFromSyncTest, SuccessWithoutManifest) {
-  const AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
 
   // Page without manifest.
   auto& fake_page_state =
@@ -257,7 +259,7 @@
 }
 
 TEST_F(InstallFromSyncTest, SuccessManifestNoIcons) {
-  const AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
 
   // Page with manifest, no icons.
   auto& fake_page_state =
@@ -293,7 +295,7 @@
 }
 
 TEST_F(InstallFromSyncTest, UrlRedirectUseFallback) {
-  const AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
 
   // Page redirects.
   auto& fake_page_state =
@@ -327,7 +329,7 @@
 }
 
 TEST_F(InstallFromSyncTest, FallbackWebAppInstallInfo) {
-  const AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
 
   // Page redirects.
   auto& fake_page_state =
@@ -362,7 +364,7 @@
 }
 
 TEST_F(InstallFromSyncTest, FallbackManifestIdMismatch) {
-  const AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
 
   // Page with manifest.
   auto& fake_page_state =
@@ -402,8 +404,9 @@
 }
 
 TEST_F(InstallFromSyncTest, TwoInstalls) {
-  const AppId app_id1 = GenerateAppIdFromManifestId(kWebAppManifestId);
-  const AppId app_id2 = GenerateAppIdFromManifestId(kOtherWebAppManifestId);
+  const webapps::AppId app_id1 = GenerateAppIdFromManifestId(kWebAppManifestId);
+  const webapps::AppId app_id2 =
+      GenerateAppIdFromManifestId(kOtherWebAppManifestId);
 
   // No need to set up our FakeWebContentsManager state, as the sync
   // installation will succeed even if the network is down.
@@ -423,7 +426,7 @@
   std::vector<webapps::InstallResultCode> codes;
   WebAppInstallManagerObserverAdapter observer(&provider()->install_manager());
   observer.SetWebAppInstalledDelegate(
-      base::BindLambdaForTesting([&](const AppId& app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& app_id) {
         if (app_id == app_id1) {
           events.push_back(Event::kNotifyApp1Installed);
         } else {
@@ -432,7 +435,7 @@
         }
       }));
   observer.SetWebAppInstalledWithOsHooksDelegate(
-      base::BindLambdaForTesting([&](const AppId& app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& app_id) {
         if (app_id == app_id1) {
           events.push_back(Event::kNotifyApp1InstalledWithHooks);
         } else {
@@ -445,7 +448,7 @@
       std::make_unique<InstallFromSyncCommand>(
           profile(), CreateParams(app_id1, kWebAppManifestId, kWebAppStartUrl),
           base::BindLambdaForTesting(
-              [&](const AppId& id, webapps::InstallResultCode code) {
+              [&](const webapps::AppId& id, webapps::InstallResultCode code) {
                 events.push_back(Event::kApp1Installed);
                 codes.push_back(code);
                 loop1.Quit();
@@ -455,7 +458,7 @@
       profile(),
       CreateParams(app_id2, kOtherWebAppManifestId, kOtherWebAppStartUrl),
       base::BindLambdaForTesting(
-          [&](const AppId& id, webapps::InstallResultCode code) {
+          [&](const webapps::AppId& id, webapps::InstallResultCode code) {
             events.push_back(Event::kApp2Installed);
             codes.push_back(code);
             loop2.Quit();
@@ -492,7 +495,7 @@
 }
 
 TEST_F(InstallFromSyncTest, Shutdown) {
-  const AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(kWebAppManifestId);
 
   // Page with manifest, but have the manifest fetch cause the system to shut
   // down.
@@ -507,7 +510,8 @@
   fake_page_state.on_manifest_fetch =
       base::BindLambdaForTesting([&]() { command_manager().Shutdown(); });
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> future;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      future;
   std::unique_ptr<InstallFromSyncCommand> command =
       std::make_unique<InstallFromSyncCommand>(
           profile(), CreateParams(app_id, kWebAppManifestId, kWebAppStartUrl),
diff --git a/chrome/browser/web_applications/commands/install_placeholder_command.cc b/chrome/browser/web_applications/commands/install_placeholder_command.cc
index 1c427ae..50f5978 100644
--- a/chrome/browser/web_applications/commands/install_placeholder_command.cc
+++ b/chrome/browser/web_applications/commands/install_placeholder_command.cc
@@ -31,7 +31,7 @@
           GenerateManifestIdFromStartUrlOnly(install_options.install_url))),
       lock_description_(
           std::make_unique<SharedWebContentsWithAppLockDescription>(
-              base::flat_set<AppId>{app_id_})),
+              base::flat_set<webapps::AppId>{app_id_})),
       install_options_(install_options),
       callback_(std::move(callback)) {}
 
@@ -96,7 +96,7 @@
 
 void InstallPlaceholderCommand::OnPlaceholderInstalled(
     webapps::InstallResultCode code,
-    AppId app_id) {
+    webapps::AppId app_id) {
   webapps::InstallableMetrics::TrackInstallResult(webapps::IsSuccess(code));
 
   if (!callback_) {
diff --git a/chrome/browser/web_applications/commands/install_placeholder_command.h b/chrome/browser/web_applications/commands/install_placeholder_command.h
index 01274da..54040b2 100644
--- a/chrome/browser/web_applications/commands/install_placeholder_command.h
+++ b/chrome/browser/web_applications/commands/install_placeholder_command.h
@@ -54,12 +54,13 @@
 
  private:
   void Abort(webapps::InstallResultCode code);
-  void OnPlaceholderInstalled(webapps::InstallResultCode code, AppId app_id);
+  void OnPlaceholderInstalled(webapps::InstallResultCode code,
+                              webapps::AppId app_id);
   void OnUninstallAndReplaced(webapps::InstallResultCode code,
                               bool did_uninstall_and_replace);
 
   const raw_ptr<Profile> profile_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   std::unique_ptr<SharedWebContentsWithAppLockDescription> lock_description_;
   std::unique_ptr<SharedWebContentsWithAppLock> lock_;
 
diff --git a/chrome/browser/web_applications/commands/install_placeholder_command_unittest.cc b/chrome/browser/web_applications/commands/install_placeholder_command_unittest.cc
index a181b4e..1df4122 100644
--- a/chrome/browser/web_applications/commands/install_placeholder_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/install_placeholder_command_unittest.cc
@@ -20,10 +20,10 @@
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "net/http/http_status_code.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -77,7 +77,7 @@
 
   ExternallyManagedAppManager::InstallResult result = future.Take();
   EXPECT_EQ(result.code, webapps::InstallResultCode::kSuccessNewInstall);
-  const AppId app_id = *result.app_id;
+  const webapps::AppId app_id = *result.app_id;
   EXPECT_TRUE(provider()->registrar_unsafe().IsPlaceholderApp(
       app_id, WebAppManagement::kPolicy));
   EXPECT_EQ(fake_os_integration_manager().num_create_shortcuts_calls(), 1u);
@@ -129,7 +129,7 @@
 
   ExternallyManagedAppManager::InstallResult result = future.Take();
   EXPECT_EQ(result.code, webapps::InstallResultCode::kSuccessNewInstall);
-  const AppId app_id = *result.app_id;
+  const webapps::AppId app_id = *result.app_id;
   EXPECT_TRUE(provider()->registrar_unsafe().IsPlaceholderApp(
       app_id, WebAppManagement::kPolicy));
   EXPECT_EQ(fake_os_integration_manager().num_create_shortcuts_calls(), 1u);
@@ -145,7 +145,7 @@
 TEST_F(InstallPlaceholderCommandTest,
        InstallPlaceholderWithUninstallAndReplace) {
   GURL old_app_url("http://old-app.com");
-  const AppId old_app =
+  const webapps::AppId old_app =
       test::InstallDummyWebApp(profile(), "old_app", old_app_url);
   auto shortcut_info = std::make_unique<ShortcutInfo>();
   shortcut_info->url = old_app_url;
@@ -166,7 +166,7 @@
   ExternallyManagedAppManager::InstallResult result = future.Take();
   EXPECT_EQ(result.code, webapps::InstallResultCode::kSuccessNewInstall);
   EXPECT_TRUE(result.did_uninstall_and_replace);
-  const AppId app_id = *result.app_id;
+  const webapps::AppId app_id = *result.app_id;
   EXPECT_TRUE(provider()->registrar_unsafe().IsPlaceholderApp(
       app_id, WebAppManagement::kPolicy));
 
diff --git a/chrome/browser/web_applications/commands/install_placeholder_job_unittest.cc b/chrome/browser/web_applications/commands/install_placeholder_job_unittest.cc
index c31d1c5..f0576aa 100644
--- a/chrome/browser/web_applications/commands/install_placeholder_job_unittest.cc
+++ b/chrome/browser/web_applications/commands/install_placeholder_job_unittest.cc
@@ -26,11 +26,11 @@
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "net/http/http_status_code.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -54,7 +54,7 @@
         data_retriever_(std::move(data_retriever)),
         lock_description_(
             std::make_unique<SharedWebContentsWithAppLockDescription>(
-                base::flat_set<AppId>{
+                base::flat_set<webapps::AppId>{
                     GenerateAppId(/*manifest_id_path=*/absl::nullopt,
                                   install_options.install_url)})) {}
 
@@ -76,7 +76,8 @@
     install_placeholder_job_->Start();
   }
 
-  void OnPlaceholderInstalled(webapps::InstallResultCode code, AppId app_id) {
+  void OnPlaceholderInstalled(webapps::InstallResultCode code,
+                              webapps::AppId app_id) {
     SignalCompletionAndSelfDestruct(
         webapps::IsSuccess(code) ? CommandResult::kSuccess
                                  : CommandResult::kFailure,
@@ -143,14 +144,14 @@
 TEST_F(InstallPlaceholderJobTest, InstallPlaceholder) {
   ExternalInstallOptions options(kInstallUrl, mojom::UserDisplayMode::kBrowser,
                                  ExternalInstallSource::kExternalPolicy);
-  base::test::TestFuture<webapps::InstallResultCode, AppId> future;
+  base::test::TestFuture<webapps::InstallResultCode, webapps::AppId> future;
 
   provider()->command_manager().ScheduleCommand(
       std::make_unique<InstallPlaceholderJobWrapperCommand>(
           profile(), options, future.GetCallback()));
 
   EXPECT_EQ(future.Get<0>(), webapps::InstallResultCode::kSuccessNewInstall);
-  const AppId app_id = future.Get<1>();
+  const webapps::AppId app_id = future.Get<1>();
   EXPECT_TRUE(provider()->registrar_unsafe().IsPlaceholderApp(
       app_id, WebAppManagement::kPolicy));
   EXPECT_EQ(fake_os_integration_manager().num_create_shortcuts_calls(), 1u);
@@ -174,7 +175,7 @@
                                  ExternalInstallSource::kExternalPolicy);
   const GURL icon_url("https://example.com/test.png");
   options.override_icon_url = icon_url;
-  base::test::TestFuture<webapps::InstallResultCode, AppId> future;
+  base::test::TestFuture<webapps::InstallResultCode, webapps::AppId> future;
 
   auto data_retriever =
       std::make_unique<testing::StrictMock<MockDataRetriever>>();
@@ -200,7 +201,7 @@
   provider()->command_manager().ScheduleCommand(std::move(command));
 
   EXPECT_EQ(future.Get<0>(), webapps::InstallResultCode::kSuccessNewInstall);
-  const AppId app_id = future.Get<1>();
+  const webapps::AppId app_id = future.Get<1>();
   EXPECT_TRUE(provider()->registrar_unsafe().IsPlaceholderApp(
       app_id, WebAppManagement::kPolicy));
   EXPECT_EQ(fake_os_integration_manager().num_create_shortcuts_calls(), 1u);
diff --git a/chrome/browser/web_applications/commands/install_preloaded_verified_app_command.cc b/chrome/browser/web_applications/commands/install_preloaded_verified_app_command.cc
index c720cd2..eed025f73 100644
--- a/chrome/browser/web_applications/commands/install_preloaded_verified_app_command.cc
+++ b/chrome/browser/web_applications/commands/install_preloaded_verified_app_command.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
@@ -28,6 +27,7 @@
 #include "chrome/browser/web_applications/web_contents/web_contents_manager.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/url_util.h"
@@ -67,7 +67,7 @@
     GURL document_url,
     GURL manifest_url,
     std::string manifest_contents,
-    AppId expected_id,
+    webapps::AppId expected_id,
     OnceInstallCallback callback)
     : WebAppCommandTemplate<SharedWebContentsLock>(
           "InstallPreloadedVerifiedAppCommand"),
@@ -208,7 +208,8 @@
 
   PopulateOtherIcons(web_app_info_.get(), icons_map);
 
-  AppId app_id = GenerateAppIdFromManifestId(web_app_info_->manifest_id);
+  webapps::AppId app_id =
+      GenerateAppIdFromManifestId(web_app_info_->manifest_id);
 
   if (app_id != expected_id_) {
     Abort(CommandResult::kFailure,
@@ -240,7 +241,7 @@
 }
 
 void InstallPreloadedVerifiedAppCommand::OnInstallFinalized(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code,
     OsHooksErrors os_hooks_errors) {
   SignalCompletionAndSelfDestruct(
@@ -254,7 +255,8 @@
     webapps::InstallResultCode code) {
   debug_value_.Set("error_code", base::ToString(code));
   SignalCompletionAndSelfDestruct(
-      result, base::BindOnce(std::move(install_callback_), AppId(), code));
+      result,
+      base::BindOnce(std::move(install_callback_), webapps::AppId(), code));
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/commands/install_preloaded_verified_app_command.h b/chrome/browser/web_applications/commands/install_preloaded_verified_app_command.h
index 72a28df9..7054b64 100644
--- a/chrome/browser/web_applications/commands/install_preloaded_verified_app_command.h
+++ b/chrome/browser/web_applications/commands/install_preloaded_verified_app_command.h
@@ -64,7 +64,7 @@
       GURL document_url,
       GURL manifest_url,
       std::string manifest_contents,
-      AppId expected_id,
+      webapps::AppId expected_id,
       OnceInstallCallback callback);
 
   ~InstallPreloadedVerifiedAppCommand() override;
@@ -83,7 +83,7 @@
                         DownloadedIconsHttpResults icons_http_results);
   void OnAppLockAcquired(
       std::unique_ptr<SharedWebContentsWithAppLock> app_lock);
-  void OnInstallFinalized(const AppId& app_id,
+  void OnInstallFinalized(const webapps::AppId& app_id,
                           webapps::InstallResultCode code,
                           OsHooksErrors os_hooks_errors);
 
@@ -93,7 +93,7 @@
   GURL document_url_;
   GURL manifest_url_;
   std::string manifest_contents_;
-  AppId expected_id_;
+  webapps::AppId expected_id_;
   OnceInstallCallback install_callback_;
 
   // SharedWebContentsLock is held while parsing the manifest.
diff --git a/chrome/browser/web_applications/commands/install_preloaded_verified_app_command_browsertest.cc b/chrome/browser/web_applications/commands/install_preloaded_verified_app_command_browsertest.cc
index 4ff4deaf..c9e84be 100644
--- a/chrome/browser/web_applications/commands/install_preloaded_verified_app_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/install_preloaded_verified_app_command_browsertest.cc
@@ -18,11 +18,11 @@
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "net/dns/mock_host_resolver.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -57,7 +57,8 @@
     WebAppControllerBrowserTest::TearDownOnMainThread();
   }
 
-  bool IsShortcutCreated(const AppId& app_id, const std::string& name) {
+  bool IsShortcutCreated(const webapps::AppId& app_id,
+                         const std::string& name) {
 #if BUILDFLAG(IS_CHROMEOS)
     // Shortcuts are always created (through App Service) on ChromeOS.
     return true;
@@ -98,14 +99,16 @@
   std::string manifest = base::ReplaceStringPlaceholders(
       kManifestTemplate, {GetIconUrl()}, nullptr);
 
-  AppId expected_id = GenerateAppId(/*manifest_id=*/absl::nullopt, kStartUrl);
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  webapps::AppId expected_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, kStartUrl);
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
           kManifestUrl, manifest, expected_id, result.GetCallback()));
 
-  AppId result_id = result.Get<0>();
+  webapps::AppId result_id = result.Get<0>();
   EXPECT_EQ(result_id, expected_id);
   EXPECT_TRUE(webapps::IsSuccess(result.Get<1>()));
 
@@ -141,16 +144,17 @@
   std::string manifest = base::ReplaceStringPlaceholders(
       kManifestTemplate, {GetIconUrl()}, nullptr);
 
-  AppId expected_id =
+  webapps::AppId expected_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, kDocumentUrl);
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
           kManifestUrl, manifest, expected_id, result.GetCallback()));
 
-  AppId result_id = result.Get<0>();
+  webapps::AppId result_id = result.Get<0>();
   EXPECT_EQ(result_id, expected_id);
   EXPECT_TRUE(webapps::IsSuccess(result.Get<1>()));
   EXPECT_TRUE(IsShortcutCreated(result_id, "Test app"));
@@ -174,14 +178,15 @@
   std::string manifest = base::ReplaceStringPlaceholders(
       kManifestTemplate, {GetIconUrl()}, nullptr);
 
-  AppId expected_id = GenerateAppId("appid", kDocumentUrl);
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  webapps::AppId expected_id = GenerateAppId("appid", kDocumentUrl);
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
           kManifestUrl, manifest, expected_id, result.GetCallback()));
 
-  AppId result_id = result.Get<0>();
+  webapps::AppId result_id = result.Get<0>();
   EXPECT_EQ(result_id, expected_id);
   EXPECT_TRUE(webapps::IsSuccess(result.Get<1>()));
   EXPECT_TRUE(IsShortcutCreated(result_id, "Test app"));
@@ -206,16 +211,17 @@
   std::string manifest = base::ReplaceStringPlaceholders(
       kManifestTemplate, {GetIconUrl()}, nullptr);
 
-  AppId existing_id =
+  webapps::AppId existing_id =
       test::InstallDummyWebApp(profile(), "User installed app", kDocumentUrl);
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::INTERNAL_DEFAULT, kDocumentUrl,
           kManifestUrl, manifest, existing_id, result.GetCallback()));
 
-  AppId result_id = result.Get<0>();
+  webapps::AppId result_id = result.Get<0>();
   EXPECT_EQ(result_id, existing_id);
   EXPECT_TRUE(webapps::IsSuccess(result.Get<1>()));
 
@@ -267,16 +273,17 @@
 
       },
       nullptr);
-  AppId expected_id =
+  webapps::AppId expected_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, kDocumentUrl);
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::INTERNAL_DEFAULT, kDocumentUrl,
           kManifestUrl, manifest, expected_id, result.GetCallback()));
 
-  AppId result_id = result.Get<0>();
+  webapps::AppId result_id = result.Get<0>();
   EXPECT_TRUE(webapps::IsSuccess(result.Get<1>()));
 
   SkColor small_icon_color =
@@ -302,7 +309,8 @@
   const GURL kManifestUrl("https://www.app.com/manifest.json");
   const char kManifest[] = "notjson";
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
@@ -322,7 +330,8 @@
     "name": "Test app 2"
   })json";
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
@@ -342,7 +351,8 @@
     "start_url": "/"
   })json";
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
@@ -369,7 +379,8 @@
     }]
   })json";
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
@@ -386,7 +397,7 @@
   // manifest.
   const GURL kDocumentUrl("https://www.app.com/");
   const GURL kManifestUrl("https://www.app.com/manifest.json");
-  const AppId kExpectedId = GenerateAppId("/two", kDocumentUrl);
+  const webapps::AppId kExpectedId = GenerateAppId("/two", kDocumentUrl);
   const char kManifestTemplate[] = R"json({
     "start_url": "/",
     "id": "/one",
@@ -400,7 +411,8 @@
   std::string manifest = base::ReplaceStringPlaceholders(
       kManifestTemplate, {GetIconUrl()}, nullptr);
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
@@ -415,7 +427,7 @@
   // Installation will fail because there are no icons that match the allowlist.
   const GURL kDocumentUrl("https://www.app.com/");
   const GURL kManifestUrl("https://www.app.com/manifest.json");
-  const AppId kExpectedId = GenerateAppId("/two", kDocumentUrl);
+  const webapps::AppId kExpectedId = GenerateAppId("/two", kDocumentUrl);
   const char kManifestTemplate[] = R"json({
     "start_url": "/",
     "name": "Test app",
@@ -440,7 +452,8 @@
   std::string manifest = base::ReplaceStringPlaceholders(
       kManifestTemplate, {GetIconUrl()}, nullptr);
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
@@ -455,7 +468,7 @@
   // Installation will fail because all icons error when downloaded.
   const GURL kDocumentUrl("https://www.app.com/");
   const GURL kManifestUrl("https://www.app.com/manifest.json");
-  const AppId kExpectedId = GenerateAppId("/two", kDocumentUrl);
+  const webapps::AppId kExpectedId = GenerateAppId("/two", kDocumentUrl);
   const char kManifestTemplate[] = R"json({
     "start_url": "/",
     "id": "/one",
@@ -479,7 +492,8 @@
        https_server()->GetURL("/nocontent").spec()},
       nullptr);
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
@@ -531,16 +545,17 @@
            .spec(),
        https_server()->GetURL("youtube.com", "/web_apps/blue-192.png").spec()},
       nullptr);
-  AppId expected_id =
+  webapps::AppId expected_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, kDocumentUrl);
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::INTERNAL_DEFAULT, kDocumentUrl,
           kManifestUrl, manifest, expected_id, result.GetCallback()));
 
-  AppId result_id = result.Get<0>();
+  webapps::AppId result_id = result.Get<0>();
   EXPECT_TRUE(webapps::IsSuccess(result.Get<1>()));
 
   SkColor small_icon_color =
@@ -591,8 +606,10 @@
        "https://evilgoogleusercontent.com/icons/192.png"},
       nullptr);
 
-  AppId expected_id = GenerateAppId(/*manifest_id=*/absl::nullopt, kStartUrl);
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  webapps::AppId expected_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, kStartUrl);
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
@@ -614,8 +631,10 @@
     }
   })json";
 
-  AppId expected_id = GenerateAppId(/*manifest_id=*/absl::nullopt, kStartUrl);
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  webapps::AppId expected_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, kStartUrl);
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      result;
   provider().command_manager().ScheduleCommand(
       std::make_unique<InstallPreloadedVerifiedAppCommand>(
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, kDocumentUrl,
diff --git a/chrome/browser/web_applications/commands/manifest_update_check_command.cc b/chrome/browser/web_applications/commands/manifest_update_check_command.cc
index 5974e32..d7bd33f 100644
--- a/chrome/browser/web_applications/commands/manifest_update_check_command.cc
+++ b/chrome/browser/web_applications/commands/manifest_update_check_command.cc
@@ -27,7 +27,7 @@
 
 ManifestUpdateCheckCommand::ManifestUpdateCheckCommand(
     const GURL& url,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::Time check_time,
     base::WeakPtr<content::WebContents> web_contents,
     CompletedCallback callback,
diff --git a/chrome/browser/web_applications/commands/manifest_update_check_command.h b/chrome/browser/web_applications/commands/manifest_update_check_command.h
index f67bbc2..510ca23 100644
--- a/chrome/browser/web_applications/commands/manifest_update_check_command.h
+++ b/chrome/browser/web_applications/commands/manifest_update_check_command.h
@@ -21,6 +21,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h"
 #include "chrome/browser/web_applications/web_contents/web_app_icon_downloader.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -58,7 +59,7 @@
 
   ManifestUpdateCheckCommand(
       const GURL& url,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::Time check_time,
       base::WeakPtr<content::WebContents> web_contents,
       CompletedCallback callback,
@@ -144,7 +145,7 @@
 
   // Manifest update check request parameters.
   const GURL url_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   base::Time check_time_;
   CompletedCallback completed_callback_;
 
diff --git a/chrome/browser/web_applications/commands/manifest_update_check_command_unittest.cc b/chrome/browser/web_applications/commands/manifest_update_check_command_unittest.cc
index 872300fa..9ce463f8 100644
--- a/chrome/browser/web_applications/commands/manifest_update_check_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/manifest_update_check_command_unittest.cc
@@ -359,7 +359,8 @@
     absl::optional<WebAppInstallInfo> new_install_info;
   };
 
-  RunResult RunCommandAndGetResult(const GURL& url, const AppId& app_id) {
+  RunResult RunCommandAndGetResult(const GURL& url,
+                                   const webapps::AppId& app_id) {
     base::test::TestFuture<ManifestUpdateCheckResult,
                            absl::optional<WebAppInstallInfo>>
         manifest_update_check_future;
@@ -375,7 +376,7 @@
     return output_result;
   }
 
-  AppId InstallAppFromInfo(std::unique_ptr<WebAppInstallInfo> info) {
+  webapps::AppId InstallAppFromInfo(std::unique_ptr<WebAppInstallInfo> info) {
     return test::InstallWebApp(profile(), std::move(info));
   }
 
@@ -422,7 +423,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   // Verify name changes are properly propagated.
   WebAppInstallInfo new_info;
@@ -444,7 +445,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   // Verify scope changes are properly propagated.
   WebAppInstallInfo new_info;
@@ -467,7 +468,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   // Verify display mode changes are properly propagated.
   WebAppInstallInfo new_info;
@@ -490,7 +491,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   // Verify display mode changes are properly propagated.
   WebAppInstallInfo new_info;
@@ -516,7 +517,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   // No fields are changed, so no updates should be needed.
   WebAppInstallInfo new_info;
@@ -537,7 +538,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   WebAppInstallInfo new_info;
   new_info.start_url = app_url();
@@ -558,7 +559,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   // start_url changing should not move ahead with a manifest update as the
   // generated app_id is different.
@@ -581,7 +582,7 @@
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->theme_color = SK_ColorRED;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(
+  webapps::AppId app_id = InstallAppFromInfo(
       std::make_unique<WebAppInstallInfo>(install_info->Clone()));
 
   WebAppInstallInfo new_info = install_info->Clone();
@@ -606,7 +607,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   WebAppInstallInfo new_info;
   new_info.start_url = app_url();
@@ -636,7 +637,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   WebAppInstallInfo new_info;
   new_info.start_url = app_url();
@@ -657,7 +658,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   WebAppInstallInfo new_info;
   new_info.start_url = app_url();
@@ -700,7 +701,7 @@
   install_info->scope = app_url().GetWithoutFilename();
   install_info->display_mode = DisplayMode::kStandalone;
   install_info->title = u"Foo App";
-  AppId app_id = InstallAppFromInfo(std::move(install_info));
+  webapps::AppId app_id = InstallAppFromInfo(std::move(install_info));
 
   WebAppInstallInfo new_info;
   new_info.start_url = app_url();
diff --git a/chrome/browser/web_applications/commands/manifest_update_finalize_command.cc b/chrome/browser/web_applications/commands/manifest_update_finalize_command.cc
index 9584c6c..b5815e1 100644
--- a/chrome/browser/web_applications/commands/manifest_update_finalize_command.cc
+++ b/chrome/browser/web_applications/commands/manifest_update_finalize_command.cc
@@ -15,19 +15,19 @@
 #include "chrome/browser/web_applications/locks/app_lock.h"
 #include "chrome/browser/web_applications/manifest_update_utils.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
 ManifestUpdateFinalizeCommand::ManifestUpdateFinalizeCommand(
     const GURL& url,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     WebAppInstallInfo install_info,
     ManifestWriteCallback write_callback,
     std::unique_ptr<ScopedKeepAlive> keep_alive,
@@ -82,7 +82,7 @@
 }
 
 void ManifestUpdateFinalizeCommand::OnInstallationComplete(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode code,
     OsHooksErrors os_hooks_errors) {
   if (!IsSuccess(code)) {
diff --git a/chrome/browser/web_applications/commands/manifest_update_finalize_command.h b/chrome/browser/web_applications/commands/manifest_update_finalize_command.h
index fdee37d..71f2a11d 100644
--- a/chrome/browser/web_applications/commands/manifest_update_finalize_command.h
+++ b/chrome/browser/web_applications/commands/manifest_update_finalize_command.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace webapps {
 enum class InstallResultCode;
@@ -31,12 +32,14 @@
 // steps of writing the data to the DB.
 class ManifestUpdateFinalizeCommand : public WebAppCommandTemplate<AppLock> {
  public:
-  using ManifestWriteCallback = base::OnceCallback<
-      void(const GURL& url, const AppId& app_id, ManifestUpdateResult result)>;
+  using ManifestWriteCallback =
+      base::OnceCallback<void(const GURL& url,
+                              const webapps::AppId& app_id,
+                              ManifestUpdateResult result)>;
 
   ManifestUpdateFinalizeCommand(
       const GURL& url,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppInstallInfo install_info,
       ManifestWriteCallback write_callback,
       std::unique_ptr<ScopedKeepAlive> keep_alive,
@@ -55,7 +58,7 @@
   }
 
  private:
-  void OnInstallationComplete(const AppId& app_id,
+  void OnInstallationComplete(const webapps::AppId& app_id,
                               webapps::InstallResultCode code,
                               OsHooksErrors os_hooks_errors);
   void CompleteCommand(webapps::InstallResultCode code,
@@ -65,7 +68,7 @@
   std::unique_ptr<AppLock> lock_;
 
   const GURL url_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   WebAppInstallInfo install_info_;
   ManifestWriteCallback write_callback_;
   // Two KeepAlive objects, to make sure that manifest update writes
diff --git a/chrome/browser/web_applications/commands/manifest_update_finalize_command_unittest.cc b/chrome/browser/web_applications/commands/manifest_update_finalize_command_unittest.cc
index c86e0a08..074d4d5 100644
--- a/chrome/browser/web_applications/commands/manifest_update_finalize_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/manifest_update_finalize_command_unittest.cc
@@ -43,7 +43,7 @@
  protected:
   std::unique_ptr<ManifestUpdateFinalizeCommand> CreateCommand(
       const GURL& url,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppInstallInfo install_info,
       ManifestUpdateFinalizeCommand::ManifestWriteCallback callback) {
     auto keep_alive = std::make_unique<ScopedKeepAlive>(
@@ -56,14 +56,14 @@
   }
 
   ManifestUpdateResult RunCommandAndGetResult(const GURL& url,
-                                              const AppId& app_id,
+                                              const webapps::AppId& app_id,
                                               WebAppInstallInfo install_info) {
     ManifestUpdateResult output_result;
     base::RunLoop loop;
     provider().command_manager().ScheduleCommand(CreateCommand(
         url, app_id, std::move(install_info),
         base::BindLambdaForTesting([&](const GURL& url,
-                                       const AppId& output_app_id,
+                                       const webapps::AppId& output_app_id,
                                        ManifestUpdateResult result) {
           EXPECT_EQ(output_app_id, app_id);
           output_result = result;
@@ -73,7 +73,7 @@
     return output_result;
   }
 
-  AppId InstallWebApp() {
+  webapps::AppId InstallWebApp() {
     auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = app_url();
     web_app_info->manifest_id = GenerateManifestIdFromStartUrlOnly(app_url());
@@ -103,7 +103,7 @@
 };
 
 TEST_F(ManifestUpdateFinalizeCommandTest, NameUpdate) {
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   ManifestUpdateResult expected_result = RunCommandAndGetResult(
       app_url(), app_id, GetNewInstallInfoWithTitle(u"New Name"));
   EXPECT_EQ(expected_result, ManifestUpdateResult::kAppUpdated);
diff --git a/chrome/browser/web_applications/commands/navigate_and_trigger_install_dialog_command.h b/chrome/browser/web_applications/commands/navigate_and_trigger_install_dialog_command.h
index 19c8d8c..0cf6c78 100644
--- a/chrome/browser/web_applications/commands/navigate_and_trigger_install_dialog_command.h
+++ b/chrome/browser/web_applications/commands/navigate_and_trigger_install_dialog_command.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/installable/installable_logging.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 #include "url/gurl.h"
 
@@ -94,7 +95,7 @@
   const std::unique_ptr<WebAppDataRetriever> data_retriever_;
   raw_ptr<Profile> profile_ = nullptr;
 
-  AppId app_id_;
+  webapps::AppId app_id_;
   raw_ptr<content::WebContents> web_contents_ = nullptr;
   base::Value::List error_log_;
 
diff --git a/chrome/browser/web_applications/commands/os_integration_synchronize_command.cc b/chrome/browser/web_applications/commands/os_integration_synchronize_command.cc
index 0ccdf340..07e208b 100644
--- a/chrome/browser/web_applications/commands/os_integration_synchronize_command.cc
+++ b/chrome/browser/web_applications/commands/os_integration_synchronize_command.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/web_applications/locks/app_lock.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -37,7 +37,7 @@
 }  // namespace
 
 OsIntegrationSynchronizeCommand::OsIntegrationSynchronizeCommand(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     absl::optional<SynchronizeOsOptions> synchronize_options,
     base::OnceClosure synchronize_callback)
     : WebAppCommandTemplate<AppLock>("OsIntegrationSynchronizeCommand"),
diff --git a/chrome/browser/web_applications/commands/os_integration_synchronize_command.h b/chrome/browser/web_applications/commands/os_integration_synchronize_command.h
index f914a09..8046d9a 100644
--- a/chrome/browser/web_applications/commands/os_integration_synchronize_command.h
+++ b/chrome/browser/web_applications/commands/os_integration_synchronize_command.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -24,7 +25,7 @@
 class OsIntegrationSynchronizeCommand : public WebAppCommandTemplate<AppLock> {
  public:
   OsIntegrationSynchronizeCommand(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       absl::optional<SynchronizeOsOptions> synchronize_options,
       base::OnceClosure synchronize_callback);
   ~OsIntegrationSynchronizeCommand() override;
@@ -41,7 +42,7 @@
   std::unique_ptr<AppLockDescription> app_lock_description_;
   std::unique_ptr<AppLock> app_lock_;
 
-  AppId app_id_;
+  webapps::AppId app_id_;
   absl::optional<SynchronizeOsOptions> synchronize_options_ = absl::nullopt;
   base::OnceClosure synchronize_callback_;
 
diff --git a/chrome/browser/web_applications/commands/os_integration_synchronize_command_unittest.cc b/chrome/browser/web_applications/commands/os_integration_synchronize_command_unittest.cc
index f9da80c86..6cc60b5b 100644
--- a/chrome/browser/web_applications/commands/os_integration_synchronize_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/os_integration_synchronize_command_unittest.cc
@@ -81,31 +81,33 @@
     WebAppTest::TearDown();
   }
 
-  AppId InstallWebApp(std::unique_ptr<WebAppInstallInfo> install_info,
-                      webapps::WebappInstallSource source =
-                          webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON) {
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+  webapps::AppId InstallWebApp(
+      std::unique_ptr<WebAppInstallInfo> install_info,
+      webapps::WebappInstallSource source =
+          webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON) {
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     provider()->scheduler().InstallFromInfo(
         std::move(install_info), /*overwrite_existing_manifest_fields=*/true,
         source, result.GetCallback());
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
-  void RunSynchronizeCommand(const AppId& app_id) {
+  void RunSynchronizeCommand(const webapps::AppId& app_id) {
     base::test::TestFuture<void> synchronize_future;
     provider()->scheduler().SynchronizeOsIntegration(
         app_id, synchronize_future.GetCallback());
     EXPECT_TRUE(synchronize_future.Wait());
   }
 
-  bool EnableRunOnOsLoginMode(const AppId& app_id) {
+  bool EnableRunOnOsLoginMode(const webapps::AppId& app_id) {
     base::test::TestFuture<void> future;
     provider()->scheduler().SetRunOnOsLoginMode(
         app_id, RunOnOsLoginMode::kWindowed, future.GetCallback());
@@ -209,7 +211,7 @@
   protocol_handler.protocol = "web+test";
 
   install_info->protocol_handlers = {protocol_handler};
-  const AppId& app_id = InstallWebApp(std::move(install_info));
+  const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   absl::optional<proto::WebAppOsIntegrationState> current_states =
       provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -258,7 +260,7 @@
   file_handlers.push_back(file_handler);
 
   install_info->file_handlers = file_handlers;
-  const AppId& app_id = InstallWebApp(std::move(install_info));
+  const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   absl::optional<proto::WebAppOsIntegrationState> current_states =
       provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -298,7 +300,7 @@
   install_info->title = u"Test App";
   install_info->user_display_mode =
       web_app::mojom::UserDisplayMode::kStandalone;
-  const AppId& app_id = InstallWebApp(std::move(install_info));
+  const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   absl::optional<proto::WebAppOsIntegrationState> current_states =
       provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -339,7 +341,7 @@
   install_info->shortcuts_menu_icon_bitmaps = shortcuts_menu_icons;
   install_info->shortcuts_menu_item_infos =
       CreateShortcutMenuItemInfoFromBitmaps(shortcuts_menu_icons);
-  const AppId& app_id = InstallWebApp(std::move(install_info));
+  const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   absl::optional<proto::WebAppOsIntegrationState> current_states =
       provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -400,7 +402,7 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   install_info->icon_bitmaps.any = std::move(icon_map);
 
-  const AppId& app_id = InstallWebApp(std::move(install_info));
+  const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   absl::optional<proto::WebAppOsIntegrationState> current_states =
       provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -437,7 +439,7 @@
   install_info->title = u"Test App";
   install_info->user_display_mode =
       web_app::mojom::UserDisplayMode::kStandalone;
-  const AppId& app_id = InstallWebApp(std::move(install_info));
+  const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   absl::optional<proto::WebAppOsIntegrationState> current_states =
       provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
diff --git a/chrome/browser/web_applications/commands/run_on_os_login_command.cc b/chrome/browser/web_applications/commands/run_on_os_login_command.cc
index 92dbfec..f50601b 100644
--- a/chrome/browser/web_applications/commands/run_on_os_login_command.cc
+++ b/chrome/browser/web_applications/commands/run_on_os_login_command.cc
@@ -25,7 +25,7 @@
 
 // static
 std::unique_ptr<RunOnOsLoginCommand> RunOnOsLoginCommand::CreateForSetLoginMode(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     RunOnOsLoginMode login_mode,
     base::OnceClosure callback) {
   return base::WrapUnique(new RunOnOsLoginCommand(
@@ -35,7 +35,7 @@
 
 // static
 std::unique_ptr<RunOnOsLoginCommand>
-RunOnOsLoginCommand::CreateForSyncLoginMode(const AppId& app_id,
+RunOnOsLoginCommand::CreateForSyncLoginMode(const webapps::AppId& app_id,
                                             base::OnceClosure callback) {
   return base::WrapUnique(new RunOnOsLoginCommand(
       app_id,
@@ -44,7 +44,7 @@
 }
 
 RunOnOsLoginCommand::RunOnOsLoginCommand(
-    AppId app_id,
+    webapps::AppId app_id,
     absl::optional<RunOnOsLoginMode> login_mode,
     RunOnOsLoginAction set_or_sync_mode,
     base::OnceClosure callback)
diff --git a/chrome/browser/web_applications/commands/run_on_os_login_command.h b/chrome/browser/web_applications/commands/run_on_os_login_command.h
index a40ecfb..ffe8d74 100644
--- a/chrome/browser/web_applications/commands/run_on_os_login_command.h
+++ b/chrome/browser/web_applications/commands/run_on_os_login_command.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -43,11 +44,11 @@
 class RunOnOsLoginCommand : public WebAppCommandTemplate<AppLock> {
  public:
   static std::unique_ptr<RunOnOsLoginCommand> CreateForSetLoginMode(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       RunOnOsLoginMode login_mode,
       base::OnceClosure callback);
   static std::unique_ptr<RunOnOsLoginCommand> CreateForSyncLoginMode(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceClosure callback);
   ~RunOnOsLoginCommand() override;
 
@@ -58,7 +59,7 @@
   base::Value ToDebugValue() const override;
 
  private:
-  RunOnOsLoginCommand(AppId app_id,
+  RunOnOsLoginCommand(webapps::AppId app_id,
                       absl::optional<RunOnOsLoginMode> login_mode,
                       RunOnOsLoginAction set_or_sync_mode,
                       base::OnceClosure callback_);
@@ -81,7 +82,7 @@
   std::unique_ptr<AppLockDescription> lock_description_;
   std::unique_ptr<AppLock> lock_;
 
-  AppId app_id_;
+  webapps::AppId app_id_;
   absl::optional<RunOnOsLoginMode> login_mode_;
   RunOnOsLoginAction set_or_sync_mode_;
   std::string stop_reason_;
diff --git a/chrome/browser/web_applications/commands/run_on_os_login_command_unittest.cc b/chrome/browser/web_applications/commands/run_on_os_login_command_unittest.cc
index ab9f54f..68b6b78 100644
--- a/chrome/browser/web_applications/commands/run_on_os_login_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/run_on_os_login_command_unittest.cc
@@ -17,13 +17,13 @@
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/common/chrome_features.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
@@ -47,7 +47,7 @@
   ~TestOsIntegrationManager() override = default;
 
   // OsIntegrationManager:
-  void InstallOsHooks(const AppId& app_id,
+  void InstallOsHooks(const webapps::AppId& app_id,
                       InstallOsHooksCallback callback,
                       std::unique_ptr<WebAppInstallInfo> web_app_info,
                       InstallOsHooksOptions options) override {
@@ -62,7 +62,7 @@
                                              std::move(web_app_info), options);
   }
 
-  void UninstallOsHooks(const AppId& app_id,
+  void UninstallOsHooks(const webapps::AppId& app_id,
                         const OsHooksOptions& os_hooks,
                         UninstallOsHooksCallback callback) override {
     if (os_hooks[OsHookType::kRunOnOsLogin]) {
@@ -137,7 +137,7 @@
 
 TEST_P(RunOnOsLoginCommandTest, SetRunOnOsLoginModes) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   RegisterApp(std::move(web_app));
   base::HistogramTester tester;
 
@@ -192,17 +192,17 @@
   auto web_app_default2 = test::CreateWebApp(GURL("https:/default2.example/"));
   auto web_app_windowed = test::CreateWebApp(GURL("https://windowed.example/"));
   auto web_app_allowed = test::CreateWebApp(GURL("https://allowed.example/"));
-  const AppId app_id_default = web_app_default->app_id();
-  const AppId app_id_default2 = web_app_default2->app_id();
-  const AppId app_id_windowed = web_app_windowed->app_id();
-  const AppId app_id_allowed = web_app_allowed->app_id();
+  const webapps::AppId app_id_default = web_app_default->app_id();
+  const webapps::AppId app_id_default2 = web_app_default2->app_id();
+  const webapps::AppId app_id_windowed = web_app_windowed->app_id();
+  const webapps::AppId app_id_allowed = web_app_allowed->app_id();
 
   RegisterApp(std::move(web_app_default));
   RegisterApp(std::move(web_app_default2));
   RegisterApp(std::move(web_app_windowed));
   RegisterApp(std::move(web_app_allowed));
 
-  for (const AppId& app_id : {app_id_default2, app_id_allowed}) {
+  for (const webapps::AppId& app_id : {app_id_default2, app_id_allowed}) {
     base::RunLoop loop;
     provider()->command_manager().ScheduleCommand(
         RunOnOsLoginCommand::CreateForSetLoginMode(
@@ -301,7 +301,7 @@
 
 TEST_P(RunOnOsLoginCommandTest, RepeatedCallsDoNotCauseRepeatedOSRegistration) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   RegisterApp(std::move(web_app));
 
   base::RunLoop loop1;
@@ -323,7 +323,7 @@
 
 TEST_P(RunOnOsLoginCommandTest, NotRunDoesNotAtemptOSRegistration) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   RegisterApp(std::move(web_app));
 
   base::RunLoop loop;
@@ -341,7 +341,7 @@
 
 TEST_P(RunOnOsLoginCommandTest, SyncCommandAndUninstallOSHooks) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   RegisterApp(std::move(web_app));
   {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
@@ -381,7 +381,7 @@
 TEST_P(RunOnOsLoginCommandTest,
        AbortCommandOnAlreadyMatchingRunOnOsLoginState) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   RegisterApp(std::move(web_app));
   base::HistogramTester tester;
 
@@ -418,7 +418,7 @@
 
 TEST_P(RunOnOsLoginCommandTest, AbortCommandOnPolicyBlockedApp) {
   auto web_app = test::CreateWebApp(GURL("https:/default.example/"));
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   RegisterApp(std::move(web_app));
   base::HistogramTester tester;
 
@@ -451,7 +451,7 @@
 
 TEST_P(RunOnOsLoginCommandTest, VerifySetWorksOnAppWithNoStateDefined) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   // Run on OS Login state in the web_app DB is not defined.
   {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
@@ -483,7 +483,7 @@
 
 TEST_P(RunOnOsLoginCommandTest, VerifySyncWorksOnAppWithNoStateDefined) {
   auto web_app = test::CreateWebApp(GURL("https:/default.example/"));
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
     update->CreateApp(std::move(web_app));
diff --git a/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command.cc b/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command.cc
index d93949dc1..cd551c9 100644
--- a/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command.cc
+++ b/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command.cc
@@ -63,7 +63,7 @@
   }
 
   // Prepare pending jobs for next app ID.
-  AppId app_id = ids_to_uninstall_.back();
+  webapps::AppId app_id = ids_to_uninstall_.back();
   ids_to_uninstall_.pop_back();
 
   for (auto install_source : kUserDrivenInstallSources) {
diff --git a/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command.h b/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command.h
index c8d1d230..3944b08 100644
--- a/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command.h
+++ b/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command.h
@@ -54,7 +54,7 @@
   const raw_ref<Profile> profile_;
   Callback callback_;
 
-  std::vector<AppId> ids_to_uninstall_;
+  std::vector<webapps::AppId> ids_to_uninstall_;
   std::vector<std::pair<std::unique_ptr<RemoveInstallSourceJob>,
                         WebAppManagement::Type>>
       pending_jobs_;
diff --git a/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command_unittest.cc b/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command_unittest.cc
index 9ed24132..befecae 100644
--- a/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/uninstall_all_user_installed_web_apps_command_unittest.cc
@@ -57,7 +57,7 @@
                                 prefs::kWebAppInstallForceList);
     update->Append(std::move(app_policy));
   }
-  AppId app_id = observer.Wait();
+  webapps::AppId app_id = observer.Wait();
 
   base::test::TestFuture<const absl::optional<std::string>&> future;
   provider()->command_manager().ScheduleCommand(
@@ -79,9 +79,9 @@
                                 prefs::kWebAppInstallForceList);
     update->Append(std::move(app_policy));
   }
-  AppId app_id = observer.Wait();
+  webapps::AppId app_id = observer.Wait();
 
-  AppId sync_app_id = test::InstallDummyWebApp(
+  webapps::AppId sync_app_id = test::InstallDummyWebApp(
       profile(), "app from sync", GURL("https://example.com/install"),
       webapps::WebappInstallSource::SYNC);
   EXPECT_EQ(app_id, sync_app_id);
@@ -104,13 +104,13 @@
 
 TEST_F(UninstallAllUserInstalledWebAppsCommandTest,
        UninstallsUserInstalledWebApps) {
-  AppId app_id1 = test::InstallDummyWebApp(
+  webapps::AppId app_id1 = test::InstallDummyWebApp(
       profile(), "app from browser", GURL("https://example1.com"),
       webapps::WebappInstallSource::AUTOMATIC_PROMPT_BROWSER_TAB);
 
-  AppId app_id2 = test::InstallDummyWebApp(profile(), "app from sync",
-                                           GURL("https://example2.com"),
-                                           webapps::WebappInstallSource::SYNC);
+  webapps::AppId app_id2 = test::InstallDummyWebApp(
+      profile(), "app from sync", GURL("https://example2.com"),
+      webapps::WebappInstallSource::SYNC);
 
   base::test::TestFuture<const absl::optional<std::string>&> future;
   provider()->command_manager().ScheduleCommand(
@@ -149,9 +149,9 @@
   EXPECT_CALL(*file_utils_wrapper_, WriteFile)
       .WillRepeatedly(testing::ReturnArg<2>());
 
-  AppId app_id = test::InstallDummyWebApp(profile(), "app from sync",
-                                          GURL("https://example.com"),
-                                          webapps::WebappInstallSource::SYNC);
+  webapps::AppId app_id = test::InstallDummyWebApp(
+      profile(), "app from sync", GURL("https://example.com"),
+      webapps::WebappInstallSource::SYNC);
 
   EXPECT_CALL(*file_utils_wrapper_, DeleteFileRecursively)
       .WillOnce(testing::Return(false));
diff --git a/chrome/browser/web_applications/commands/update_file_handler_command.cc b/chrome/browser/web_applications/commands/update_file_handler_command.cc
index 05aa6d7..c8be7035 100644
--- a/chrome/browser/web_applications/commands/update_file_handler_command.cc
+++ b/chrome/browser/web_applications/commands/update_file_handler_command.cc
@@ -14,9 +14,9 @@
 #include "chrome/browser/web_applications/locks/app_lock.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -44,14 +44,14 @@
 // static
 std::unique_ptr<UpdateFileHandlerCommand>
 UpdateFileHandlerCommand::CreateForPersistUserChoice(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool allowed,
     base::OnceClosure callback) {
   return base::WrapUnique(
       new UpdateFileHandlerCommand(app_id, allowed, std::move(callback)));
 }
 
-UpdateFileHandlerCommand::UpdateFileHandlerCommand(const AppId& app_id,
+UpdateFileHandlerCommand::UpdateFileHandlerCommand(const webapps::AppId& app_id,
                                                    bool user_choice_to_remember,
                                                    base::OnceClosure callback)
     : WebAppCommandTemplate<AppLock>("UpdateFileHandlerCommand"),
diff --git a/chrome/browser/web_applications/commands/update_file_handler_command.h b/chrome/browser/web_applications/commands/update_file_handler_command.h
index 78f37f3..eda92a88 100644
--- a/chrome/browser/web_applications/commands/update_file_handler_command.h
+++ b/chrome/browser/web_applications/commands/update_file_handler_command.h
@@ -10,6 +10,7 @@
 #include "base/functional/callback.h"
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -25,7 +26,7 @@
   // Updates the File Handling API approval state for the given app. If
   // necessary, it also updates the registration with the OS.
   static std::unique_ptr<UpdateFileHandlerCommand> CreateForPersistUserChoice(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       bool allowed,
       base::OnceClosure callback);
 
@@ -38,7 +39,7 @@
   void OnShutdown() override;
 
  private:
-  UpdateFileHandlerCommand(const AppId& app_id,
+  UpdateFileHandlerCommand(const webapps::AppId& app_id,
                            bool user_choice_to_remember,
                            base::OnceClosure callback);
   void OnFileHandlerUpdated(bool file_handling_enabled, Result result);
@@ -47,7 +48,7 @@
   std::unique_ptr<AppLockDescription> lock_description_;
   std::unique_ptr<AppLock> lock_;
 
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   const bool user_choice_to_remember_;
   base::OnceClosure callback_;
 
diff --git a/chrome/browser/web_applications/commands/update_file_handler_command_unittest.cc b/chrome/browser/web_applications/commands/update_file_handler_command_unittest.cc
index cc47df45..9076802 100644
--- a/chrome/browser/web_applications/commands/update_file_handler_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/update_file_handler_command_unittest.cc
@@ -67,7 +67,7 @@
 };
 
 TEST_P(UpdateFileHandlerCommandTest, UserChoiceAllowPersisted) {
-  const AppId app_id =
+  const webapps::AppId app_id =
       test::InstallDummyWebApp(profile(), kTestAppName, kTestAppUrl);
   EXPECT_EQ(
       provider()->registrar_unsafe().GetAppFileHandlerApprovalState(app_id),
@@ -87,7 +87,7 @@
 }
 
 TEST_P(UpdateFileHandlerCommandTest, UserChoiceDisallowPersisted) {
-  const AppId app_id =
+  const webapps::AppId app_id =
       test::InstallDummyWebApp(profile(), kTestAppName, kTestAppUrl);
   EXPECT_EQ(
       provider()->registrar_unsafe().GetAppFileHandlerApprovalState(app_id),
diff --git a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.cc b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.cc
index fad1a9b3..74477e52 100644
--- a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.cc
+++ b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.cc
@@ -17,16 +17,16 @@
 #include "chrome/browser/web_applications/locks/app_lock.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
 UpdateProtocolHandlerApprovalCommand::UpdateProtocolHandlerApprovalCommand(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& protocol_scheme,
     ApiApprovalState approval_state,
     base::OnceClosure callback)
diff --git a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.h b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.h
index f2a6e68..692e576 100644
--- a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.h
+++ b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -27,7 +28,7 @@
 class UpdateProtocolHandlerApprovalCommand
     : public WebAppCommandTemplate<AppLock> {
  public:
-  UpdateProtocolHandlerApprovalCommand(const AppId& app_id,
+  UpdateProtocolHandlerApprovalCommand(const webapps::AppId& app_id,
                                        const std::string& protocol_scheme,
                                        ApiApprovalState approval_state,
                                        base::OnceClosure callback);
@@ -50,7 +51,7 @@
   std::unique_ptr<AppLockDescription> lock_description_;
   std::unique_ptr<AppLock> lock_;
 
-  const AppId app_id_;
+  const webapps::AppId app_id_;
   std::string protocol_scheme_;
   const ApiApprovalState approval_state_;
   base::OnceClosure callback_;
diff --git a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command_browsertest.cc b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command_browsertest.cc
index 50eedf32..5274c03 100644
--- a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command_browsertest.cc
@@ -82,7 +82,7 @@
     WebAppControllerBrowserTest::TearDownOnMainThread();
   }
 
-  web_app::AppId InstallWebAppWithProtocolHandlers(
+  webapps::AppId InstallWebAppWithProtocolHandlers(
       const std::vector<apps::ProtocolHandlerInfo>& protocol_handlers) {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
@@ -90,7 +90,8 @@
     info->title = kAppName;
     info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
     info->protocol_handlers = protocol_handlers;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     // InstallFromInfoWithParams is used instead of InstallFromInfo, because
     // InstallFromInfo doesn't register OS integration.
     provider().scheduler().InstallFromInfoWithParams(
@@ -100,15 +101,15 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success)
-      return AppId();
+      return webapps::AppId();
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
 #if BUILDFLAG(IS_MAC)
   std::vector<std::string> GetAppShimRegisteredProtocolHandlers(
-      const AppId& app_id) {
+      const webapps::AppId& app_id) {
     std::vector<std::string> protocol_schemes;
     for (const auto& [file_path, handler] :
          AppShimRegistry::Get()->GetHandlersForApp(app_id)) {
@@ -140,7 +141,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   EXPECT_THAT(provider().registrar_unsafe().IsAllowedLaunchProtocol(
                   app_id, protocol_handler.protocol),
@@ -170,7 +171,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   base::test::TestFuture<void> future;
   provider().scheduler().UpdateProtocolHandlerUserApproval(
@@ -207,7 +208,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   base::test::TestFuture<void> future_first;
   base::test::TestFuture<void> future_second;
@@ -249,7 +250,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   base::test::TestFuture<void> future;
   provider().scheduler().UpdateProtocolHandlerUserApproval(
@@ -291,7 +292,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   base::test::TestFuture<void> future_first;
   base::test::TestFuture<void> future_second;
@@ -338,7 +339,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   {
     base::test::TestFuture<void> future;
@@ -388,7 +389,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   {
     base::test::TestFuture<void> future;
@@ -460,7 +461,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   {
     base::test::TestFuture<void> future;
@@ -533,7 +534,7 @@
       std::string(kTestAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  webapps::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
 
   {
     base::test::TestFuture<void> future;
diff --git a/chrome/browser/web_applications/commands/web_app_command.h b/chrome/browser/web_applications/commands/web_app_command.h
index 1d1e74925..9ff844a 100644
--- a/chrome/browser/web_applications/commands/web_app_command.h
+++ b/chrome/browser/web_applications/commands/web_app_command.h
@@ -14,6 +14,7 @@
 #include "base/sequence_checker.h"
 #include "base/values.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace content {
@@ -28,10 +29,10 @@
 
 enum class CommandResult { kSuccess, kFailure, kShutdown };
 
-// Each command has a queue id, which is either an `AppId` corresponding to a
-// specific web app, or `absl::nullopt` for the global queue. The global queue
-// is independent (does not block) of other queues.
-using WebAppCommandQueueId = absl::optional<AppId>;
+// Each command has a queue id, which is either an `webapps::AppId`
+// corresponding to a specific web app, or `absl::nullopt` for the global queue.
+// The global queue is independent (does not block) of other queues.
+using WebAppCommandQueueId = absl::optional<webapps::AppId>;
 
 // Encapsulates code that reads or modifies the WebAppProvider system. All
 // reading or writing to the system should occur in a WebAppCommand to ensure
diff --git a/chrome/browser/web_applications/commands/web_app_uninstall_command_unittest.cc b/chrome/browser/web_applications/commands/web_app_uninstall_command_unittest.cc
index 6a596da..bea95b4 100644
--- a/chrome/browser/web_applications/commands/web_app_uninstall_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/web_app_uninstall_command_unittest.cc
@@ -81,7 +81,7 @@
 TEST_F(WebAppUninstallCommandTest, SimpleUninstallInternal) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kSync);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update =
         provider()->sync_bridge_unsafe().BeginUpdate();
@@ -118,7 +118,7 @@
 TEST_F(WebAppUninstallCommandTest, SimpleUninstallExternal) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kDefault);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update =
         provider()->sync_bridge_unsafe().BeginUpdate();
@@ -156,7 +156,7 @@
 TEST_F(WebAppUninstallCommandTest, FailedDataDeletion) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kSync);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update =
         provider()->sync_bridge_unsafe().BeginUpdate();
@@ -193,7 +193,7 @@
 TEST_F(WebAppUninstallCommandTest, FailedOsHooksSetting) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kSync);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update =
         provider()->sync_bridge_unsafe().BeginUpdate();
@@ -231,7 +231,7 @@
 TEST_F(WebAppUninstallCommandTest, TryToUninstallNonExistentApp) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kSync);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
 
   EXPECT_CALL(*os_integration_manager_,
               Synchronize(app_id, testing::_, testing::_))
@@ -262,7 +262,7 @@
 TEST_F(WebAppUninstallCommandTest, CommandManagerShutdownThrowsError) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kSync);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update =
         provider()->sync_bridge_unsafe().BeginUpdate();
@@ -297,7 +297,7 @@
 TEST_F(WebAppUninstallCommandTest, UserUninstalledPrefsFilled) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kDefault);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   web_app->AddInstallURLToManagementExternalConfigMap(
       WebAppManagement::kDefault, GURL("https://www.example.com/install"));
   {
@@ -340,7 +340,7 @@
 TEST_F(WebAppUninstallCommandTest, ExternalConfigMapMissing) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kDefault);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update =
         provider()->sync_bridge_unsafe().BeginUpdate();
@@ -385,7 +385,7 @@
   web_app->AddInstallURLToManagementExternalConfigMap(
       WebAppManagement::kDefault, GURL("https://example.com/install"));
   EXPECT_FALSE(web_app->CanUserUninstallWebApp());
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update =
         provider()->sync_bridge_unsafe().BeginUpdate();
@@ -437,7 +437,7 @@
 
   WebAppInstallManagerObserverAdapter observer(profile());
   observer.SetWebAppSourceRemovedDelegate(
-      base::BindLambdaForTesting([&](const AppId& app_id) {
+      base::BindLambdaForTesting([&](const webapps::AppId& app_id) {
         // The policy source will be removed and WebAppOsUninstallation is
         // registered.
         EXPECT_FALSE(provider()
@@ -467,7 +467,7 @@
 TEST_P(WebAppUninstallCommandSourceTest, RunTestForUninstallSource) {
   auto web_app = test::CreateWebApp(GURL("https://www.example.com"),
                                     WebAppManagement::kSync);
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   {
     ScopedRegistryUpdate update =
         provider()->sync_bridge_unsafe().BeginUpdate();
diff --git a/chrome/browser/web_applications/extensions/BUILD.gn b/chrome/browser/web_applications/extensions/BUILD.gn
index c26fd762..6505025 100644
--- a/chrome/browser/web_applications/extensions/BUILD.gn
+++ b/chrome/browser/web_applications/extensions/BUILD.gn
@@ -38,6 +38,7 @@
     "//components/services/app_service",
     "//components/sync/model",
     "//components/webapps/browser:browser",
+    "//components/webapps/common",
     "//content/public/browser",
     "//extensions/browser",
     "//skia",
@@ -62,6 +63,7 @@
     "//chrome/test:test_support",
     "//components/crx_file:crx_file",
     "//components/webapps/browser:browser",
+    "//components/webapps/common",
     "//content/public/browser",
     "//content/test:test_support",
     "//extensions/browser/install",
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_shortcut.cc b/chrome/browser/web_applications/extensions/web_app_extension_shortcut.cc
index 8c76127b..afed4b87 100644
--- a/chrome/browser/web_applications/extensions/web_app_extension_shortcut.cc
+++ b/chrome/browser/web_applications/extensions/web_app_extension_shortcut.cc
@@ -24,12 +24,12 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_registry.h"
@@ -82,14 +82,15 @@
       std::move(shortcut_info), std::move(callback));
 }
 
-using AppCallbackMap = base::flat_map<AppId, std::vector<base::OnceClosure>>;
+using AppCallbackMap =
+    base::flat_map<webapps::AppId, std::vector<base::OnceClosure>>;
 AppCallbackMap& GetShortcutsDeletedCallbackMap() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   static base::NoDestructor<AppCallbackMap> map;
   return *map;
 }
 
-void ShortcutsDeleted(const AppId& app_id, bool /*shortcut_deleted*/) {
+void ShortcutsDeleted(const webapps::AppId& app_id, bool /*shortcut_deleted*/) {
   auto& map = GetShortcutsDeletedCallbackMap();
   auto it = map.find(app_id);
   if (it == map.end())
@@ -284,7 +285,7 @@
       base::BindOnce(ShortcutsDeleted, app->id()));
 }
 
-void WaitForExtensionShortcutsDeleted(const AppId& app_id,
+void WaitForExtensionShortcutsDeleted(const webapps::AppId& app_id,
                                       base::OnceClosure callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   GetShortcutsDeletedCallbackMap()[app_id].push_back(std::move(callback));
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_shortcut.h b/chrome/browser/web_applications/extensions/web_app_extension_shortcut.h
index e15b9ea..8bc19550 100644
--- a/chrome/browser/web_applications/extensions/web_app_extension_shortcut.h
+++ b/chrome/browser/web_applications/extensions/web_app_extension_shortcut.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -77,7 +78,7 @@
 
 // Register a callback that will be run once |app_id|'s shortcuts have been
 // deleted.
-void WaitForExtensionShortcutsDeleted(const AppId& app_id,
+void WaitForExtensionShortcutsDeleted(const webapps::AppId& app_id,
                                       base::OnceClosure callback);
 
 // Updates shortcuts for |app|, but does not create new ones if shortcuts are
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
index 9b7a340..ebd3153 100644
--- a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
+++ b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
@@ -22,12 +22,12 @@
 #include "chrome/browser/web_applications/app_shim_registry_mac.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut_mac.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #import "chrome/common/mac/app_mode_common.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_registry.h"
diff --git a/chrome/browser/web_applications/extensions/web_app_uninstall_and_replace_job.cc b/chrome/browser/web_applications/extensions/web_app_uninstall_and_replace_job.cc
index c677f78..905ce312 100644
--- a/chrome/browser/web_applications/extensions/web_app_uninstall_and_replace_job.cc
+++ b/chrome/browser/web_applications/extensions/web_app_uninstall_and_replace_job.cc
@@ -31,7 +31,7 @@
 
 namespace {
 
-bool IsAppInstalled(Profile* profile, const AppId& app_id) {
+bool IsAppInstalled(Profile* profile, const webapps::AppId& app_id) {
   bool installed = false;
   auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile);
   proxy->AppRegistryCache().ForOneApp(
@@ -66,8 +66,8 @@
 WebAppUninstallAndReplaceJob::WebAppUninstallAndReplaceJob(
     Profile* profile,
     WithAppResources& to_app_lock,
-    const std::vector<AppId>& from_apps_or_extensions,
-    const AppId& to_app,
+    const std::vector<webapps::AppId>& from_apps_or_extensions,
+    const webapps::AppId& to_app,
     base::OnceCallback<void(bool uninstall_triggered)> on_complete)
     : profile_(*profile),
       to_app_lock_(to_app_lock),
@@ -79,8 +79,8 @@
 void WebAppUninstallAndReplaceJob::Start() {
   DCHECK(to_app_lock_->registrar().IsInstalled(to_app_));
 
-  std::vector<AppId> apps_to_replace;
-  for (const AppId& from_app : from_apps_or_extensions_) {
+  std::vector<webapps::AppId> apps_to_replace;
+  for (const webapps::AppId& from_app : from_apps_or_extensions_) {
     if (IsAppInstalled(&profile_.get(), from_app)) {
       apps_to_replace.emplace_back(from_app);
     }
@@ -109,7 +109,7 @@
 }
 
 void WebAppUninstallAndReplaceJob::MigrateUiAndUninstallApp(
-    const AppId& from_app,
+    const webapps::AppId& from_app,
     base::OnceClosure on_complete) {
 #if BUILDFLAG(IS_CHROMEOS)
   to_app_lock_->ui_manager().MigrateLauncherState(
@@ -123,7 +123,7 @@
 }
 
 void WebAppUninstallAndReplaceJob::OnMigrateLauncherState(
-    const AppId& from_app,
+    const webapps::AppId& from_app,
     base::OnceClosure on_complete) {
   // If migration of user/UI data is required for other app types consider
   // generalising this operation to be part of app service.
@@ -163,7 +163,7 @@
 
 void WebAppUninstallAndReplaceJob::
     OnShortcutInfoReceivedSearchShortcutLocations(
-        const AppId& from_app,
+        const webapps::AppId& from_app,
         base::OnceClosure on_complete,
         std::unique_ptr<ShortcutInfo> shortcut_info) {
   if (!shortcut_info) {
@@ -182,7 +182,7 @@
 }
 
 void WebAppUninstallAndReplaceJob::OnShortcutLocationGathered(
-    const AppId& from_app,
+    const webapps::AppId& from_app,
     base::OnceClosure on_complete,
     ShortcutLocations locations) {
   auto* proxy = apps::AppServiceProxyFactory::GetForProfile(&profile_.get());
diff --git a/chrome/browser/web_applications/extensions/web_app_uninstall_and_replace_job_unittest.cc b/chrome/browser/web_applications/extensions/web_app_uninstall_and_replace_job_unittest.cc
index aeef56e..2e9c52ee 100644
--- a/chrome/browser/web_applications/extensions/web_app_uninstall_and_replace_job_unittest.cc
+++ b/chrome/browser/web_applications/extensions/web_app_uninstall_and_replace_job_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/web_applications/test/web_app_test.h"
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -30,8 +30,8 @@
  public:
   TestUninstallAndReplaceJobCommand(
       Profile* profile,
-      const std::vector<AppId>& from_apps,
-      const AppId& to_app,
+      const std::vector<webapps::AppId>& from_apps,
+      const webapps::AppId& to_app,
       base::OnceCallback<void(bool uninstall_triggered)> on_complete)
       : WebAppCommandTemplate<AppLock>("TestUninstallAndReplaceJobCommand"),
         profile_(profile),
@@ -70,8 +70,8 @@
   std::unique_ptr<AppLockDescription> lock_description_;
   std::unique_ptr<AppLock> lock_;
 
-  const std::vector<AppId> from_apps_;
-  const AppId to_app_;
+  const std::vector<webapps::AppId> from_apps_;
+  const webapps::AppId to_app_;
   base::OnceCallback<void(bool uninstall_triggered)> on_complete_;
 
   absl::optional<WebAppUninstallAndReplaceJob> uninstall_and_replace_job_;
@@ -88,8 +88,8 @@
   }
 
   void ScheduleUninstallAndReplaceJob(
-      const std::vector<AppId>& from_apps,
-      const AppId& to_app,
+      const std::vector<webapps::AppId>& from_apps,
+      const webapps::AppId& to_app,
       base::OnceCallback<void(bool uninstall_triggered)> on_complete) {
     WebAppProvider::GetForTest(profile())->command_manager().ScheduleCommand(
         std::make_unique<TestUninstallAndReplaceJobCommand>(
@@ -118,11 +118,12 @@
        WebAppMigrationPreservesShortcutStates) {
   const GURL kOldAppUrl("https://old.app.com");
   // Install an old app to be replaced.
-  AppId old_app_id = test::InstallDummyWebApp(profile(), "old_app", kOldAppUrl);
+  webapps::AppId old_app_id =
+      test::InstallDummyWebApp(profile(), "old_app", kOldAppUrl);
 
   // Install a new app to migrate the old one to.
-  AppId new_app_id = test::InstallDummyWebApp(profile(), "new_app",
-                                              GURL("https://new.app.com"));
+  webapps::AppId new_app_id = test::InstallDummyWebApp(
+      profile(), "new_app", GURL("https://new.app.com"));
   if (AreOsIntegrationSubManagersEnabled()) {
     absl::optional<proto::WebAppOsIntegrationState> os_state =
         provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(
@@ -164,11 +165,11 @@
 
 TEST_F(WebAppUninstallAndReplaceJobTest, DoubleMigration) {
   // Install an old app to be replaced.
-  AppId old_app_id = test::InstallDummyWebApp(profile(), "old_app",
-                                              GURL("https://old.app.com"));
+  webapps::AppId old_app_id = test::InstallDummyWebApp(
+      profile(), "old_app", GURL("https://old.app.com"));
   // Install a new app to migrate the old one to.
-  AppId new_app_id = test::InstallDummyWebApp(profile(), "new_app",
-                                              GURL("https://new.app.com"));
+  webapps::AppId new_app_id = test::InstallDummyWebApp(
+      profile(), "new_app", GURL("https://new.app.com"));
   {
     WebAppTestUninstallObserver waiter(profile());
     waiter.BeginListening({old_app_id});
diff --git a/chrome/browser/web_applications/external_install_options.h b/chrome/browser/web_applications/external_install_options.h
index 4a99c4b..84f769c 100644
--- a/chrome/browser/web_applications/external_install_options.h
+++ b/chrome/browser/web_applications/external_install_options.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
@@ -188,7 +189,7 @@
 
   // A list of app_ids that the Web App System should attempt to uninstall and
   // replace with this app (e.g maintain shelf pins, app list positions).
-  std::vector<AppId> uninstall_and_replace;
+  std::vector<webapps::AppId> uninstall_and_replace;
 
   // Additional keywords that will be used by the OS when searching for the app.
   // Only affects Chrome OS.
@@ -223,7 +224,7 @@
   // Does not block installation if the actual app id doesn't match the
   // expectation.
   // Intended to be used for post-install activities like metrics and migration.
-  absl::optional<AppId> expected_app_id;
+  absl::optional<webapps::AppId> expected_app_id;
 };
 
 WebAppInstallParams ConvertExternalInstallOptionsToParams(
diff --git a/chrome/browser/web_applications/externally_managed_app_install_task.cc b/chrome/browser/web_applications/externally_managed_app_install_task.cc
index e543b9d..713f980 100644
--- a/chrome/browser/web_applications/externally_managed_app_install_task.cc
+++ b/chrome/browser/web_applications/externally_managed_app_install_task.cc
@@ -23,7 +23,7 @@
 ExternallyManagedAppInstallTask::~ExternallyManagedAppInstallTask() = default;
 
 void ExternallyManagedAppInstallTask::Install(
-    absl::optional<AppId> installed_placeholder_app_id,
+    absl::optional<webapps::AppId> installed_placeholder_app_id,
     ResultCallback result_callback) {
   provider_->scheduler().InstallExternallyManagedApp(
       std::move(install_options_), std::move(installed_placeholder_app_id),
diff --git a/chrome/browser/web_applications/externally_managed_app_manager.cc b/chrome/browser/web_applications/externally_managed_app_manager.cc
index 61d1c5fe..5b562ad 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager.cc
@@ -50,7 +50,7 @@
 
 ExternallyManagedAppManager::InstallResult::InstallResult(
     webapps::InstallResultCode code,
-    absl::optional<AppId> app_id,
+    absl::optional<webapps::AppId> app_id,
     bool did_uninstall_and_replace)
     : code(code),
       app_id(std::move(app_id)),
@@ -314,7 +314,7 @@
     const ExternalInstallOptions& install_options =
         front->task->install_options();
 
-    absl::optional<AppId> app_id =
+    absl::optional<webapps::AppId> app_id =
         lock.registrar().LookupExternalAppId(install_options.install_url);
     const bool is_placeholder_installed =
         app_id.has_value()
diff --git a/chrome/browser/web_applications/externally_managed_app_manager.h b/chrome/browser/web_applications/externally_managed_app_manager.h
index 64de8d9..ae28b25 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager.h
+++ b/chrome/browser/web_applications/externally_managed_app_manager.h
@@ -16,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/web_applications/external_install_options.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "url/gurl.h"
 
 class GURL;
@@ -68,16 +69,17 @@
  public:
   struct InstallResult {
     InstallResult();
-    explicit InstallResult(webapps::InstallResultCode code,
-                           absl::optional<AppId> app_id = absl::nullopt,
-                           bool did_uninstall_and_replace = false);
+    explicit InstallResult(
+        webapps::InstallResultCode code,
+        absl::optional<webapps::AppId> app_id = absl::nullopt,
+        bool did_uninstall_and_replace = false);
     InstallResult(const InstallResult&);
     ~InstallResult();
 
     bool operator==(const InstallResult& other) const;
 
     webapps::InstallResultCode code;
-    absl::optional<AppId> app_id;
+    absl::optional<webapps::AppId> app_id;
     bool did_uninstall_and_replace = false;
     // When adding fields, please update the `==` and `<<` operators to include
     // the new field.
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_browsertest.cc b/chrome/browser/web_applications/externally_managed_app_manager_browsertest.cc
index 1273b89..df1d50c 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_browsertest.cc
@@ -119,7 +119,7 @@
   InstallApp(CreateInstallOptions(url));
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(url);
+  absl::optional<webapps::AppId> app_id = registrar().LookupExternalAppId(url);
   EXPECT_TRUE(app_id.has_value());
   EXPECT_EQ("Manifest test app", registrar().GetAppShortName(app_id.value()));
 }
@@ -135,12 +135,13 @@
   InstallApp(CreateInstallOptions(install_url));
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(install_url);
+  absl::optional<webapps::AppId> app_id =
+      registrar().LookupExternalAppId(install_url);
   EXPECT_TRUE(app_id.has_value());
   EXPECT_EQ("Manifest test app", registrar().GetAppShortName(app_id.value()));
   // Same AppID should be in the registrar using start_url from the manifest.
   EXPECT_TRUE(registrar().IsLocallyInstalled(start_url));
-  absl::optional<AppId> opt_app_id =
+  absl::optional<webapps::AppId> opt_app_id =
       registrar().FindAppWithUrlInScope(start_url);
   EXPECT_TRUE(opt_app_id.has_value());
   EXPECT_EQ(*opt_app_id, app_id);
@@ -157,13 +158,14 @@
   InstallApp(CreateInstallOptions(install_url));
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(install_url);
+  absl::optional<webapps::AppId> app_id =
+      registrar().LookupExternalAppId(install_url);
   EXPECT_TRUE(app_id.has_value());
   EXPECT_EQ("Web app banner test page",
             registrar().GetAppShortName(app_id.value()));
   // Same AppID should be in the registrar using install_url.
   EXPECT_TRUE(registrar().IsLocallyInstalled(install_url));
-  absl::optional<AppId> opt_app_id =
+  absl::optional<webapps::AppId> opt_app_id =
       registrar().FindAppWithUrlInScope(install_url);
   ASSERT_TRUE(opt_app_id.has_value());
   EXPECT_EQ(*opt_app_id, app_id);
@@ -190,7 +192,7 @@
 
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(url);
+  absl::optional<webapps::AppId> app_id = registrar().LookupExternalAppId(url);
   ASSERT_TRUE(app_id.has_value());
   EXPECT_TRUE(
       registrar().IsPlaceholderApp(app_id.value(), WebAppManagement::kPolicy));
@@ -358,7 +360,7 @@
 
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(url);
+  absl::optional<webapps::AppId> app_id = registrar().LookupExternalAppId(url);
   ASSERT_TRUE(app_id.has_value());
   EXPECT_TRUE(
       registrar().IsPlaceholderApp(app_id.value(), WebAppManagement::kPolicy));
@@ -394,7 +396,8 @@
 
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(app_url);
+  absl::optional<webapps::AppId> app_id =
+      registrar().LookupExternalAppId(app_url);
   ASSERT_TRUE(app_id.has_value());
   EXPECT_TRUE(
       registrar().IsPlaceholderApp(app_id.value(), WebAppManagement::kPolicy));
@@ -459,7 +462,8 @@
 
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(app_url);
+  absl::optional<webapps::AppId> app_id =
+      registrar().LookupExternalAppId(app_url);
   ASSERT_TRUE(app_id.has_value());
   EXPECT_TRUE(
       registrar().IsPlaceholderApp(app_id.value(), WebAppManagement::kPolicy));
@@ -500,7 +504,8 @@
   ExternalInstallOptions install_options = CreateInstallOptions(url);
   install_options.bypass_service_worker_check = true;
   InstallApp(std::move(install_options));
-  absl::optional<AppId> app_id = registrar().FindAppWithUrlInScope(url);
+  absl::optional<webapps::AppId> app_id =
+      registrar().FindAppWithUrlInScope(url);
   EXPECT_TRUE(app_id.has_value());
   EXPECT_TRUE(registrar().GetAppScopeInternal(*app_id).has_value());
   EXPECT_EQ("Manifest test app", registrar().GetAppShortName(*app_id));
@@ -513,14 +518,15 @@
       "/banners/manifest_no_service_worker.html"));
   ExternalInstallOptions install_options = CreateInstallOptions(url);
   InstallApp(std::move(install_options));
-  absl::optional<AppId> app_id = registrar().FindAppWithUrlInScope(url);
+  absl::optional<webapps::AppId> app_id =
+      registrar().FindAppWithUrlInScope(url);
   EXPECT_TRUE(app_id.has_value());
   EXPECT_TRUE(registrar().GetAppScopeInternal(app_id.value()).has_value());
 }
 
 IN_PROC_BROWSER_TEST_F(ExternallyManagedAppManagerBrowserTest, ForceReinstall) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  absl::optional<AppId> app_id;
+  absl::optional<webapps::AppId> app_id;
   {
     GURL url(embedded_test_server()->GetURL(
         "/banners/"
@@ -540,7 +546,8 @@
     install_options.force_reinstall = true;
     InstallApp(std::move(install_options));
 
-    absl::optional<AppId> new_app_id = registrar().FindAppWithUrlInScope(url);
+    absl::optional<webapps::AppId> new_app_id =
+        registrar().FindAppWithUrlInScope(url);
     EXPECT_TRUE(new_app_id.has_value());
     EXPECT_EQ(new_app_id, app_id);
     EXPECT_EQ("Manifest test app",
@@ -551,7 +558,7 @@
 IN_PROC_BROWSER_TEST_F(ExternallyManagedAppManagerBrowserTest,
                        PolicyAppOverridesUserInstalledApp) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  absl::optional<AppId> app_id;
+  absl::optional<webapps::AppId> app_id;
   {
     // Install user app
     auto install_info = std::make_unique<WebAppInstallInfo>();
@@ -570,7 +577,8 @@
     // Install policy app
     GURL url(
         embedded_test_server()->GetURL("/banners/manifest_test_page.html"));
-    absl::optional<AppId> policy_app_id = ForceInstallWebApp(profile(), url);
+    absl::optional<webapps::AppId> policy_app_id =
+        ForceInstallWebApp(profile(), url);
     ASSERT_EQ(policy_app_id, app_id);
     ASSERT_EQ("Manifest test app",
               registrar().GetAppShortName(policy_app_id.value()));
@@ -587,7 +595,7 @@
   InstallApp(CreateInstallOptions(url));
   EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
             result_code_.value());
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(url);
+  absl::optional<webapps::AppId> app_id = registrar().LookupExternalAppId(url);
   ASSERT_TRUE(app_id.has_value());
 
   // The installer falls back to installing a web app of the original URL.
@@ -609,7 +617,7 @@
 
   EXPECT_EQ(webapps::InstallResultCode::kNotValidManifestForWebApp,
             result_code_.value());
-  absl::optional<AppId> id = registrar().LookupExternalAppId(url);
+  absl::optional<webapps::AppId> id = registrar().LookupExternalAppId(url);
   ASSERT_FALSE(id.has_value());
 }
 
@@ -756,7 +764,8 @@
           }));
   run_loop.Run();
 
-  absl::optional<AppId> app_id = registrar().FindAppWithUrlInScope(app_url);
+  absl::optional<webapps::AppId> app_id =
+      registrar().FindAppWithUrlInScope(app_url);
   DCHECK(app_id.has_value());
   EXPECT_EQ(registrar().GetAppDisplayMode(*app_id), DisplayMode::kBrowser);
   EXPECT_EQ(registrar().GetAppUserDisplayMode(*app_id),
@@ -793,12 +802,14 @@
   auto install_info = std::make_unique<WebAppInstallInfo>();
   install_info->start_url = url;
   install_info->title = u"Test user app";
-  AppId app_id = test::InstallWebApp(profile(), std::move(install_info));
+  webapps::AppId app_id =
+      test::InstallWebApp(profile(), std::move(install_info));
   ASSERT_TRUE(registrar().WasInstalledByUser(app_id));
   ASSERT_FALSE(registrar().HasExternalApp(app_id));
 
   // Install policy app
-  absl::optional<AppId> policy_app_id = ForceInstallWebApp(profile(), url);
+  absl::optional<webapps::AppId> policy_app_id =
+      ForceInstallWebApp(profile(), url);
   ASSERT_EQ(policy_app_id, app_id);
 
   // Uninstall policy app
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
index 679e511..7ea9fea 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
@@ -46,6 +45,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -296,7 +296,7 @@
       auto result =
           externally_managed_app_manager_impl_->GetNextInstallationTaskResult(
               install_url);
-      absl::optional<AppId> app_id;
+      absl::optional<webapps::AppId> app_id;
       if (result.code == webapps::InstallResultCode::kSuccessNewInstall) {
         app_id = GenerateAppIdFromManifestId(
             GenerateManifestIdFromStartUrlOnly(install_url));
@@ -430,7 +430,7 @@
   }
 
   // WebAppCommandScheduler:
-  void RemoveInstallUrl(absl::optional<AppId> app_id,
+  void RemoveInstallUrl(absl::optional<webapps::AppId> app_id,
                         WebAppManagement::Type install_source,
                         const GURL& install_url,
                         webapps::WebappUninstallSource uninstall_source,
@@ -454,7 +454,7 @@
             }));
   }
   void RemoveInstallSource(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppManagement::Type install_source,
       webapps::WebappUninstallSource uninstall_source,
       UninstallJob::Callback callback,
@@ -466,7 +466,7 @@
   }
 
  private:
-  void UnregisterApp(const AppId& app_id) {
+  void UnregisterApp(const webapps::AppId& app_id) {
     auto it = registrar_->registry().find(app_id);
     DCHECK(it != registrar_->registry().end());
     registrar_->registry().erase(it);
@@ -476,7 +476,7 @@
   std::vector<GURL> uninstall_external_web_app_urls_;
   // Maps app URLs to the id of the app that would have been uninstalled for
   // that url and the result of trying to uninstall it.
-  std::map<GURL, std::pair<AppId, webapps::UninstallResultCode>>
+  std::map<GURL, std::pair<webapps::AppId, webapps::UninstallResultCode>>
       next_uninstall_external_web_app_results_;
 };
 
@@ -1507,7 +1507,8 @@
     EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
   }
 
-  absl::optional<AppId> app_id = registrar().LookupExternalAppId(kFooWebAppUrl);
+  absl::optional<webapps::AppId> app_id =
+      registrar().LookupExternalAppId(kFooWebAppUrl);
   if (app_id.has_value()) {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
     update->DeleteApp(app_id.value());
@@ -1741,7 +1742,7 @@
 
   // Reinstall placeholder
   {
-    AppId app_id = GenerateAppIdFromManifestId(
+    webapps::AppId app_id = GenerateAppIdFromManifestId(
         GenerateManifestIdFromStartUrlOnly(kFooWebAppUrl));
     install_options.wait_for_windows_closed = true;
     externally_managed_app_manager_impl().SetNextInstallationTaskResult(
@@ -1749,7 +1750,7 @@
         /*did_install_placeholder=*/false);
     ui_manager().SetNumWindowsForApp(app_id, 1);
 
-    base::MockRepeatingCallback<void(AppId)> callback;
+    base::MockRepeatingCallback<void(webapps::AppId)> callback;
     EXPECT_CALL(callback, Run(app_id)).WillOnce(::testing::Invoke([&]() {
       ui_manager().SetNumWindowsForApp(app_id, 0);
     }));
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
index 565e012..718b97c3 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
@@ -90,7 +90,7 @@
         base::BindLambdaForTesting(
             [this](const GURL& app_url,
                    ExternalInstallSource install_source) -> bool {
-              absl::optional<AppId> app_id =
+              absl::optional<webapps::AppId> app_id =
                   app_registrar().LookupExternalAppId(app_url);
               if (app_id.has_value()) {
                 ScopedRegistryUpdate update =
@@ -133,7 +133,7 @@
               const std::vector<GURL>& installed_app_urls) {
     EXPECT_EQ(deduped_install_count, deduped_install_count_);
     EXPECT_EQ(deduped_uninstall_count, deduped_uninstall_count_);
-    base::flat_map<AppId, base::flat_set<GURL>> apps =
+    base::flat_map<webapps::AppId, base::flat_set<GURL>> apps =
         app_registrar().GetExternallyInstalledApps(
             ExternalInstallSource::kInternalDefault);
     std::vector<GURL> urls;
@@ -372,9 +372,9 @@
         provider().web_contents_manager());
   }
 
-  AppId PopulateBasicInstallPageWithManifest(GURL install_url,
-                                             GURL manifest_url,
-                                             GURL start_url) {
+  webapps::AppId PopulateBasicInstallPageWithManifest(GURL install_url,
+                                                      GURL manifest_url,
+                                                      GURL start_url) {
     auto& install_page_state =
         web_contents_manager().GetOrCreatePageState(install_url);
     install_page_state.url_load_result = WebAppUrlLoaderResult::kUrlLoaded;
@@ -433,7 +433,7 @@
       GURL("https://www.example.com/nested/install_url.html");
   const GURL kManifestUrl = GURL("https://www.example.com/manifest.json");
 
-  AppId app_id = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl, kStartUrl);
 
   SynchronizeFuture result;
@@ -465,9 +465,9 @@
       GURL("https://www.example.com/nested/install_url2.html");
   const GURL kManifestUrl = GURL("https://www.example.com/manifest.json");
 
-  AppId app_id = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl1, kManifestUrl, kStartUrl);
-  AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl2, kManifestUrl, kStartUrl);
   EXPECT_EQ(app_id, app_id2);
 
@@ -516,9 +516,9 @@
       GURL("https://www.example.com/nested/install_url2.html");
   const GURL kManifestUrl = GURL("https://www.example.com/manifest.json");
 
-  AppId app_id = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl1, kManifestUrl, kStartUrl);
-  AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl2, kManifestUrl, kStartUrl);
   EXPECT_EQ(app_id, app_id2);
 
@@ -623,9 +623,9 @@
       GURL("https://www.example.com/nested/install_url2.html");
   const GURL kManifestUrl = GURL("https://www.example.com/manifest.json");
 
-  AppId app_id = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl, kStartUrl);
-  AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl2, kManifestUrl, kStartUrl);
   EXPECT_EQ(app_id, app_id2);
 
@@ -687,7 +687,7 @@
       GURL("https://www.example.com/nested/install_url.html");
   const GURL kManifestUrl = GURL("https://www.example.com/manifest.json");
 
-  AppId app_id = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl, kStartUrl);
 
   {
@@ -699,7 +699,7 @@
     auto install_info = std::make_unique<WebAppInstallInfo>();
     install_info->start_url = kStartUrl;
     install_info->title = u"Test user app";
-    absl::optional<AppId> user_app_id =
+    absl::optional<webapps::AppId> user_app_id =
         test::InstallWebApp(profile(), std::move(install_info));
 
     ASSERT_TRUE(user_app_id.has_value());
@@ -747,8 +747,9 @@
       ExternalInstallSource::kExternalPolicy, result.GetCallback());
   ASSERT_TRUE(result.Wait());
 
-  // The AppId should be created from teh install url.
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, kInstallUrl);
+  // The webapps::AppId should be created from teh install url.
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, kInstallUrl);
 
   // Install should succeed.
   std::map<GURL, ExternallyManagedAppManager::InstallResult> install_results =
@@ -793,8 +794,9 @@
       ExternalInstallSource::kExternalPolicy, result.GetCallback());
   ASSERT_TRUE(result.Wait());
 
-  // The AppId should be created from teh install url.
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, kInstallUrl);
+  // The webapps::AppId should be created from teh install url.
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, kInstallUrl);
 
   // Install should succeed.
   std::map<GURL, ExternallyManagedAppManager::InstallResult> install_results =
@@ -840,14 +842,14 @@
     ASSERT_TRUE(result.Wait());
   }
 
-  AppId placeholder_app_id =
+  webapps::AppId placeholder_app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, kInstallUrl);
 
   auto app_ids = provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(placeholder_app_id));
 
   // Replace the redirect with an app that resolves.
-  AppId app_id = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl, kStartUrl);
 
   // The placeholder app should be uninstalled & the real one installed.
@@ -890,14 +892,14 @@
     ASSERT_TRUE(result.Wait());
   }
 
-  AppId placeholder_app_id =
+  webapps::AppId placeholder_app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, kInstallUrl);
 
   auto app_ids = provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(placeholder_app_id));
 
   // Replace the redirect with an app that resolves.
-  AppId app_id = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl, kStartUrl);
 
   ExternalInstallOptions options = template_options;
@@ -923,7 +925,7 @@
       GURL(), mojom::UserDisplayMode::kStandalone,
       ExternalInstallSource::kExternalPolicy);
 
-  AppId app_id1 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id1 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl1, kStartUrl1);
 
   {
@@ -940,7 +942,7 @@
   auto app_ids = provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id1));
 
-  AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl2, kStartUrl2);
 
   {
@@ -969,7 +971,7 @@
       GURL(), mojom::UserDisplayMode::kStandalone,
       ExternalInstallSource::kExternalPolicy);
 
-  AppId app_id1 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id1 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl1, kStartUrl1);
 
   {
@@ -986,7 +988,7 @@
   auto app_ids = provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id1));
 
-  AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl2, kStartUrl2);
 
   {
@@ -1016,7 +1018,7 @@
       GURL(), mojom::UserDisplayMode::kStandalone,
       ExternalInstallSource::kExternalPolicy);
 
-  AppId app_id1 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id1 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl1, kStartUrl1);
 
   {
@@ -1032,7 +1034,7 @@
   auto app_ids = provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id1));
 
-  AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
+  webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
       kInstallUrl, kManifestUrl2, kStartUrl2);
 
   {
@@ -1070,8 +1072,9 @@
   page_state.redirection_url =
       GURL("https://www.otherorigin.com/redirect.html");
 
-  AppId app_at_install_url = web_contents_manager().CreateBasicInstallPageState(
-      kInstallUrl2, kManifestUrl, kInstallUrl1);
+  webapps::AppId app_at_install_url =
+      web_contents_manager().CreateBasicInstallPageState(
+          kInstallUrl2, kManifestUrl, kInstallUrl1);
 
   {
     ExternalInstallOptions options = template_options;
@@ -1143,8 +1146,9 @@
   page_state.redirection_url =
       GURL("https://www.otherorigin.com/redirect.html");
 
-  AppId app_at_install_url = web_contents_manager().CreateBasicInstallPageState(
-      kInstallUrl2, kManifestUrl, /*start_url=*/kInstallUrl1);
+  webapps::AppId app_at_install_url =
+      web_contents_manager().CreateBasicInstallPageState(
+          kInstallUrl2, kManifestUrl, /*start_url=*/kInstallUrl1);
 
   SynchronizeFuture result;
   provider().externally_managed_app_manager().SynchronizeInstalledApps(
@@ -1215,8 +1219,9 @@
   page_state.redirection_url =
       GURL("https://www.otherorigin.com/redirect.html");
 
-  AppId app_at_install_url = web_contents_manager().CreateBasicInstallPageState(
-      kInstallUrl2, kManifestUrl1, kInstallUrl1);
+  webapps::AppId app_at_install_url =
+      web_contents_manager().CreateBasicInstallPageState(
+          kInstallUrl2, kManifestUrl1, kInstallUrl1);
 
   {
     ExternalInstallOptions options = template_options;
@@ -1269,8 +1274,9 @@
                                               /*install_urls=*/{kInstallUrl2},
                                               /*additional_policy_ids=*/{}))));
   // Phase 2 - undo the redirection, and point to start url.
-  AppId app_at_start_url = web_contents_manager().CreateBasicInstallPageState(
-      kInstallUrl1, kManifestUrl2, kStartUrl1);
+  webapps::AppId app_at_start_url =
+      web_contents_manager().CreateBasicInstallPageState(
+          kInstallUrl1, kManifestUrl2, kStartUrl1);
 
   {
     ExternalInstallOptions options = template_options;
diff --git a/chrome/browser/web_applications/generated_icon_fix_manager.cc b/chrome/browser/web_applications/generated_icon_fix_manager.cc
index 29e9d36d..7c3618b 100644
--- a/chrome/browser/web_applications/generated_icon_fix_manager.cc
+++ b/chrome/browser/web_applications/generated_icon_fix_manager.cc
@@ -50,7 +50,8 @@
             if (!manager) {
               return;
             }
-            for (const AppId& app_id : all_apps_lock.registrar().GetAppIds()) {
+            for (const webapps::AppId& app_id :
+                 all_apps_lock.registrar().GetAppIds()) {
               manager->MaybeScheduleFix(all_apps_lock, app_id);
             }
             // TODO(crbug.com/1216965): Record the count of how many fixes were
@@ -61,7 +62,7 @@
 
 GeneratedIconFixScheduleDecision GeneratedIconFixManager::MaybeScheduleFix(
     WithAppResources& resources,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   CHECK(IsEnabled());
 
   GeneratedIconFixScheduleDecision decision =
@@ -84,7 +85,7 @@
 
 GeneratedIconFixScheduleDecision GeneratedIconFixManager::MakeScheduleDecision(
     const WebAppRegistrar& registrar,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   const WebApp* app = registrar.GetAppById(app_id);
   if (!app || !app->IsSynced()) {
     return GeneratedIconFixScheduleDecision::kNoApp;
@@ -112,7 +113,7 @@
              : GeneratedIconFixScheduleDecision::kSchedule;
 }
 
-void GeneratedIconFixManager::FixCompleted(const AppId& app_id,
+void GeneratedIconFixManager::FixCompleted(const webapps::AppId& app_id,
                                            GeneratedIconFixResult result) {
   CHECK_EQ(scheduled_fixes_.erase(app_id), 1u);
 
diff --git a/chrome/browser/web_applications/generated_icon_fix_manager.h b/chrome/browser/web_applications/generated_icon_fix_manager.h
index a34bc96e..e3cdb83 100644
--- a/chrome/browser/web_applications/generated_icon_fix_manager.h
+++ b/chrome/browser/web_applications/generated_icon_fix_manager.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/commands/generated_icon_fix_command.h"
 #include "chrome/browser/web_applications/locks/with_app_resources.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
@@ -39,16 +40,17 @@
   // TODO(crbug.com/1216965): Schedule fixes ten minutes after sync install.
   // TODO(crbug.com/1216965): Schedule fixes on network reconnection.
 
-  const base::flat_set<AppId>& scheduled_fixes_for_testing() const {
+  const base::flat_set<webapps::AppId>& scheduled_fixes_for_testing() const {
     return scheduled_fixes_;
   }
 
-  base::OnceCallback<void(const AppId&, GeneratedIconFixScheduleDecision)>&
+  base::OnceCallback<void(const webapps::AppId&,
+                          GeneratedIconFixScheduleDecision)>&
   maybe_schedule_callback_for_testing() {
     return maybe_schedule_callback_for_testing_;
   }
 
-  base::OnceCallback<void(const AppId&, GeneratedIconFixResult)>&
+  base::OnceCallback<void(const webapps::AppId&, GeneratedIconFixResult)>&
   fix_completed_callback_for_testing() {
     return fix_completed_callback_for_testing_;
   }
@@ -56,20 +58,23 @@
   absl::optional<base::Time>& time_for_testing() { return time_for_testing_; }
 
  private:
-  GeneratedIconFixScheduleDecision MaybeScheduleFix(WithAppResources& resources,
-                                                    const AppId& app_id);
+  GeneratedIconFixScheduleDecision MaybeScheduleFix(
+      WithAppResources& resources,
+      const webapps::AppId& app_id);
   GeneratedIconFixScheduleDecision MakeScheduleDecision(
       const WebAppRegistrar& registrar,
-      const AppId& app_id);
-  void FixCompleted(const AppId& app_id, GeneratedIconFixResult result);
+      const webapps::AppId& app_id);
+  void FixCompleted(const webapps::AppId& app_id,
+                    GeneratedIconFixResult result);
 
   raw_ptr<WebAppProvider> provider_ = nullptr;
 
-  base::flat_set<AppId> scheduled_fixes_;
+  base::flat_set<webapps::AppId> scheduled_fixes_;
 
-  base::OnceCallback<void(const AppId&, GeneratedIconFixScheduleDecision)>
+  base::OnceCallback<void(const webapps::AppId&,
+                          GeneratedIconFixScheduleDecision)>
       maybe_schedule_callback_for_testing_;
-  base::OnceCallback<void(const AppId&, GeneratedIconFixResult)>
+  base::OnceCallback<void(const webapps::AppId&, GeneratedIconFixResult)>
       fix_completed_callback_for_testing_;
   absl::optional<base::Time> time_for_testing_;
 
diff --git a/chrome/browser/web_applications/install_bounce_metric.cc b/chrome/browser/web_applications/install_bounce_metric.cc
index 02c015b..01d3a8b 100644
--- a/chrome/browser/web_applications/install_bounce_metric.cc
+++ b/chrome/browser/web_applications/install_bounce_metric.cc
@@ -53,7 +53,7 @@
 
 absl::optional<InstallMetrics> ParseInstallMetricsFromPrefs(
     const PrefService* pref_service,
-    const web_app::AppId& app_id) {
+    const webapps::AppId& app_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   const base::Value::Dict& ids_to_metrics =
@@ -78,7 +78,7 @@
 
 void WriteInstallMetricsToPrefs(const InstallMetrics& install_metrics,
                                 PrefService* pref_service,
-                                const web_app::AppId& app_id) {
+                                const webapps::AppId& app_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   base::Value::Dict dict;
   dict.Set(kInstallTimestamp, SerializeTime(install_metrics.timestamp));
@@ -102,14 +102,14 @@
 
 void RecordWebAppInstallationTimestamp(
     PrefService* pref_service,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappInstallSource install_source) {
   WriteInstallMetricsToPrefs(InstallMetrics{GetTime(), install_source},
                              pref_service, app_id);
 }
 
 void RecordWebAppUninstallation(PrefService* pref_service,
-                                const AppId& app_id) {
+                                const webapps::AppId& app_id) {
   absl::optional<InstallMetrics> metrics =
       ParseInstallMetricsFromPrefs(pref_service, app_id);
   if (!metrics)
diff --git a/chrome/browser/web_applications/install_bounce_metric.h b/chrome/browser/web_applications/install_bounce_metric.h
index d7e5b9a..2d5b09ab 100644
--- a/chrome/browser/web_applications/install_bounce_metric.h
+++ b/chrome/browser/web_applications/install_bounce_metric.h
@@ -8,6 +8,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class PrefService;
@@ -21,10 +22,11 @@
 
 void RecordWebAppInstallationTimestamp(
     PrefService* pref_service,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappInstallSource install_source);
 
-void RecordWebAppUninstallation(PrefService* pref_service, const AppId& app_id);
+void RecordWebAppUninstallation(PrefService* pref_service,
+                                const webapps::AppId& app_id);
 
 }  // namespace web_app
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/garbage_collect_storage_partitions_command_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/garbage_collect_storage_partitions_command_browsertest.cc
index ea65fe0..4d2cccd1 100644
--- a/chrome/browser/web_applications/isolated_web_apps/garbage_collect_storage_partitions_command_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/garbage_collect_storage_partitions_command_browsertest.cc
@@ -22,13 +22,13 @@
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
 #include "chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/pref_test_utils.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/storage_partition_config.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/web_applications/isolated_web_apps/get_isolated_web_app_browsing_data_command.cc b/chrome/browser/web_applications/isolated_web_apps/get_isolated_web_app_browsing_data_command.cc
index 07b3166..20e6b3a 100644
--- a/chrome/browser/web_applications/isolated_web_apps/get_isolated_web_app_browsing_data_command.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/get_isolated_web_app_browsing_data_command.cc
@@ -18,9 +18,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_observer.h"
 #include "chrome/browser/web_applications/locks/all_apps_lock.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/browsing_data/content/browsing_data_model.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/storage_partition_config.h"
 #include "ui/base/models/tree_model.h"
 #include "url/origin.h"
@@ -163,7 +163,7 @@
   pending_task_count_++;
   const WebAppRegistrar& web_app_registrar = lock_->registrar();
   for (const WebApp& web_app : web_app_registrar.GetApps()) {
-    const AppId& app_id = web_app.app_id();
+    const webapps::AppId& app_id = web_app.app_id();
     if (!web_app_registrar.IsIsolated(app_id)) {
       continue;
     }
diff --git a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.cc b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.cc
index ee9f9d7..b546684 100644
--- a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.cc
@@ -31,7 +31,6 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
@@ -42,6 +41,7 @@
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_logging.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -209,7 +209,7 @@
 }
 
 void InstallIsolatedWebAppCommand::OnFinalizeInstall(
-    const AppId& unused_app_id,
+    const webapps::AppId& unused_app_id,
     webapps::InstallResultCode install_result_code,
     OsHooksErrors unused_os_hooks_errors) {
   if (install_result_code == webapps::InstallResultCode::kSuccessNewInstall) {
diff --git a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.h b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.h
index 53b4c5e1..23c1274 100644
--- a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.h
+++ b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.h
@@ -29,6 +29,7 @@
 #include "components/keep_alive_registry/scoped_keep_alive.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_logging.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 
@@ -169,7 +170,7 @@
       WebAppInstallInfo install_info);
 
   void FinalizeInstall(WebAppInstallInfo info);
-  void OnFinalizeInstall(const AppId& unused_app_id,
+  void OnFinalizeInstall(const webapps::AppId& unused_app_id,
                          webapps::InstallResultCode install_result_code,
                          OsHooksErrors unused_os_hooks_errors);
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_from_command_line_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_from_command_line_browsertest.cc
index e950203..5ff5d53c 100644
--- a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_from_command_line_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_from_command_line_browsertest.cc
@@ -19,12 +19,12 @@
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/web_app.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -89,7 +89,7 @@
 IN_PROC_BROWSER_TEST_F(InstallIsolatedWebAppFromCommandLineFromUrlBrowserTest,
                        AppFromCommandLineIsInstalled) {
   WebAppTestInstallObserver observer(browser()->profile());
-  AppId id = observer.BeginListeningAndWait();
+  webapps::AppId id = observer.BeginListeningAndWait();
 
   EXPECT_THAT(GetWebAppRegistrar().IsInstalled(id), IsTrue());
   EXPECT_THAT(GetWebAppRegistrar().GetAppById(id),
@@ -140,7 +140,7 @@
 IN_PROC_BROWSER_TEST_F(InstallIsolatedWebAppFromCommandLineFromFileBrowserTest,
                        AppFromCommandLineIsInstalled) {
   WebAppTestInstallObserver observer(browser()->profile());
-  AppId id = observer.BeginListeningAndWait();
+  webapps::AppId id = observer.BeginListeningAndWait();
 
   ASSERT_TRUE(bundle_id_);
   ASSERT_EQ(
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command.cc
index 18859334..52a339f 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command.cc
@@ -32,7 +32,6 @@
 #include "chrome/browser/web_applications/locks/app_lock.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
@@ -43,6 +42,7 @@
 #include "chrome/browser/web_applications/web_contents/web_contents_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -241,7 +241,7 @@
 }
 
 void IsolatedWebAppApplyUpdateCommand::OnFinalized(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::InstallResultCode update_result_code,
     OsHooksErrors unused_os_hooks_errors) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command.h b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command.h
index b9d3c78..0346d47 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command.h
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command.h
@@ -27,6 +27,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 
@@ -151,7 +152,7 @@
 
   void Finalize(WebAppInstallInfo info);
 
-  void OnFinalized(const AppId& app_id,
+  void OnFinalized(const webapps::AppId& app_id,
                    webapps::InstallResultCode update_result_code,
                    OsHooksErrors os_hooks_errors);
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command_unittest.cc
index d0ce205..0519d31 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_apply_update_command_unittest.cc
@@ -347,7 +347,7 @@
 TEST_F(IsolatedWebAppApplyUpdateCommandTest, FailsIfInstallFinalizerFails) {
   class FailingUpdateFinalizer : public WebAppInstallFinalizer {
    public:
-    explicit FailingUpdateFinalizer(AppId app_id)
+    explicit FailingUpdateFinalizer(webapps::AppId app_id)
         : WebAppInstallFinalizer(nullptr), app_id_(std::move(app_id)) {}
 
     void FinalizeUpdate(const WebAppInstallInfo& web_app_info,
@@ -357,7 +357,7 @@
     }
 
    private:
-    AppId app_id_;
+    webapps::AppId app_id_;
   };
 
   fake_provider().SetInstallFinalizer(
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_browsing_data_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_browsing_data_browsertest.cc
index 60e0715..582dc1f 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_browsing_data_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_browsing_data_browsertest.cc
@@ -26,7 +26,6 @@
 #include "chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
@@ -34,6 +33,7 @@
 #include "components/browsing_data/core/browsing_data_utils.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/services/storage/public/mojom/local_storage_control.mojom.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browsing_data_filter_builder.h"
 #include "content/public/browser/browsing_data_remover.h"
 #include "content/public/browser/render_frame_host.h"
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_error_page_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_error_page_browsertest.cc
index 9390029a..6aa334d 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_error_page_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_error_page_browsertest.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
 #include "chrome/browser/web_applications/test/web_app_icon_waiter.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/url_loader_interceptor.h"
@@ -44,7 +44,7 @@
   }
 
   // Navigates IWA and fails with error
-  Browser* LaunchIwaAndFailWithError(const AppId& app_id,
+  Browser* LaunchIwaAndFailWithError(const webapps::AppId& app_id,
                                      const url::Origin& iwa_origin,
                                      net::Error error_code) {
     GURL starting_url = iwa_origin.GetURL().Resolve("/index.html");
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_prepare_and_store_update_command.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_prepare_and_store_update_command.cc
index 0dba440..3a85786a 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_prepare_and_store_update_command.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_prepare_and_store_update_command.cc
@@ -33,7 +33,6 @@
 #include "chrome/browser/web_applications/isolated_web_apps/pending_install_info.h"
 #include "chrome/browser/web_applications/locks/app_lock.h"
 #include "chrome/browser/web_applications/web_app.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
@@ -42,6 +41,7 @@
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
 #include "chrome/browser/web_applications/web_contents/web_contents_manager.h"
 #include "components/prefs/pref_service.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_prepare_and_store_update_command.h b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_prepare_and_store_update_command.h
index 1026080e..18d6c4d7 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_prepare_and_store_update_command.h
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_prepare_and_store_update_command.h
@@ -25,6 +25,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_waiter_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_waiter_unittest.cc
index 893fe44..5d9277d 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_waiter_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_waiter_unittest.cc
@@ -52,7 +52,7 @@
                                          fake_provider().ui_manager());
   EXPECT_EQ(CountProfileKeepAlives(profile()), 1ul);
 
-  base::MockRepeatingCallback<void(AppId)> callback;
+  base::MockRepeatingCallback<void(webapps::AppId)> callback;
   EXPECT_CALL(callback, Run(url_info_.app_id()))
       .WillOnce(::testing::Invoke(
           [&]() { ui_manager().SetNumWindowsForApp(url_info_.app_id(), 0); }));
@@ -79,7 +79,7 @@
   IsolatedWebAppUpdateApplyWaiter waiter(url_info_,
                                          fake_provider().ui_manager());
 
-  base::MockRepeatingCallback<void(AppId)> callback;
+  base::MockRepeatingCallback<void(webapps::AppId)> callback;
   EXPECT_CALL(callback, Run(url_info_.app_id()));
   ui_manager().SetOnNotifyOnAllAppWindowsClosedCallback(callback.Get());
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.cc
index b0bb9c1b..2ab04e6 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.cc
@@ -22,9 +22,9 @@
 #include "chrome/browser/web_applications/isolated_web_apps/update_manifest/update_manifest_fetcher.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/net_errors.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.h b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.h
index 6ee39df0..025cac0a 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.h
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "components/webapps/common/web_app_id.h"
 #include "net/base/net_errors.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.cc
index c26bfbf..ab131c1 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.cc
@@ -36,7 +36,6 @@
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
 #include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_external_install_options.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -46,6 +45,7 @@
 #include "components/keep_alive_registry/scoped_keep_alive.h"
 #include "components/prefs/pref_service.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/isolated_web_apps_policy.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -175,13 +175,13 @@
 
 bool IsolatedWebAppUpdateManager::IsUpdateBeingApplied(
     base::PassKey<IsolatedWebAppURLLoaderFactory>,
-    const AppId app_id) const {
+    const webapps::AppId app_id) const {
   return task_queue_.IsUpdateApplyTaskQueued(app_id);
 }
 
 void IsolatedWebAppUpdateManager::PrioritizeUpdateAndWait(
     base::PassKey<IsolatedWebAppURLLoaderFactory>,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure callback) {
   bool task_has_started =
       task_queue_.EnsureQueuedUpdateApplyTaskHasStarted(app_id);
@@ -201,12 +201,13 @@
   automatic_updates_enabled_ = automatic_updates_enabled;
 }
 
-void IsolatedWebAppUpdateManager::OnWebAppInstalled(const AppId& app_id) {
+void IsolatedWebAppUpdateManager::OnWebAppInstalled(
+    const webapps::AppId& app_id) {
   MaybeStartUpdateDiscoveryTimer();
 }
 
 void IsolatedWebAppUpdateManager::OnWebAppUninstalled(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   update_apply_waiters_.erase(app_id);
   task_queue_.ClearNonStartedTasksOfApp(app_id);
@@ -306,7 +307,7 @@
 
 void IsolatedWebAppUpdateManager::CreateUpdateApplyWaiter(
     const IsolatedWebAppUrlInfo& url_info) {
-  const AppId& app_id = url_info.app_id();
+  const webapps::AppId& app_id = url_info.app_id();
   if (update_apply_waiters_.contains(app_id)) {
     return;
   }
@@ -405,7 +406,7 @@
 }
 
 bool IsolatedWebAppUpdateManager::TaskQueue::
-    EnsureQueuedUpdateApplyTaskHasStarted(const AppId& app_id) {
+    EnsureQueuedUpdateApplyTaskHasStarted(const webapps::AppId& app_id) {
   auto task_it =
       base::ranges::find_if(update_apply_tasks_, [&app_id](const auto& task) {
         return task->url_info().app_id() == app_id;
@@ -421,7 +422,7 @@
 }
 
 void IsolatedWebAppUpdateManager::TaskQueue::ClearNonStartedTasksOfApp(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   base::EraseIf(update_discovery_tasks_, [&app_id](const auto& task) {
     return !task->has_started() && task->url_info().app_id() == app_id;
   });
@@ -449,7 +450,7 @@
 }
 
 bool IsolatedWebAppUpdateManager::TaskQueue::IsUpdateApplyTaskQueued(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   return base::ranges::any_of(update_apply_tasks_, [&app_id](const auto& task) {
     return task->url_info().app_id() == app_id;
   });
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.h b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.h
index a602871..29383e5 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.h
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager.h
@@ -26,6 +26,7 @@
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_discovery_task.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
+#include "components/webapps/common/web_app_id.h"
 
 class GURL;
 class Profile;
@@ -80,7 +81,7 @@
   // `IsolatedWebAppURLLoaderFactory`. If you have a different use case, please
   // talk to iwa-dev@chromium.org first.
   bool IsUpdateBeingApplied(base::PassKey<IsolatedWebAppURLLoaderFactory>,
-                            const AppId app_id) const;
+                            const webapps::AppId app_id) const;
 
   // Starts an already scheduled update apply task for the provided `app_id`, if
   // it is queued but not already running. This happens regardless of whether
@@ -94,15 +95,15 @@
   // `IsolatedWebAppURLLoaderFactory`. If you have a different use case, please
   // talk to iwa-dev@chromium.org first.
   void PrioritizeUpdateAndWait(base::PassKey<IsolatedWebAppURLLoaderFactory>,
-                               const AppId& app_id,
+                               const webapps::AppId& app_id,
                                base::OnceClosure callback);
 
   void SetEnableAutomaticUpdatesForTesting(bool automatic_updates_enabled);
 
   // `WebAppInstallManagerObserver`:
-  void OnWebAppInstalled(const AppId& app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& app_id) override;
   void OnWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
 
   const base::RepeatingTimer& GetUpdateDiscoveryTimerForTesting() const {
@@ -141,7 +142,7 @@
     // it immediately, even if other tasks are currently running. Returns
     // `false` if a task for this `app_id` is neither queued nor running,
     // returns `true` otherwise.
-    bool EnsureQueuedUpdateApplyTaskHasStarted(const AppId& app_id);
+    bool EnsureQueuedUpdateApplyTaskHasStarted(const webapps::AppId& app_id);
 
     // Removes all tasks for the provided `app_id` that haven't yet started from
     // the queue.
@@ -149,13 +150,13 @@
     // TODO(crbug.com/1444407): Ideally, we'd also cancel tasks that have
     // already started, especially update discovery tasks, but the task
     // implementation currently does not support cancellation of ongoing tasks.
-    void ClearNonStartedTasksOfApp(const AppId& app_id);
+    void ClearNonStartedTasksOfApp(const webapps::AppId& app_id);
 
     // Starts the next task if no task is currently running. Will prioritize
     // update apply over update discovery tasks.
     void MaybeStartNextTask();
 
-    bool IsUpdateApplyTaskQueued(const AppId& app_id) const;
+    bool IsUpdateApplyTaskQueued(const webapps::AppId& app_id) const;
 
    private:
     void StartUpdateDiscoveryTask(IsolatedWebAppUpdateDiscoveryTask* task_ptr);
@@ -226,12 +227,14 @@
 
   TaskQueue task_queue_;
 
-  base::flat_map<AppId, std::unique_ptr<IsolatedWebAppUpdateApplyWaiter>>
+  base::flat_map<webapps::AppId,
+                 std::unique_ptr<IsolatedWebAppUpdateApplyWaiter>>
       update_apply_waiters_;
 
   // Callbacks that are run once an update apply task for a given app id has
   // finished (successfully or unsuccessfully).
-  base::flat_map<AppId, std::unique_ptr<base::OnceCallbackList<void()>>>
+  base::flat_map<webapps::AppId,
+                 std::unique_ptr<base::OnceCallbackList<void()>>>
       on_update_finished_callbacks_;
 
   base::ScopedObservation<WebAppInstallManager, WebAppInstallManagerObserver>
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager_unittest.cc
index a292153a..8672ae2 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_manager_unittest.cc
@@ -581,8 +581,8 @@
   // Uninstall the other IWA whose update discovery task has not yet started.
   GURL pending_url =
       profile_url_loader_factory().GetPendingRequest(0)->request.url;
-  AppId iwa_to_keep;
-  AppId iwa_to_uninstall;
+  webapps::AppId iwa_to_keep;
+  webapps::AppId iwa_to_uninstall;
   if (pending_url == iwa_info1_->update_manifest_url) {
     iwa_to_keep = iwa_info1_->url_info.app_id();
     iwa_to_uninstall = iwa_info2_->url_info.app_id();
@@ -678,13 +678,13 @@
           &future, &base::test::TestFuture<IsolatedWebAppUrlInfo>::SetValue)));
   fake_ui_manager().SetNumWindowsForApp(iwa_info1_->url_info.app_id(), 0);
   fake_ui_manager().SetNumWindowsForApp(iwa_info2_->url_info.app_id(), 0);
-  AppId iwa_to_keep = future.Take().app_id();
+  webapps::AppId iwa_to_keep = future.Take().app_id();
 
   EXPECT_THAT(UpdateApplyTasks(), SizeIs(2));  // two tasks should be queued
   EXPECT_THAT(UpdateApplyLog(), IsEmpty());    // no task should have finished
 
   // Uninstall the other IWA whose update apply task has not yet started.
-  AppId iwa_to_uninstall;
+  webapps::AppId iwa_to_uninstall;
   if (iwa_to_keep == iwa_info1_->url_info.app_id()) {
     iwa_to_uninstall = iwa_info2_->url_info.app_id();
   } else if (iwa_to_keep == iwa_info2_->url_info.app_id()) {
@@ -737,17 +737,17 @@
   EXPECT_THAT(update_manager().GetUpdateDiscoveryTimerForTesting().IsRunning(),
               IsFalse());
 
-  AppId non_iwa_id =
+  webapps::AppId non_iwa_id =
       test::InstallDummyWebApp(profile(), "non-iwa", GURL("https://a"));
   EXPECT_THAT(update_manager().GetUpdateDiscoveryTimerForTesting().IsRunning(),
               IsFalse());
 
-  AppId iwa_app_id1 = AddDummyIsolatedAppToRegistry(
+  webapps::AppId iwa_app_id1 = AddDummyIsolatedAppToRegistry(
       profile(), GURL("isolated-app://a"), "iwa1");
   EXPECT_THAT(update_manager().GetUpdateDiscoveryTimerForTesting().IsRunning(),
               IsTrue());
 
-  AppId iwa_app_id2 = AddDummyIsolatedAppToRegistry(
+  webapps::AppId iwa_app_id2 = AddDummyIsolatedAppToRegistry(
       profile(), GURL("isolated-app://b"), "iwa2");
   EXPECT_THAT(update_manager().GetUpdateDiscoveryTimerForTesting().IsRunning(),
               IsTrue());
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.cc
index 4817937..3596062 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.cc
@@ -132,7 +132,7 @@
   return origin_;
 }
 
-const AppId& IsolatedWebAppUrlInfo::app_id() const {
+const webapps::AppId& IsolatedWebAppUrlInfo::app_id() const {
   return app_id_;
 }
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h
index 581a91f7..c9abdd7 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_location.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -52,9 +53,9 @@
   // Returns the origin of the IWA that this URL refers to.
   const url::Origin& origin() const;
 
-  // Returns the AppId that should be used when installing the app hosted at
-  // this URL.
-  const AppId& app_id() const;
+  // Returns the webapps::AppId that should be used when installing the app
+  // hosted at this URL.
+  const webapps::AppId& app_id() const;
 
   // Returns the Web Bundle ID of the IWA that this URL refers to.
   const web_package::SignedWebBundleId& web_bundle_id() const;
@@ -78,7 +79,7 @@
   std::string partition_domain() const;
 
   url::Origin origin_;
-  AppId app_id_;
+  webapps::AppId app_id_;
   web_package::SignedWebBundleId web_bundle_id_;
 };
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_browsertest.cc
index 4badd9c..ebb09b9 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_browsertest.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -33,6 +32,7 @@
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
 #include "components/web_package/test_support/signed_web_bundles/web_bundle_signer.h"
 #include "components/web_package/web_bundle_builder.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
@@ -63,7 +63,7 @@
 }
 
 std::unique_ptr<WebApp> CreateWebApp(const GURL& start_url) {
-  AppId app_id = GenerateAppId(/*manifest_id=*/"", start_url);
+  webapps::AppId app_id = GenerateAppId(/*manifest_id=*/"", start_url);
   auto web_app = std::make_unique<WebApp>(app_id);
   web_app->SetStartUrl(start_url);
   web_app->SetName("Isolated Web App Example");
@@ -155,7 +155,7 @@
   }
 
   Browser* CreateAppWindow() {
-    AppId app_id = GenerateAppId(/*manifest_id=*/"", kUrl);
+    webapps::AppId app_id = GenerateAppId(/*manifest_id=*/"", kUrl);
 
     return Browser::Create(Browser::CreateParams::CreateForApp(
         GenerateApplicationNameFromAppId(app_id),
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_unittest.cc
index 690c79f2..07968fc2 100644
--- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory_unittest.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/url_constants.h"
@@ -37,6 +36,7 @@
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
 #include "components/web_package/test_support/signed_web_bundles/web_bundle_signer.h"
 #include "components/web_package/web_bundle_builder.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/storage_partition_config.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
@@ -87,7 +87,7 @@
 }
 
 std::unique_ptr<WebApp> CreateWebApp(const GURL& start_url) {
-  AppId app_id = GenerateAppId(/*manifest_id=*/"", start_url);
+  webapps::AppId app_id = GenerateAppId(/*manifest_id=*/"", start_url);
   auto web_app = std::make_unique<WebApp>(app_id);
   web_app->SetName("iwa name");
   web_app->SetStartUrl(start_url);
@@ -286,7 +286,7 @@
   RegisterWebApp(CreateWebApp(kDevAppStartUrl));
 
   // Verify that a PWA is installed at kAppStartUrl's origin.
-  absl::optional<AppId> installed_app =
+  absl::optional<webapps::AppId> installed_app =
       fake_provider().registrar_unsafe().FindInstalledAppWithUrlInScope(
           kDevAppStartUrl);
   EXPECT_THAT(installed_app.has_value(), IsTrue());
@@ -310,7 +310,7 @@
   RegisterWebApp(std::move(iwa));
 
   // Verify that a PWA is installed at kAppStartUrl's origin.
-  absl::optional<AppId> installed_app =
+  absl::optional<webapps::AppId> installed_app =
       fake_provider().registrar_unsafe().FindAppWithUrlInScope(kDevAppStartUrl);
   EXPECT_THAT(installed_app.has_value(), IsTrue());
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc
index d8d2cc3..ee893584 100644
--- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc
@@ -223,7 +223,7 @@
 
   // Wait for the IWA to be installed.
   WebAppTestInstallObserver observer(profile);
-  const AppId id = observer.BeginListeningAndWait();
+  const webapps::AppId id = observer.BeginListeningAndWait();
   ASSERT_EQ(id,
             IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(iwa_bundle_.id)
                 .app_id());
diff --git a/chrome/browser/web_applications/jobs/install_from_info_job.cc b/chrome/browser/web_applications/jobs/install_from_info_job.cc
index 1b7f25f7..122472a 100644
--- a/chrome/browser/web_applications/jobs/install_from_info_job.cc
+++ b/chrome/browser/web_applications/jobs/install_from_info_job.cc
@@ -13,11 +13,11 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -111,7 +111,7 @@
   SignalCompletionAndSelfDestruct(code, OsHooksErrors());
 }
 
-void InstallFromInfoJob::OnInstallCompleted(const AppId& app_id,
+void InstallFromInfoJob::OnInstallCompleted(const webapps::AppId& app_id,
                                             webapps::InstallResultCode code,
                                             OsHooksErrors os_hook_errors) {
   debug_value_.Set("result_code", base::ToString(code));
diff --git a/chrome/browser/web_applications/jobs/install_from_info_job.h b/chrome/browser/web_applications/jobs/install_from_info_job.h
index 54c0a97c..34dd5221 100644
--- a/chrome/browser/web_applications/jobs/install_from_info_job.h
+++ b/chrome/browser/web_applications/jobs/install_from_info_job.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -40,7 +41,7 @@
 class InstallFromInfoJob {
  public:
   using ResultCallback =
-      base::OnceCallback<void(const AppId& app_id,
+      base::OnceCallback<void(const webapps::AppId& app_id,
                               webapps::InstallResultCode code,
                               OsHooksErrors os_hook_errors)>;
 
@@ -60,7 +61,7 @@
  private:
   void Abort(webapps::InstallResultCode code);
 
-  void OnInstallCompleted(const AppId& app_id,
+  void OnInstallCompleted(const webapps::AppId& app_id,
                           webapps::InstallResultCode code,
                           OsHooksErrors os_hooks_errors);
 
@@ -68,8 +69,8 @@
                                        OsHooksErrors os_hook_errors);
 
   const raw_ref<Profile> profile_;
-  const ManifestId manifest_id_;
-  const AppId app_id_;
+  const webapps::ManifestId manifest_id_;
+  const webapps::AppId app_id_;
   const bool overwrite_existing_manifest_fields_;
   const webapps::WebappInstallSource install_surface_;
   absl::optional<WebAppInstallParams> install_params_;
diff --git a/chrome/browser/web_applications/jobs/install_placeholder_job.cc b/chrome/browser/web_applications/jobs/install_placeholder_job.cc
index 97a715e..ddaddace 100644
--- a/chrome/browser/web_applications/jobs/install_placeholder_job.cc
+++ b/chrome/browser/web_applications/jobs/install_placeholder_job.cc
@@ -180,7 +180,7 @@
                      weak_factory_.GetWeakPtr()));
 }
 
-void InstallPlaceholderJob::OnInstallFinalized(const AppId& app_id,
+void InstallPlaceholderJob::OnInstallFinalized(const webapps::AppId& app_id,
                                                webapps::InstallResultCode code,
                                                OsHooksErrors os_hooks_errors) {
   debug_value_.Set("result_code", base::ToString(code));
diff --git a/chrome/browser/web_applications/jobs/install_placeholder_job.h b/chrome/browser/web_applications/jobs/install_placeholder_job.h
index b39d959c..8884f03 100644
--- a/chrome/browser/web_applications/jobs/install_placeholder_job.h
+++ b/chrome/browser/web_applications/jobs/install_placeholder_job.h
@@ -32,7 +32,8 @@
 class InstallPlaceholderJob {
  public:
   using InstallAndReplaceCallback =
-      base::OnceCallback<void(webapps::InstallResultCode code, AppId app_id)>;
+      base::OnceCallback<void(webapps::InstallResultCode code,
+                              webapps::AppId app_id)>;
   InstallPlaceholderJob(Profile* profile,
                         const ExternalInstallOptions& install_options,
                         InstallAndReplaceCallback callback,
@@ -61,12 +62,12 @@
       absl::optional<std::reference_wrapper<const std::vector<SkBitmap>>>
           bitmaps);
 
-  void OnInstallFinalized(const AppId& app_id,
+  void OnInstallFinalized(const webapps::AppId& app_id,
                           webapps::InstallResultCode code,
                           OsHooksErrors os_hooks_errors);
 
   const raw_ref<Profile> profile_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
 
   // `this` must exist within the scope of a WebCommand's
   // SharedWebContentsWithAppLock.
diff --git a/chrome/browser/web_applications/jobs/uninstall/remove_install_source_job.cc b/chrome/browser/web_applications/jobs/uninstall/remove_install_source_job.cc
index f1a0e85..a254ef7 100644
--- a/chrome/browser/web_applications/jobs/uninstall/remove_install_source_job.cc
+++ b/chrome/browser/web_applications/jobs/uninstall/remove_install_source_job.cc
@@ -50,7 +50,7 @@
 RemoveInstallSourceJob::RemoveInstallSourceJob(
     webapps::WebappUninstallSource uninstall_source,
     Profile& profile,
-    AppId app_id,
+    webapps::AppId app_id,
     WebAppManagement::Type install_source)
     : uninstall_source_(uninstall_source),
       profile_(profile),
diff --git a/chrome/browser/web_applications/jobs/uninstall/remove_install_source_job.h b/chrome/browser/web_applications/jobs/uninstall/remove_install_source_job.h
index e199a2b..4c4c6b3 100644
--- a/chrome/browser/web_applications/jobs/uninstall/remove_install_source_job.h
+++ b/chrome/browser/web_applications/jobs/uninstall/remove_install_source_job.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -22,11 +23,11 @@
  public:
   RemoveInstallSourceJob(webapps::WebappUninstallSource uninstall_source,
                          Profile& profile,
-                         AppId app_id,
+                         webapps::AppId app_id,
                          WebAppManagement::Type install_source);
   ~RemoveInstallSourceJob() override;
 
-  const AppId& app_id() const { return app_id_; }
+  const webapps::AppId& app_id() const { return app_id_; }
 
   // UninstallJob:
   void Start(AllAppsLock& lock, Callback callback) override;
@@ -40,7 +41,7 @@
   webapps::WebappUninstallSource uninstall_source_;
   // `this` must be owned by `profile_`.
   raw_ref<Profile> profile_;
-  AppId app_id_;
+  webapps::AppId app_id_;
   WebAppManagement::Type install_source_;
 
   // `this` must be started and run within the scope of a WebAppCommand's
diff --git a/chrome/browser/web_applications/jobs/uninstall/remove_install_url_job.cc b/chrome/browser/web_applications/jobs/uninstall/remove_install_url_job.cc
index c805fa1..edaa984 100644
--- a/chrome/browser/web_applications/jobs/uninstall/remove_install_url_job.cc
+++ b/chrome/browser/web_applications/jobs/uninstall/remove_install_url_job.cc
@@ -25,7 +25,7 @@
 
 MatchingWebAppResult FindMatchingWebApp(
     const WebAppRegistrar& registrar,
-    const absl::optional<AppId>& app_id,
+    const absl::optional<webapps::AppId>& app_id,
     const WebAppManagement::Type& install_source,
     const GURL& install_url) {
   if (app_id.has_value()) {
@@ -74,7 +74,7 @@
 RemoveInstallUrlJob::RemoveInstallUrlJob(
     webapps::WebappUninstallSource uninstall_source,
     Profile& profile,
-    absl::optional<AppId> app_id,
+    absl::optional<webapps::AppId> app_id,
     WebAppManagement::Type install_source,
     GURL install_url)
     : uninstall_source_(uninstall_source),
diff --git a/chrome/browser/web_applications/jobs/uninstall/remove_install_url_job.h b/chrome/browser/web_applications/jobs/uninstall/remove_install_url_job.h
index 10b947e..7aef703e 100644
--- a/chrome/browser/web_applications/jobs/uninstall/remove_install_url_job.h
+++ b/chrome/browser/web_applications/jobs/uninstall/remove_install_url_job.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
@@ -31,7 +32,7 @@
  public:
   RemoveInstallUrlJob(webapps::WebappUninstallSource uninstall_source,
                       Profile& profile,
-                      absl::optional<AppId> app_id,
+                      absl::optional<webapps::AppId> app_id,
                       WebAppManagement::Type install_source,
                       GURL install_url);
   ~RemoveInstallUrlJob() override;
@@ -47,7 +48,7 @@
   webapps::WebappUninstallSource uninstall_source_;
   // `this` must be owned by `profile_`.
   raw_ref<Profile> profile_;
-  absl::optional<AppId> app_id_;
+  absl::optional<webapps::AppId> app_id_;
   WebAppManagement::Type install_source_;
   GURL install_url_;
 
diff --git a/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.cc b/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.cc
index c255a75..5dace68c 100644
--- a/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.cc
+++ b/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.cc
@@ -66,7 +66,7 @@
 RemoveWebAppJob::RemoveWebAppJob(
     webapps::WebappUninstallSource uninstall_source,
     Profile& profile,
-    AppId app_id,
+    webapps::AppId app_id,
     bool is_initial_request)
     : uninstall_source_(uninstall_source),
       profile_(profile),
@@ -214,7 +214,7 @@
                : base::Value());
   {
     base::Value::List list;
-    for (const AppId& sub_app_id : sub_apps_pending_removal_) {
+    for (const webapps::AppId& sub_app_id : sub_apps_pending_removal_) {
       list.Append(sub_app_id);
     }
     dict.Set("sub_apps_pending_removal", std::move(list));
@@ -311,7 +311,7 @@
     return;
   }
 
-  AppId sub_app_id = std::move(sub_apps_pending_removal_.back());
+  webapps::AppId sub_app_id = std::move(sub_apps_pending_removal_.back());
   sub_apps_pending_removal_.pop_back();
 
   sub_job_ = std::make_unique<RemoveInstallSourceJob>(
diff --git a/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.h b/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.h
index 8481545..e6b7b87 100644
--- a/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.h
+++ b/chrome/browser/web_applications/jobs/uninstall/remove_web_app_job.h
@@ -11,6 +11,7 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -27,7 +28,7 @@
   // will be treated as a user uninstall.
   RemoveWebAppJob(webapps::WebappUninstallSource uninstall_source,
                   Profile& profile,
-                  AppId app_id,
+                  webapps::AppId app_id,
                   bool is_initial_request = true);
   ~RemoveWebAppJob() override;
 
@@ -49,7 +50,7 @@
   webapps::WebappUninstallSource uninstall_source_;
   // `this` must be owned by `profile_`.
   raw_ref<Profile> profile_;
-  AppId app_id_;
+  webapps::AppId app_id_;
   bool is_initial_request_;
 
   // `this` must be started and run within the scope of a WebAppCommand's
@@ -66,7 +67,7 @@
   bool has_isolated_storage_ = false;
   absl::optional<webapps::UninstallResultCode> primary_removal_result_;
 
-  std::vector<AppId> sub_apps_pending_removal_;
+  std::vector<webapps::AppId> sub_apps_pending_removal_;
   std::unique_ptr<RemoveInstallSourceJob> sub_job_;
   base::Value::Dict completed_sub_job_debug_dict_;
 
diff --git a/chrome/browser/web_applications/jobs/uninstall/web_app_uninstall_and_replace_job.h b/chrome/browser/web_applications/jobs/uninstall/web_app_uninstall_and_replace_job.h
index da25218..32e8c890 100644
--- a/chrome/browser/web_applications/jobs/uninstall/web_app_uninstall_and_replace_job.h
+++ b/chrome/browser/web_applications/jobs/uninstall/web_app_uninstall_and_replace_job.h
@@ -11,6 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -33,8 +34,8 @@
   WebAppUninstallAndReplaceJob(
       Profile* profile,
       WithAppResources& to_app_lock,
-      const std::vector<AppId>& from_apps_or_extensions,
-      const AppId& to_app,
+      const std::vector<webapps::AppId>& from_apps_or_extensions,
+      const webapps::AppId& to_app,
       base::OnceCallback<void(bool uninstall_triggered)> on_complete);
   ~WebAppUninstallAndReplaceJob();
 
@@ -43,16 +44,16 @@
   base::Value ToDebugValue() const;
 
  private:
-  void MigrateUiAndUninstallApp(const AppId& from_app,
+  void MigrateUiAndUninstallApp(const webapps::AppId& from_app,
                                 base::OnceClosure on_complete);
-  void OnMigrateLauncherState(const AppId& from_app,
+  void OnMigrateLauncherState(const webapps::AppId& from_app,
                               base::OnceClosure on_complete);
   void OnShortcutInfoReceivedSearchShortcutLocations(
-      const AppId& from_app,
+      const webapps::AppId& from_app,
       base::OnceClosure on_complete,
       std::unique_ptr<ShortcutInfo> shortcut_info);
 
-  void OnShortcutLocationGathered(const AppId& from_app,
+  void OnShortcutLocationGathered(const webapps::AppId& from_app,
                                   base::OnceClosure on_complete,
                                   ShortcutLocations locations);
 
@@ -64,8 +65,8 @@
   const raw_ref<Profile> profile_;
   // `this` must exist within the scope of a WebAppCommand's WithAppResources.
   const raw_ref<WithAppResources> to_app_lock_;
-  std::vector<AppId> from_apps_or_extensions_;
-  const AppId to_app_;
+  std::vector<webapps::AppId> from_apps_or_extensions_;
+  const webapps::AppId to_app_;
   base::OnceCallback<void(bool uninstall_triggered)> on_complete_;
 
   base::Value::Dict debug_value_;
diff --git a/chrome/browser/web_applications/locks/all_apps_lock.h b/chrome/browser/web_applications/locks/all_apps_lock.h
index 508b2d1c..f7f3bef6 100644
--- a/chrome/browser/web_applications/locks/all_apps_lock.h
+++ b/chrome/browser/web_applications/locks/all_apps_lock.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/locks/lock.h"
 #include "chrome/browser/web_applications/locks/with_app_resources.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace content {
 struct PartitionedLockHolder;
diff --git a/chrome/browser/web_applications/locks/app_lock.cc b/chrome/browser/web_applications/locks/app_lock.cc
index dbed87a..e58a7273 100644
--- a/chrome/browser/web_applications/locks/app_lock.cc
+++ b/chrome/browser/web_applications/locks/app_lock.cc
@@ -9,9 +9,9 @@
 
 namespace web_app {
 
-AppLockDescription::AppLockDescription(const AppId& app_id)
+AppLockDescription::AppLockDescription(const webapps::AppId& app_id)
     : LockDescription({app_id}, LockDescription::Type::kApp) {}
-AppLockDescription::AppLockDescription(base::flat_set<AppId> app_ids)
+AppLockDescription::AppLockDescription(base::flat_set<webapps::AppId> app_ids)
     : LockDescription(std::move(app_ids), LockDescription::Type::kApp) {}
 AppLockDescription::~AppLockDescription() = default;
 
diff --git a/chrome/browser/web_applications/locks/app_lock.h b/chrome/browser/web_applications/locks/app_lock.h
index adb4b69..40f540fc 100644
--- a/chrome/browser/web_applications/locks/app_lock.h
+++ b/chrome/browser/web_applications/locks/app_lock.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/locks/lock.h"
 #include "chrome/browser/web_applications/locks/with_app_resources.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace content {
 struct PartitionedLockHolder;
@@ -26,8 +27,8 @@
 // Locks can be acquired by using the `WebAppLockManager`.
 class AppLockDescription : public LockDescription {
  public:
-  explicit AppLockDescription(const AppId& app_id);
-  explicit AppLockDescription(base::flat_set<AppId> app_ids);
+  explicit AppLockDescription(const webapps::AppId& app_id);
+  explicit AppLockDescription(base::flat_set<webapps::AppId> app_ids);
   ~AppLockDescription();
 };
 
diff --git a/chrome/browser/web_applications/locks/lock.cc b/chrome/browser/web_applications/locks/lock.cc
index 32e7a0b..7279dc9 100644
--- a/chrome/browser/web_applications/locks/lock.cc
+++ b/chrome/browser/web_applications/locks/lock.cc
@@ -28,7 +28,7 @@
   }
 }
 
-LockDescription::LockDescription(base::flat_set<AppId> app_ids,
+LockDescription::LockDescription(base::flat_set<webapps::AppId> app_ids,
                                  LockDescription::Type type)
     : app_ids_(std::move(app_ids)), type_(type) {}
 LockDescription::~LockDescription() = default;
diff --git a/chrome/browser/web_applications/locks/lock.h b/chrome/browser/web_applications/locks/lock.h
index f5c8be3..a51b7ef 100644
--- a/chrome/browser/web_applications/locks/lock.h
+++ b/chrome/browser/web_applications/locks/lock.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace content {
 struct PartitionedLockHolder;
@@ -45,7 +46,7 @@
 
   Type type() const { return type_; }
 
-  const base::flat_set<AppId>& app_ids() const { return app_ids_; }
+  const base::flat_set<webapps::AppId>& app_ids() const { return app_ids_; }
 
   // Shortcut methods looking at the `type()`. Returns if this lock includes an
   // exclusive lock on the shared web contents.
@@ -54,7 +55,7 @@
   base::Value AsDebugValue() const;
 
  protected:
-  explicit LockDescription(base::flat_set<AppId> app_ids, Type type);
+  explicit LockDescription(base::flat_set<webapps::AppId> app_ids, Type type);
 
  private:
   enum class LockLevel {
@@ -63,7 +64,7 @@
     kMaxValue = kApp,
   };
 
-  const base::flat_set<AppId> app_ids_{};
+  const base::flat_set<webapps::AppId> app_ids_{};
   const Type type_;
 
   base::WeakPtrFactory<LockDescription> weak_factory_{this};
diff --git a/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.cc b/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.cc
index 7e47f353..fa49514 100644
--- a/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.cc
+++ b/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.cc
@@ -14,7 +14,8 @@
 namespace web_app {
 
 SharedWebContentsWithAppLockDescription::
-    SharedWebContentsWithAppLockDescription(base::flat_set<AppId> app_ids)
+    SharedWebContentsWithAppLockDescription(
+        base::flat_set<webapps::AppId> app_ids)
     : LockDescription(std::move(app_ids),
                       LockDescription::Type::kAppAndWebContents) {}
 SharedWebContentsWithAppLockDescription::
diff --git a/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h b/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h
index 3f53b08b..4ba2d09 100644
--- a/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h
+++ b/chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/web_applications/locks/with_app_resources.h"
 #include "chrome/browser/web_applications/locks/with_shared_web_contents_resources.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace content {
 class WebContents;
@@ -34,7 +35,7 @@
 class SharedWebContentsWithAppLockDescription : public LockDescription {
  public:
   explicit SharedWebContentsWithAppLockDescription(
-      base::flat_set<AppId> app_ids);
+      base::flat_set<webapps::AppId> app_ids);
   ~SharedWebContentsWithAppLockDescription();
 };
 
diff --git a/chrome/browser/web_applications/locks/web_app_lock_manager.cc b/chrome/browser/web_applications/locks/web_app_lock_manager.cc
index e199d63..1d9bff5 100644
--- a/chrome/browser/web_applications/locks/web_app_lock_manager.cc
+++ b/chrome/browser/web_applications/locks/web_app_lock_manager.cc
@@ -25,10 +25,10 @@
 #include "chrome/browser/web_applications/locks/shared_web_contents_lock.h"
 #include "chrome/browser/web_applications/locks/shared_web_contents_with_app_lock.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "components/services/storage/indexed_db/locks/partitioned_lock_id.h"
 #include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -75,10 +75,10 @@
 }
 
 std::vector<content::PartitionedLockManager::PartitionedLockRequest>
-GetExclusiveAppIdLocks(const base::flat_set<AppId>& app_ids) {
+GetExclusiveAppIdLocks(const base::flat_set<webapps::AppId>& app_ids) {
   std::vector<content::PartitionedLockManager::PartitionedLockRequest>
       lock_requests;
-  for (const AppId& app_id : app_ids) {
+  for (const webapps::AppId& app_id : app_ids) {
     lock_requests.emplace_back(
         content::PartitionedLockId(
             {static_cast<int>(LockPartition::kApp), app_id}),
@@ -243,7 +243,7 @@
 std::unique_ptr<SharedWebContentsWithAppLockDescription>
 WebAppLockManager::UpgradeAndAcquireLock(
     std::unique_ptr<SharedWebContentsLock> lock,
-    const base::flat_set<AppId>& app_ids,
+    const base::flat_set<webapps::AppId>& app_ids,
     base::OnceCallback<void(std::unique_ptr<SharedWebContentsWithAppLock>)>
         on_lock_acquired,
     const base::Location& location) {
@@ -272,7 +272,7 @@
 
 std::unique_ptr<AppLockDescription> WebAppLockManager::UpgradeAndAcquireLock(
     std::unique_ptr<NoopLock> lock,
-    const base::flat_set<AppId>& app_ids,
+    const base::flat_set<webapps::AppId>& app_ids,
     base::OnceCallback<void(std::unique_ptr<AppLock>)> on_lock_acquired,
     const base::Location& location) {
   std::unique_ptr<AppLockDescription> result_lock_description =
diff --git a/chrome/browser/web_applications/locks/web_app_lock_manager.h b/chrome/browser/web_applications/locks/web_app_lock_manager.h
index 842f91b6..1ff14512 100644
--- a/chrome/browser/web_applications/locks/web_app_lock_manager.h
+++ b/chrome/browser/web_applications/locks/web_app_lock_manager.h
@@ -15,6 +15,7 @@
 #include "base/types/pass_key.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace base {
 class Value;
@@ -44,7 +45,8 @@
 // example, the following method call guarantees that it is done in an isolated
 // context:
 //
-// void UpdateWidget(WithAppResources& lock_with_app_exclusivity, AppId id) {
+// void UpdateWidget(WithAppResources& lock_with_app_exclusivity, webapps::AppId
+// id) {
 //    widget_.SetTitle(lock_with_app_exclusivity.registrar().GetShortName(id));
 //    ...
 // }
@@ -58,7 +60,7 @@
 // Example of using a lock across an async boundary:
 //
 // void UpdateWidget(base::WeakPtr<WithAppResources> lock_with_app_exclusivity,
-//                   AppId id) {
+//                   webapps::AppId id) {
 //    widget_.SetTitle(lock_with_app_exclusivity.registrar().GetShortName(id));
 //    TalkToAsyncSystem(..., base::BindOnce(&OnAsyncSystemUpdated,
 //                                          lock_with_app_exclusivity));
@@ -100,7 +102,7 @@
   std::unique_ptr<SharedWebContentsWithAppLockDescription>
   UpgradeAndAcquireLock(
       std::unique_ptr<SharedWebContentsLock> lock,
-      const base::flat_set<AppId>& app_ids,
+      const base::flat_set<webapps::AppId>& app_ids,
       base::OnceCallback<void(std::unique_ptr<SharedWebContentsWithAppLock>)>
           on_lock_acquired,
       const base::Location& location = FROM_HERE);
@@ -109,7 +111,7 @@
   // when the new lock has been acquired.
   std::unique_ptr<AppLockDescription> UpgradeAndAcquireLock(
       std::unique_ptr<NoopLock> lock,
-      const base::flat_set<AppId>& app_ids,
+      const base::flat_set<webapps::AppId>& app_ids,
       base::OnceCallback<void(std::unique_ptr<AppLock>)> on_lock_acquired,
       const base::Location& location = FROM_HERE);
 
diff --git a/chrome/browser/web_applications/manifest_update_manager.cc b/chrome/browser/web_applications/manifest_update_manager.cc
index 1b3037c0..69204e6a 100644
--- a/chrome/browser/web_applications/manifest_update_manager.cc
+++ b/chrome/browser/web_applications/manifest_update_manager.cc
@@ -200,9 +200,10 @@
   started_ = false;
 }
 
-void ManifestUpdateManager::MaybeUpdate(const GURL& url,
-                                        const absl::optional<AppId>& app_id,
-                                        content::WebContents* web_contents) {
+void ManifestUpdateManager::MaybeUpdate(
+    const GURL& url,
+    const absl::optional<webapps::AppId>& app_id,
+    content::WebContents* web_contents) {
   if (!started_) {
     return;
   }
@@ -270,7 +271,7 @@
 ManifestUpdateManager::UpdateStage::~UpdateStage() = default;
 
 void ManifestUpdateManager::StartCheckAfterPageAndManifestUrlLoad(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::Time check_time,
     base::WeakPtr<content::WebContents> web_contents) {
   auto update_stage_it = update_stages_.find(app_id);
@@ -306,7 +307,7 @@
 void ManifestUpdateManager::OnManifestCheckAwaitAppWindowClose(
     base::WeakPtr<content::WebContents> contents,
     const GURL& url,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ManifestUpdateCheckResult check_result,
     absl::optional<WebAppInstallInfo> install_info) {
   auto update_stage_it = update_stages_.find(app_id);
@@ -374,7 +375,7 @@
 
 void ManifestUpdateManager::StartManifestWriteAfterWindowsClosed(
     const GURL& url,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     std::unique_ptr<ScopedKeepAlive> keep_alive,
     std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive,
     WebAppInstallInfo install_info) {
@@ -395,7 +396,7 @@
                      weak_factory_.GetWeakPtr()));
 }
 
-bool ManifestUpdateManager::IsUpdateConsumed(const AppId& app_id,
+bool ManifestUpdateManager::IsUpdateConsumed(const webapps::AppId& app_id,
                                              base::Time check_time) {
   absl::optional<base::Time> last_check_time = GetLastUpdateCheckTime(app_id);
   if (last_check_time.has_value() &&
@@ -407,12 +408,14 @@
   return false;
 }
 
-bool ManifestUpdateManager::IsUpdateCommandPending(const AppId& app_id) {
+bool ManifestUpdateManager::IsUpdateCommandPending(
+    const webapps::AppId& app_id) {
   return base::Contains(update_stages_, app_id);
 }
 
 // WebAppInstallManager:
-void ManifestUpdateManager::OnWebAppWillBeUninstalled(const AppId& app_id) {
+void ManifestUpdateManager::OnWebAppWillBeUninstalled(
+    const webapps::AppId& app_id) {
   CHECK(started_);
   auto it = update_stages_.find(app_id);
   if (it != update_stages_.end()) {
@@ -430,9 +433,10 @@
 
 // Throttling updates to at most once per day is consistent with Android.
 // See |UPDATE_INTERVAL| in WebappDataStorage.java.
-bool ManifestUpdateManager::MaybeConsumeUpdateCheck(const GURL& origin,
-                                                    const AppId& app_id,
-                                                    base::Time check_time) {
+bool ManifestUpdateManager::MaybeConsumeUpdateCheck(
+    const GURL& origin,
+    const webapps::AppId& app_id,
+    base::Time check_time) {
   if (IsUpdateConsumed(app_id, check_time)) {
     return false;
   }
@@ -442,20 +446,20 @@
 }
 
 absl::optional<base::Time> ManifestUpdateManager::GetLastUpdateCheckTime(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto it = last_update_check_.find(app_id);
   return it != last_update_check_.end() ? absl::optional<base::Time>(it->second)
                                         : absl::nullopt;
 }
 
 void ManifestUpdateManager::SetLastUpdateCheckTime(const GURL& origin,
-                                                   const AppId& app_id,
+                                                   const webapps::AppId& app_id,
                                                    base::Time time) {
   last_update_check_[app_id] = time;
 }
 
 void ManifestUpdateManager::OnUpdateStopped(const GURL& url,
-                                            const AppId& app_id,
+                                            const webapps::AppId& app_id,
                                             ManifestUpdateResult result) {
   auto update_stage_it = update_stages_.find(app_id);
   // If the app has been uninstalled in the middle of the manifest
@@ -466,9 +470,10 @@
   NotifyResult(url, app_id, result);
 }
 
-void ManifestUpdateManager::NotifyResult(const GURL& url,
-                                         const absl::optional<AppId>& app_id,
-                                         ManifestUpdateResult result) {
+void ManifestUpdateManager::NotifyResult(
+    const GURL& url,
+    const absl::optional<webapps::AppId>& app_id,
+    ManifestUpdateResult result) {
   // Don't log kNoAppInScope because it will be far too noisy (most page loads
   // will hit it).
   if (result != ManifestUpdateResult::kNoAppInScope) {
@@ -480,7 +485,7 @@
 }
 
 void ManifestUpdateManager::ResetManifestThrottleForTesting(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   // Erase the throttle info from the map so that corresponding
   // manifest writes can go through.
   auto it = last_update_check_.find(app_id);
@@ -504,9 +509,9 @@
   load_finished_callback_ = std::move(load_finished_callback);
 }
 
-base::flat_set<AppId>
+base::flat_set<webapps::AppId>
 ManifestUpdateManager::GetAppsPendingWindowsClosingForTesting() {
-  base::flat_set<AppId> apps_pending_window_closed;
+  base::flat_set<webapps::AppId> apps_pending_window_closed;
   for (const auto& data : update_stages_) {
     if (data.second.stage == UpdateStage::Stage::kPendingAppWindowClose) {
       apps_pending_window_closed.emplace(data.first);
@@ -516,7 +521,7 @@
 }
 
 bool ManifestUpdateManager::IsAppPendingPageAndManifestUrlLoadForTesting(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   CHECK_IS_TEST();
   auto update_stage_it = update_stages_.find(app_id);
   if (update_stage_it == update_stages_.end()) {
diff --git a/chrome/browser/web_applications/manifest_update_manager.h b/chrome/browser/web_applications/manifest_update_manager.h
index 49980f05..516c465 100644
--- a/chrome/browser/web_applications/manifest_update_manager.h
+++ b/chrome/browser/web_applications/manifest_update_manager.h
@@ -26,6 +26,7 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_ui_manager.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -89,13 +90,13 @@
   void Shutdown();
 
   void MaybeUpdate(const GURL& url,
-                   const absl::optional<AppId>& app_id,
+                   const absl::optional<webapps::AppId>& app_id,
                    content::WebContents* web_contents);
-  bool IsUpdateConsumed(const AppId& app_id, base::Time check_time);
-  bool IsUpdateCommandPending(const AppId& app_id);
+  bool IsUpdateConsumed(const webapps::AppId& app_id, base::Time check_time);
+  bool IsUpdateCommandPending(const webapps::AppId& app_id);
 
   // WebAppInstallManagerObserver:
-  void OnWebAppWillBeUninstalled(const AppId& app_id) override;
+  void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
 
   void set_time_override_for_testing(base::Time time_override) {
@@ -106,7 +107,7 @@
     hang_update_checks_for_testing_ = true;
   }
 
-  void ResetManifestThrottleForTesting(const AppId& app_id);
+  void ResetManifestThrottleForTesting(const webapps::AppId& app_id);
   // Return whether there are pending updates waiting for the page load to
   // finish.
   bool HasUpdatesPendingLoadFinishForTesting();
@@ -116,9 +117,10 @@
   // happen. These includes app with windows open, ready to be closed as well as
   // apps with no windows and an already scheduled command to finalize the
   // manifest update.
-  base::flat_set<AppId> GetAppsPendingWindowsClosingForTesting();
+  base::flat_set<webapps::AppId> GetAppsPendingWindowsClosingForTesting();
 
-  bool IsAppPendingPageAndManifestUrlLoadForTesting(const AppId& app_id);
+  bool IsAppPendingPageAndManifestUrlLoadForTesting(
+      const webapps::AppId& app_id);
 
  private:
   // This class is used to either observe the url loading or web_contents
@@ -152,36 +154,37 @@
   };
 
   void StartCheckAfterPageAndManifestUrlLoad(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::Time check_time,
       base::WeakPtr<content::WebContents> web_contents);
 
   void OnManifestCheckAwaitAppWindowClose(
       base::WeakPtr<content::WebContents> contents,
       const GURL& url,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       ManifestUpdateCheckResult check_result,
       absl::optional<WebAppInstallInfo> install_info);
 
   void StartManifestWriteAfterWindowsClosed(
       const GURL& url,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       std::unique_ptr<ScopedKeepAlive> keep_alive,
       std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive,
       WebAppInstallInfo install_info);
 
   bool MaybeConsumeUpdateCheck(const GURL& origin,
-                               const AppId& app_id,
+                               const webapps::AppId& app_id,
                                base::Time check_time);
-  absl::optional<base::Time> GetLastUpdateCheckTime(const AppId& app_id) const;
+  absl::optional<base::Time> GetLastUpdateCheckTime(
+      const webapps::AppId& app_id) const;
   void SetLastUpdateCheckTime(const GURL& origin,
-                              const AppId& app_id,
+                              const webapps::AppId& app_id,
                               base::Time time);
   void OnUpdateStopped(const GURL& url,
-                       const AppId& app_id,
+                       const webapps::AppId& app_id,
                        ManifestUpdateResult result);
   void NotifyResult(const GURL& url,
-                    const absl::optional<AppId>& app_id,
+                    const absl::optional<webapps::AppId>& app_id,
                     ManifestUpdateResult result);
 
   static bool& BypassWindowCloseWaitingForTesting();
@@ -195,8 +198,8 @@
   base::ScopedObservation<WebAppInstallManager, WebAppInstallManagerObserver>
       install_manager_observation_{this};
 
-  std::map<AppId, UpdateStage> update_stages_;
-  base::flat_map<AppId, base::Time> last_update_check_;
+  std::map<webapps::AppId, UpdateStage> update_stages_;
+  base::flat_map<webapps::AppId, base::Time> last_update_check_;
 
   absl::optional<base::Time> time_override_for_testing_;
 
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
index 90c32a6..cb9b101 100644
--- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -65,7 +65,6 @@
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
@@ -86,6 +85,7 @@
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "components/webapps/services/web_app_origin_association/test/test_web_app_origin_association_fetcher.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
@@ -403,7 +403,7 @@
   // `expectations`. The latter is a vector mapping (size, os) to an SK_Color
   // value.
   void ConfirmShortcutColors(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<std::pair<std::pair<int, int>, SkColor>>&
           expectations) {
     GetProvider().os_integration_manager().GetShortcutInfoForApp(
@@ -478,12 +478,12 @@
   }
 
   // Mimics the Create Shortcut flow from the three dot overflow menu.
-  AppId InstallWebAppWithoutManifest() {
+  webapps::AppId InstallWebAppWithoutManifest() {
     GURL app_url = GetAppURLWithoutManifest();
     EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), app_url));
 
-    AppId app_id;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode>
+    webapps::AppId app_id;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
         install_future;
     GetProvider().scheduler().FetchManifestAndInstall(
         webapps::WebappInstallSource::MENU_CREATE_SHORTCUT,
@@ -494,56 +494,56 @@
         /*use_fallback=*/true);
     EXPECT_EQ(install_future.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return install_future.Get<AppId>();
+    return install_future.Get<webapps::AppId>();
   }
 
-  AppId InstallWebApp() {
+  webapps::AppId InstallWebApp() {
     GURL app_url = GetAppURL();
     EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), app_url));
 
-    AppId app_id;
+    webapps::AppId app_id;
     base::RunLoop run_loop;
     GetProvider().scheduler().FetchManifestAndInstall(
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
         browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
         /*bypass_service_worker_check=*/false,
         base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting(
-            [&](const AppId& new_app_id, webapps::InstallResultCode code) {
-              EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
-              app_id = new_app_id;
-              run_loop.Quit();
-            }),
+        base::BindLambdaForTesting([&](const webapps::AppId& new_app_id,
+                                       webapps::InstallResultCode code) {
+          EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
+          app_id = new_app_id;
+          run_loop.Quit();
+        }),
         /*use_fallback=*/true);
 
     run_loop.Run();
     return app_id;
   }
 
-  AppId InstallOemWebApp() {
+  webapps::AppId InstallOemWebApp() {
     const GURL app_url = GetAppURL();
     EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), app_url));
 
-    AppId app_id;
+    webapps::AppId app_id;
     base::RunLoop run_loop;
     GetProvider().scheduler().FetchManifestAndInstall(
         webapps::WebappInstallSource::PRELOADED_OEM,
         browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
         /*bypass_service_worker_check=*/false,
         base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting(
-            [&](const AppId& new_app_id, webapps::InstallResultCode code) {
-              EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
-              app_id = new_app_id;
-              run_loop.Quit();
-            }),
+        base::BindLambdaForTesting([&](const webapps::AppId& new_app_id,
+                                       webapps::InstallResultCode code) {
+          EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
+          app_id = new_app_id;
+          run_loop.Quit();
+        }),
         /*use_fallback=*/true);
 
     run_loop.Run();
     return app_id;
   }
 
-  AppId InstallDefaultApp() {
+  webapps::AppId InstallDefaultApp() {
     const GURL app_url = GetAppURL();
     base::RunLoop run_loop;
     ExternalInstallOptions install_options(
@@ -570,7 +570,7 @@
         .value();
   }
 
-  AppId InstallPolicyApp() {
+  webapps::AppId InstallPolicyApp() {
     const GURL app_url = GetAppURL();
     base::RunLoop run_loop;
     ExternalInstallOptions install_options(
@@ -597,7 +597,7 @@
         .value();
   }
 
-  AppId InstallKioskApp() {
+  webapps::AppId InstallKioskApp() {
     const GURL app_url = GetAppURL();
     base::RunLoop run_loop;
     ExternalInstallOptions install_options(app_url,
@@ -621,8 +621,8 @@
         .value();
   }
 
-  AppId InstallWebAppFromSync(const GURL& start_url) {
-    const AppId app_id =
+  webapps::AppId InstallWebAppFromSync(const GURL& start_url) {
+    const webapps::AppId app_id =
         GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
 
     std::vector<std::unique_ptr<WebApp>> add_synced_apps_data;
@@ -684,7 +684,7 @@
     return *WebAppProvider::GetForTest(browser()->profile());
   }
 
-  SkColor ReadAppIconPixel(const AppId& app_id,
+  SkColor ReadAppIconPixel(const webapps::AppId& app_id,
                            SquareSizePx size,
                            int x = 0,
                            int y = 0) {
@@ -763,7 +763,7 @@
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
             ManifestUpdateResult::kNoAppInScope);
 
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   EXPECT_EQ(GetResultAfterPageLoad(GURL("http://example.org")),
             ManifestUpdateResult::kNoAppInScope);
@@ -776,7 +776,7 @@
   base::Time time_override = base::Time::UnixEpoch();
   SetTimeOverride(time_override);
 
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
             ManifestUpdateResult::kAppUpToDate);
 
@@ -808,7 +808,7 @@
 
 IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
                        CheckCancelledByWebContentsDestroyed) {
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   GetManifestUpdateManager(browser()->profile())
       .hang_update_checks_for_testing();
 
@@ -824,7 +824,7 @@
 
 IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
                        CheckCancelledByAppUninstalled) {
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   GetManifestUpdateManager(browser()->profile())
       .hang_update_checks_for_testing();
 
@@ -852,7 +852,7 @@
                        TriggersAfterLoadingNewManifestUrl) {
   // Install an app with no manifest, trigger an update by navigation.
   GURL no_manifest_url = GetAppURLWithoutManifest();
-  const AppId app_id = InstallWebAppWithoutManifest();
+  const webapps::AppId app_id = InstallWebAppWithoutManifest();
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   UpdateCheckResultAwaiter result_awaiter(no_manifest_url);
@@ -888,7 +888,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, ""});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "\n\n\n\n"});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -909,7 +909,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"Test app name", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate,
                    {"Different app name", kInstallableIconList});
@@ -933,7 +933,7 @@
   )";
   OverrideManifest(kManifestTemplate,
                    {"Short test app name", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate,
                    {"Different short test app name", kInstallableIconList});
@@ -962,7 +962,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"Test app name", kInstallableIconList});
-  AppId app_id = InstallDefaultApp();
+  webapps::AppId app_id = InstallDefaultApp();
 
   OverrideManifest(kManifestTemplate,
                    {"Different app name", kInstallableIconList});
@@ -986,7 +986,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"a.html", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {"b.html", kInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1007,7 +1007,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
             ManifestUpdateResult::kAppUpToDate);
   histogram_tester_.ExpectBucketCount(kUpdateHistogramName,
@@ -1027,7 +1027,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, ""});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   OverrideManifest(kManifestTemplate, {kInstallableIconList,
                                        "invalid manifest syntax !@#$%^*&()"});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1049,7 +1049,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "blue"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   GetProvider().sync_bridge_unsafe().SetAppIsLocallyInstalledForTesting(app_id,
                                                                         false);
@@ -1081,7 +1081,7 @@
 
   // Install via ExternallyManagedAppManager, the redirect to a different origin
   // should cause it to install a placeholder app.
-  AppId app_id = InstallPolicyApp();
+  webapps::AppId app_id = InstallPolicyApp();
   EXPECT_TRUE(GetProvider().registrar_unsafe().IsPlaceholderApp(
       app_id, WebAppManagement::kPolicy));
 
@@ -1123,7 +1123,7 @@
 
   // Install via ExternallyManagedAppManager, the redirect to a different origin
   // should cause it to install a placeholder app.
-  AppId app_id = InstallKioskApp();
+  webapps::AppId app_id = InstallKioskApp();
   EXPECT_TRUE(GetProvider().registrar_unsafe().IsPlaceholderApp(
       app_id, WebAppManagement::kKiosk));
 
@@ -1158,7 +1158,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "blue"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppThemeColor(app_id),
             SK_ColorBLUE);
 
@@ -1166,10 +1166,10 @@
   // if in-place web app update happens.
   WebAppInstallManagerObserverAdapter install_observer(
       &GetProvider().install_manager());
-  install_observer.SetWebAppInstalledDelegate(
-      base::BindLambdaForTesting([](const AppId& app_id) { NOTREACHED(); }));
-  install_observer.SetWebAppUninstalledDelegate(
-      base::BindLambdaForTesting([](const AppId& app_id) { NOTREACHED(); }));
+  install_observer.SetWebAppInstalledDelegate(base::BindLambdaForTesting(
+      [](const webapps::AppId& app_id) { NOTREACHED(); }));
+  install_observer.SetWebAppUninstalledDelegate(base::BindLambdaForTesting(
+      [](const webapps::AppId& app_id) { NOTREACHED(); }));
 
   // CSS #RRGGBBAA syntax.
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "#00FF00F0"});
@@ -1202,7 +1202,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "blue"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppBackgroundColor(app_id),
             SK_ColorBLUE);
 
@@ -1236,7 +1236,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppManifestUrl(app_id),
             GetManifestURL());
 
@@ -1267,7 +1267,7 @@
   )";
   OverrideManifest(kManifestTemplate,
                    {"App name 1", kInstallableIconList, "blue"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppThemeColor(app_id),
             SK_ColorBLUE);
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppShortName(app_id),
@@ -1304,7 +1304,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kAnotherInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1339,7 +1339,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallDefaultApp();
+  webapps::AppId app_id = InstallDefaultApp();
 
   OverrideManifest(kManifestTemplate, {kAnotherInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1369,7 +1369,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"blue", kInstallableIconList});
-  AppId app_id = InstallPolicyApp();
+  webapps::AppId app_id = InstallPolicyApp();
   EXPECT_FALSE(GetProvider().registrar_unsafe().CanUserUninstallWebApp(app_id));
 
   OverrideManifest(kManifestTemplate, {"red", kInstallableIconList});
@@ -1402,7 +1402,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"blue", kInstallableIconList});
-  AppId app_id = InstallKioskApp();
+  webapps::AppId app_id = InstallKioskApp();
   EXPECT_FALSE(GetProvider().registrar_unsafe().CanUserUninstallWebApp(app_id));
 
   OverrideManifest(kManifestTemplate, {"red", kInstallableIconList});
@@ -1434,7 +1434,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"/banners/", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {"/", kInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1464,7 +1464,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"Test app name", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ("Test app name",
             GetProvider().registrar_unsafe().GetAppShortName(app_id));
 
@@ -1518,7 +1518,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"Test app name", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ("Test app name",
             GetProvider().registrar_unsafe().GetAppShortName(app_id));
 
@@ -1567,7 +1567,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"/banners/", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   if (IsUpdateDialogEnabled()) {
     AcceptAppIdentityUpdateDialogForTesting();
@@ -1624,7 +1624,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"/banners/", kInstallableIconList});
-  AppId app_id = InstallDefaultApp();
+  webapps::AppId app_id = InstallDefaultApp();
 
   OverrideManifest(kManifestTemplate, {"/", kAnotherInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1673,7 +1673,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallPolicyApp();
+  webapps::AppId app_id = InstallPolicyApp();
 
   OverrideManifest(kManifestTemplate, {kAnotherInstallableIconList});
 
@@ -1721,7 +1721,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"Test app name", kInstallableIconList});
-  AppId app_id = InstallPolicyApp();
+  webapps::AppId app_id = InstallPolicyApp();
 
   OverrideManifest(kManifestTemplate,
                    {"Different app name", kInstallableIconList});
@@ -1757,7 +1757,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallKioskApp();
+  webapps::AppId app_id = InstallKioskApp();
 
   OverrideManifest(kManifestTemplate, {kAnotherInstallableIconList});
 
@@ -1789,7 +1789,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"Test app name", kInstallableIconList});
-  AppId app_id = InstallKioskApp();
+  webapps::AppId app_id = InstallKioskApp();
 
   OverrideManifest(kManifestTemplate,
                    {"Different app name", kInstallableIconList});
@@ -1819,7 +1819,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"minimal-ui", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {"standalone", kInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1848,7 +1848,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"standalone", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   GetProvider().sync_bridge_unsafe().SetAppUserDisplayMode(
       app_id, mojom::UserDisplayMode::kStandalone, /*is_user_action=*/false);
 
@@ -1883,7 +1883,7 @@
 
   OverrideManifest(kManifestTemplate,
                    {R"([ "fullscreen", "standalone" ])", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate,
                    {R"([ "fullscreen", "minimal-ui" ])", kInstallableIconList});
@@ -1921,7 +1921,7 @@
 
   // No display_override in manifest
   OverrideManifest(kManifestTemplate, {"", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // Add display_override field
   OverrideManifest(kManifestTemplate,
@@ -1963,7 +1963,7 @@
   OverrideManifest(kManifestTemplate,
                    {R"("display_override": [ "fullscreen", "minimal-ui" ],)",
                     kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // Remove display_override from manifest
   OverrideManifest(kManifestTemplate, {"", kInstallableIconList});
@@ -1999,7 +1999,7 @@
 
   OverrideManifest(kManifestTemplate,
                    {R"([ "browser", "fullscreen" ])", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   ASSERT_EQ(2u, GetProvider()
                     .registrar_unsafe()
@@ -2041,7 +2041,7 @@
 
   // No display_override in manifest
   OverrideManifest(kManifestTemplate, {"", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // display_override contains only invalid values
   OverrideManifest(
@@ -2068,7 +2068,7 @@
 
   OverrideManifest(kManifestTemplate,
                    {R"([ "standard", "fullscreen" ])", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // display_override contains an additional invalid value
   OverrideManifest(
@@ -2098,7 +2098,7 @@
     }
   )";
   OverrideManifest(kManifest, {});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // Replace the contents of 192x192-green.png with 192x192-red.png without
   // changing the URL.
@@ -2141,7 +2141,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"[]"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kAnotherInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -2174,7 +2174,7 @@
 
   OverrideManifest(kManifest, {"standalone"});
 
-  AppId app_id;
+  webapps::AppId app_id;
 
   // Make blue-192.png fail to download for the first sync install.
   {
@@ -2279,7 +2279,7 @@
   OverrideManifest(kManifestTemplate, {kInstallableIconList, R"({
     "client_mode": "focus-existing"
   })"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(
       GetProvider().registrar_unsafe().GetAppById(app_id)->launch_handler(),
       (LaunchHandler{LaunchHandler::ClientMode::kFocusExisting}));
@@ -2319,7 +2319,7 @@
 
 IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerSystemAppBrowserTest,
                        CheckUpdateSkipped) {
-  AppId app_id = system_app_->GetAppId();
+  webapps::AppId app_id = system_app_->GetAppId();
   EXPECT_EQ(GetResultAfterPageLoad(system_app_->GetAppUrl()),
             ManifestUpdateResult::kAppIsSystemWebApp);
 
@@ -2391,7 +2391,7 @@
   )";
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kShareTargetManifestTemplate, {kInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -2423,7 +2423,7 @@
     }
   )";
   OverrideManifest(kShareTargetManifestTemplate, {"GET", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kShareTargetManifestTemplate,
                    {"POST", kInstallableIconList});
@@ -2467,7 +2467,7 @@
   )";
 
   OverrideManifest(kShareTargetManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -2521,7 +2521,7 @@
   )";
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kFileHandlerManifestTemplate, {kInstallableIconList});
   EXPECT_EQ(ManifestUpdateResult::kAppUpdated,
@@ -2559,7 +2559,7 @@
   )";
 
   OverrideManifest(kFileHandlerManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kFileHandlerManifestTemplate, {kInstallableIconList});
   EXPECT_EQ(ManifestUpdateResult::kAppUpToDate,
@@ -2594,7 +2594,7 @@
 
   OverrideManifest(kFileHandlerManifestTemplate,
                    {".txt", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   const auto& old_file_handler = web_app->file_handlers()[0];
   EXPECT_EQ(1u, old_file_handler.accept.size());
@@ -2644,7 +2644,7 @@
   )";
 
   OverrideManifest(kFileHandlerManifestTemplate, {".txt", "red"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   const auto& old_file_handler = web_app->file_handlers()[0];
   auto old_extensions = old_file_handler.accept[0].file_extensions;
@@ -2749,7 +2749,7 @@
 
   OverrideManifest(kFileHandlerManifestTemplate,
                    {".txt", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   WebAppRegistrar& registrar = GetProvider().registrar_unsafe();
   const WebApp* web_app = registrar.GetAppById(app_id);
 
@@ -2809,7 +2809,7 @@
   )";
 
   OverrideManifest(kFileHandlerManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
   EXPECT_EQ(ManifestUpdateResult::kAppUpdated,
@@ -2845,7 +2845,7 @@
   )";
 
   OverrideManifest(kFileHandlerManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   auto [associations_list, association_count] =
       GetFileTypeAssociationsHandledByWebAppForDisplay(browser()->profile(),
@@ -2876,7 +2876,7 @@
   )";
 
   OverrideManifest(kFileHandlerManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   auto [associations_list, association_count] =
       GetFileTypeAssociationsHandledByWebAppForDisplay(browser()->profile(),
@@ -2914,7 +2914,7 @@
   )";
 
   OverrideManifest(kFileHandlerManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   auto [associations_list, association_count] =
       GetFileTypeAssociationsHandledByWebAppForDisplay(browser()->profile(),
@@ -2936,7 +2936,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, kShortcutsItem});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList, kShortcutsItems});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -2977,7 +2977,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "Home"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate,
                    {kInstallableIconList, kAnotherShortcutsItemName});
@@ -3019,7 +3019,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "HM", "Go home"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate,
                    {kInstallableIconList, kAnotherShortcutsItemShortName,
@@ -3057,7 +3057,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "/"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate,
                    {kInstallableIconList, kAnotherShortcutsItemUrl});
@@ -3099,7 +3099,7 @@
     }
   )";
   OverrideManifest(kManifest, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // Replace the contents of basic-192.png with blue-192.png without changing
   // the URL.
@@ -3152,7 +3152,7 @@
     }
   )";
   OverrideManifest(kManifest, {kNewName, kInstallableIconList});
-  AppId app_id = InstallOemWebApp();
+  webapps::AppId app_id = InstallOemWebApp();
 
   // Replace the contents of basic-192.png with blue-192.png without changing
   // the URL.
@@ -3208,7 +3208,7 @@
     }
   )";
   OverrideManifest(kManifest, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // Replace the contents of basic-192.png with blue-192.png without changing
   // the URL.
@@ -3282,7 +3282,7 @@
   )";
   OverrideManifest(kManifestTemplate,
                    {kInstallableIconList, "/banners/image-512px.png"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList, kAnotherIconSrc});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -3324,7 +3324,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "512x512"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate,
                    {kInstallableIconList,
@@ -3354,7 +3354,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "blue"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   base::Time manifest_update_time = web_app->manifest_update_time();
 
@@ -3396,7 +3396,7 @@
   }
 
   OverrideManifest(kManifest, {});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // Replace the green icon with a red icon without changing the URL.
   content::URLLoaderInterceptor url_interceptor(base::BindLambdaForTesting(
@@ -3454,7 +3454,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kAnotherInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -3503,7 +3503,7 @@
     }
   )";
   OverrideManifest(kManifest, {});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   histogram_tester_.ExpectBucketCount("WebApp.Icon.DownloadedResultOnCreate",
                                       IconsDownloadedResult::kCompleted, 1);
@@ -3579,7 +3579,7 @@
   )";
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kProtocolHandlerManifestTemplate, {kInstallableIconList});
   EXPECT_EQ(ManifestUpdateResult::kAppUpdated,
@@ -3614,7 +3614,7 @@
   )";
 
   OverrideManifest(kProtocolHandlerManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kProtocolHandlerManifestTemplate, {kInstallableIconList});
   EXPECT_EQ(ManifestUpdateResult::kAppUpToDate,
@@ -3646,7 +3646,7 @@
 
   OverrideManifest(kProtocolHandlerManifestTemplate,
                    {"mailto", "mailto", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_EQ(1u, web_app->protocol_handlers().size());
   const auto& old_protocol_handler = web_app->protocol_handlers()[0];
@@ -3697,7 +3697,7 @@
   )";
 
   OverrideManifest(kProtocolHandlerManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
   EXPECT_EQ(ManifestUpdateResult::kAppUpdated,
@@ -3746,7 +3746,7 @@
   )";
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_TRUE(web_app->lock_screen_start_url().is_empty());
 
@@ -3775,7 +3775,7 @@
   )";
 
   OverrideManifest(kLockScreenStartUrlManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_EQ(http_server_.GetURL("/lock-screen-start"),
             web_app->lock_screen_start_url().spec());
@@ -3806,7 +3806,7 @@
 
   OverrideManifest(kLockScreenStartUrlManifestTemplate,
                    {"old-relative-url", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   // URL parsed relative to manifest URL, which is in /banners/.
   EXPECT_EQ(http_server_.GetURL("/banners/old-relative-url"),
@@ -3848,7 +3848,7 @@
   )";
 
   OverrideManifest(kLockScreenStartUrlManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_FALSE(web_app->lock_screen_start_url().is_empty());
 
@@ -3896,7 +3896,7 @@
   )";
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_TRUE(web_app->lock_screen_start_url().is_empty());
 
@@ -3934,7 +3934,7 @@
   )";
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_TRUE(web_app->note_taking_new_note_url().is_empty());
 
@@ -3963,7 +3963,7 @@
   )";
 
   OverrideManifest(kNewNoteUrlManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_EQ(http_server_.GetURL("/new"),
             web_app->note_taking_new_note_url().spec());
@@ -3994,7 +3994,7 @@
 
   OverrideManifest(kNewNoteUrlManifestTemplate,
                    {"old-relative-url", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   // URL parsed relative to manifest URL, which is in /banners/.
   EXPECT_EQ(http_server_.GetURL("/banners/old-relative-url"),
@@ -4036,7 +4036,7 @@
   )";
 
   OverrideManifest(kNewNoteUrlManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_FALSE(web_app->note_taking_new_note_url().is_empty());
 
@@ -4064,7 +4064,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"/startA", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppStartUrl(app_id).path(),
             "/startA");
 
@@ -4090,7 +4090,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"test", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   OverrideManifest(kManifestTemplate, {"testb", kInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -4111,7 +4111,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   // manifest_id should default to start_url when it's not provided in manifest.
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppById(app_id)->manifest_id(),
@@ -4161,14 +4161,14 @@
         std::move(origin_association_fetcher));
   }
 
-  ScopeExtensions GetScopeExtensions(const AppId& app_id) {
+  ScopeExtensions GetScopeExtensions(const webapps::AppId& app_id) {
     return GetProvider()
         .registrar_unsafe()
         .GetAppById(app_id)
         ->scope_extensions();
   }
 
-  ScopeExtensions GetValidatedScopeExtensions(const AppId& app_id) {
+  ScopeExtensions GetValidatedScopeExtensions(const webapps::AppId& app_id) {
     return GetProvider()
         .registrar_unsafe()
         .GetAppById(app_id)
@@ -4210,7 +4210,7 @@
                        AddedScopeExtensionsWithAssociation) {
   // Install with no scope_extensions.
   OverrideScopeExtensions(R"([])");
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetScopeExtensions(app_id), ScopeExtensions());
   EXPECT_EQ(GetValidatedScopeExtensions(app_id), ScopeExtensions());
 
@@ -4244,7 +4244,7 @@
                        AddedScopeExtensionsWithoutAssociation) {
   // Install with no scope_extensions.
   OverrideScopeExtensions(R"([])");
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetScopeExtensions(app_id), ScopeExtensions());
   EXPECT_EQ(GetValidatedScopeExtensions(app_id), ScopeExtensions());
 
@@ -4284,7 +4284,7 @@
   SetOriginAssociationData({{url::Origin::Create(GURL("https://extension.com")),
                              OriginAssociationFileFromAppIdentity(
                                  GetAppURL().GetWithoutFilename())}});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   ScopeExtensions expected_extensions = ScopeExtensions(
       {ScopeExtensionInfo(url::Origin::Create(GURL("https://extension.com")))});
   EXPECT_EQ(GetScopeExtensions(app_id), expected_extensions);
@@ -4316,7 +4316,7 @@
       {{url::Origin::Create(GURL("https://extension_1.com")),
         OriginAssociationFileFromAppIdentity(
             GetAppURL().GetWithoutFilename())}});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   ScopeExtensions expected_extensions = ScopeExtensions({ScopeExtensionInfo(
       url::Origin::Create(GURL("https://extension_1.com")))});
@@ -4361,7 +4361,7 @@
                              OriginAssociationFileFromAppIdentity(
                                  GetAppURL().GetWithoutFilename())}});
 
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   ScopeExtensions expected_extensions = ScopeExtensions(
       {ScopeExtensionInfo(url::Origin::Create(GURL("https://extension.com")))});
   EXPECT_EQ(GetScopeExtensions(app_id), expected_extensions);
@@ -4392,7 +4392,7 @@
       )");
   // Validation should fail during initial install.
   SetOriginAssociationData({});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   ScopeExtensions expected_extensions = ScopeExtensions(
       {ScopeExtensionInfo(url::Origin::Create(GURL("https://extension.com")))});
   EXPECT_EQ(GetScopeExtensions(app_id), expected_extensions);
@@ -4423,7 +4423,7 @@
       )");
   // Validation should fail during initial install.
   SetOriginAssociationData({});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   ScopeExtensions expected_extensions = ScopeExtensions(
       {ScopeExtensionInfo(url::Origin::Create(GURL("https://extension.com")))});
   EXPECT_EQ(GetScopeExtensions(app_id), expected_extensions);
@@ -4455,9 +4455,10 @@
   }
 
  protected:
-  AppId InstallShortcutAppForCurrentUrl(Browser* browser,
-                                        bool open_as_window = false,
-                                        const char* override_title = nullptr) {
+  webapps::AppId InstallShortcutAppForCurrentUrl(
+      Browser* browser,
+      bool open_as_window = false,
+      const char* override_title = nullptr) {
     chrome::SetAutoAcceptWebAppDialogForTesting(
         /*auto_accept=*/true,
         /*auto_open_in_window=*/open_as_window);
@@ -4465,7 +4466,7 @@
     WebAppTestInstallWithOsHooksObserver observer(browser->profile());
     observer.BeginListening();
     CHECK(chrome::ExecuteCommand(browser, IDC_CREATE_SHORTCUT));
-    AppId app_id = observer.Wait();
+    webapps::AppId app_id = observer.Wait();
     chrome::SetAutoAcceptWebAppDialogForTesting(false, false);
     chrome::SetOverrideTitleForTesting(nullptr);
     return app_id;
@@ -4503,7 +4504,7 @@
 
   // Install a shortcut to the app, but use a different name for it (necessary
   // to reproduce the bug).
-  AppId app_id =
+  webapps::AppId app_id =
       InstallShortcutAppForCurrentUrl(browser(), false, kOverrideName);
 
   // The app installed should be the only app installed.
@@ -4568,7 +4569,7 @@
 
   // Setup the web app, install it and immediately update the manifest.
   OverrideManifest(kManifestTemplate, {"Test app name", kIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   OverrideManifest(kManifestTemplate,
                    {"Different app name", kUpdatedSingleIconList});
 
@@ -4604,7 +4605,7 @@
   // The app installed in the pre-test should be the only app installed.
   auto app_ids = GetProvider().registrar_unsafe().GetAppIds();
   ASSERT_EQ(1u, app_ids.size());
-  AppId app_id = app_ids[0];
+  webapps::AppId app_id = app_ids[0];
 
   EXPECT_EQ("Different app name",
             GetProvider().registrar_unsafe().GetAppShortName(app_id));
@@ -4634,7 +4635,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "blue"});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppBackgroundColor(app_id),
             SK_ColorBLUE);
   OverrideManifest(kManifestTemplate, {kInstallableIconList, "red"});
@@ -4671,7 +4672,7 @@
   // The app installed in the pre-test should be the only app installed.
   auto app_ids = GetProvider().registrar_unsafe().GetAppIds();
   ASSERT_EQ(1u, app_ids.size());
-  AppId app_id = app_ids[0];
+  webapps::AppId app_id = app_ids[0];
 
   EXPECT_EQ(GetProvider().registrar_unsafe().GetAppBackgroundColor(app_id),
             SK_ColorRED);
@@ -4694,7 +4695,7 @@
     }
   )";
   OverrideManifest(kManifestTemplate, {"Test app name", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
 
   base::RunLoop run_loop;
 
@@ -4754,7 +4755,7 @@
   // its identity).
   OverrideManifest(kManifestTemplate,
                    {"Old name", "standalone", "256x256-red.png", "red"});
-  AppId app_id = InstallDefaultApp();
+  webapps::AppId app_id = InstallDefaultApp();
   GURL app_url = GetAppURL();
   Browser* app_browser = nullptr;
 
@@ -4842,12 +4843,12 @@
 // call ManifestUpdateManager as a primary page is not changed.
 IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerPrerenderingBrowserTest,
                        NotUpdateInPrerendering) {
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   EXPECT_EQ(ManifestUpdateResult::kAppUpToDate,
             GetResultAfterPageLoad(GetAppURL()));
 
   content::WebContents* web_contents = GetWebContents();
-  const AppId* first_app_id = WebAppTabHelper::GetAppId(web_contents);
+  const webapps::AppId* first_app_id = WebAppTabHelper::GetAppId(web_contents);
   EXPECT_EQ(app_id, *first_app_id);
 
   base::HistogramTester histogram_tester;
@@ -4855,7 +4856,8 @@
   int host_id = prerender_helper().AddPrerender(prerender_url);
   content::test::PrerenderHostObserver host_observer(*web_contents, host_id);
   // Prerendering doesn't update the existing App ID.
-  const AppId* app_id_on_prerendering = WebAppTabHelper::GetAppId(web_contents);
+  const webapps::AppId* app_id_on_prerendering =
+      WebAppTabHelper::GetAppId(web_contents);
   EXPECT_EQ(app_id, *app_id_on_prerendering);
 
   // In prerendering navigation, it doesn't call ManifestUpdateManager.
@@ -4863,7 +4865,7 @@
 
   prerender_helper().NavigatePrimaryPage(prerender_url);
   EXPECT_TRUE(host_observer.was_activated());
-  const AppId* app_id_after_activation =
+  const webapps::AppId* app_id_after_activation =
       WebAppTabHelper::GetAppId(web_contents);
   EXPECT_EQ(nullptr, app_id_after_activation);
 }
@@ -4915,7 +4917,7 @@
   )";
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_FALSE(web_app->tab_strip().has_value());
 
@@ -4954,7 +4956,7 @@
   )";
 
   OverrideManifest(kTabStripManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_TRUE(web_app->tab_strip().has_value());
   EXPECT_EQ(http_server_.GetURL("/new-tab-url"),
@@ -4994,7 +4996,7 @@
 
   OverrideManifest(kTabStripManifestTemplate,
                    {"old-relative-url", kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   // URL parsed relative to manifest URL, which is in /banners/.
   EXPECT_TRUE(web_app->tab_strip().has_value());
@@ -5043,7 +5045,7 @@
   )";
 
   OverrideManifest(kTabStripManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_TRUE(web_app->tab_strip().has_value());
   EXPECT_EQ(http_server_.GetURL("/new-tab-url"),
@@ -5099,7 +5101,7 @@
   )";
 
   OverrideManifest(kManifestTemplate, {kInstallableIconList});
-  AppId app_id = InstallWebApp();
+  webapps::AppId app_id = InstallWebApp();
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
   EXPECT_FALSE(web_app->tab_strip().has_value());
 
@@ -5662,7 +5664,7 @@
 
   OverrideManifest(kManifestTemplate, {app_name, starting_stage});
 
-  AppId app_id;
+  webapps::AppId app_id;
   if (IsDefaultApp()) {
     app_id = InstallDefaultApp();
   } else if (IsKioskApp()) {
diff --git a/chrome/browser/web_applications/manifest_update_utils.cc b/chrome/browser/web_applications/manifest_update_utils.cc
index 7926b046..4d150555 100644
--- a/chrome/browser/web_applications/manifest_update_utils.cc
+++ b/chrome/browser/web_applications/manifest_update_utils.cc
@@ -11,10 +11,10 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/web_applications/web_app.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/common/chrome_features.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/blink/public/common/features.h"
 #include "ui/gfx/skia_util.h"
 
diff --git a/chrome/browser/web_applications/manifest_update_utils.h b/chrome/browser/web_applications/manifest_update_utils.h
index 5c6d8f6..f4980dd 100644
--- a/chrome/browser/web_applications/manifest_update_utils.h
+++ b/chrome/browser/web_applications/manifest_update_utils.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
diff --git a/chrome/browser/web_applications/os_integration/file_handling_sub_manager.cc b/chrome/browser/web_applications/os_integration/file_handling_sub_manager.cc
index c1acced0..8b9cc97 100644
--- a/chrome/browser/web_applications/os_integration/file_handling_sub_manager.cc
+++ b/chrome/browser/web_applications/os_integration/file_handling_sub_manager.cc
@@ -92,7 +92,7 @@
 FileHandlingSubManager::~FileHandlingSubManager() = default;
 
 void FileHandlingSubManager::Configure(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure configure_done) {
   DCHECK(!desired_state.has_file_handling());
@@ -131,7 +131,7 @@
 }
 
 void FileHandlingSubManager::Execute(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const absl::optional<SynchronizeOsOptions>& synchronize_options,
     const proto::WebAppOsIntegrationState& desired_state,
     const proto::WebAppOsIntegrationState& current_state,
@@ -156,7 +156,7 @@
                             desired_state, std::move(callback)));
 }
 
-void FileHandlingSubManager::ForceUnregister(const AppId& app_id,
+void FileHandlingSubManager::ForceUnregister(const webapps::AppId& app_id,
                                              base::OnceClosure callback) {
   if (!ShouldRegisterFileHandlersWithOs()) {
     std::move(callback).Run();
@@ -174,7 +174,7 @@
 }
 
 void FileHandlingSubManager::Unregister(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const proto::WebAppOsIntegrationState& desired_state,
     const proto::WebAppOsIntegrationState& current_state,
     base::OnceClosure callback) {
@@ -202,7 +202,7 @@
 }
 
 void FileHandlingSubManager::Register(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure callback) {
   if (!HasFileHandling(desired_state)) {
diff --git a/chrome/browser/web_applications/os_integration/file_handling_sub_manager.h b/chrome/browser/web_applications/os_integration/file_handling_sub_manager.h
index b66a9b1..e280f745 100644
--- a/chrome/browser/web_applications/os_integration/file_handling_sub_manager.h
+++ b/chrome/browser/web_applications/os_integration/file_handling_sub_manager.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -30,24 +31,24 @@
                          WebAppProvider& provider);
   ~FileHandlingSubManager() override;
 
-  void Configure(const AppId& app_id,
+  void Configure(const webapps::AppId& app_id,
                  proto::WebAppOsIntegrationState& desired_state,
                  base::OnceClosure configure_done) override;
-  void Execute(const AppId& app_id,
+  void Execute(const webapps::AppId& app_id,
                const absl::optional<SynchronizeOsOptions>& synchronize_options,
                const proto::WebAppOsIntegrationState& desired_state,
                const proto::WebAppOsIntegrationState& current_state,
                base::OnceClosure callback) override;
-  void ForceUnregister(const AppId& app_id,
+  void ForceUnregister(const webapps::AppId& app_id,
                        base::OnceClosure callback) override;
 
  private:
-  void Unregister(const AppId& app_id,
+  void Unregister(const webapps::AppId& app_id,
                   const proto::WebAppOsIntegrationState& desired_state,
                   const proto::WebAppOsIntegrationState& current_state,
                   base::OnceClosure callback);
 
-  void Register(const AppId& app_id,
+  void Register(const webapps::AppId& app_id,
                 const proto::WebAppOsIntegrationState& desired_state,
                 base::OnceClosure callback);
 
diff --git a/chrome/browser/web_applications/os_integration/file_handling_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/file_handling_sub_manager_unittest.cc
index 7bc57187..8a218fa 100644
--- a/chrome/browser/web_applications/os_integration/file_handling_sub_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/file_handling_sub_manager_unittest.cc
@@ -80,7 +80,7 @@
     WebAppTest::TearDown();
   }
 
-  web_app::AppId InstallWebAppWithFileHandlers(
+  webapps::AppId InstallWebAppWithFileHandlers(
       apps::FileHandlers file_handlers) {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
@@ -88,7 +88,8 @@
     info->title = u"Test App";
     info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
     info->file_handlers = file_handlers;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     // InstallFromInfoWithParams is used instead of InstallFromInfo, because
     // InstallFromInfo doesn't register OS integration.
     provider().scheduler().InstallFromInfoWithParams(
@@ -98,11 +99,11 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
  protected:
@@ -166,7 +167,7 @@
     file_handlers.push_back(file_handler);
   }
 
-  const AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
+  const webapps::AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -229,7 +230,7 @@
     file_handlers.push_back(file_handler);
   }
 
-  const AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
+  const webapps::AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
 
   base::test::TestFuture<void> future;
   provider().scheduler().PersistFileHandlersUserChoice(
@@ -260,7 +261,7 @@
     file_handlers.push_back(file_handler);
   }
 
-  const AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
+  const webapps::AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
 
   test::UninstallAllWebApps(profile());
   auto state =
@@ -332,7 +333,7 @@
     file_handlers.push_back(file_handler);
   }
 
-  const AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
+  const webapps::AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -363,7 +364,7 @@
     file_handlers.push_back(file_handler);
   }
 
-  const AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
+  const webapps::AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
   ASSERT_TRUE(state.has_value());
@@ -413,7 +414,7 @@
     file_handlers.push_back(file_handler);
   }
 
-  const AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
+  const webapps::AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -458,7 +459,7 @@
     file_handlers.push_back(file_handler);
   }
 
-  const AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
+  const webapps::AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
   const std::string& app_name =
       provider().registrar_unsafe().GetAppShortName(app_id);
 
@@ -504,7 +505,7 @@
     file_handlers.push_back(file_handler);
   }
 
-  const AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
+  const webapps::AppId& app_id = InstallWebAppWithFileHandlers(file_handlers);
   const std::string& app_name =
       provider().registrar_unsafe().GetAppShortName(app_id);
 
diff --git a/chrome/browser/web_applications/os_integration/os_integration_manager.cc b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
index 2e97e757..8c9666a 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_manager.cc
+++ b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
@@ -35,13 +35,13 @@
 #include "chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/browser/web_applications/web_app_ui_manager.h"
 #include "chrome/common/chrome_features.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_thread.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -209,7 +209,7 @@
 }
 
 void OsIntegrationManager::Synchronize(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure callback,
     absl::optional<SynchronizeOsOptions> options) {
   first_synchronize_called_ = true;
@@ -268,7 +268,7 @@
 }
 
 void OsIntegrationManager::InstallOsHooks(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     InstallOsHooksCallback callback,
     std::unique_ptr<WebAppInstallInfo> web_app_info,
     InstallOsHooksOptions options) {
@@ -318,14 +318,14 @@
 }
 
 void OsIntegrationManager::UninstallAllOsHooks(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     UninstallOsHooksCallback callback) {
   OsHooksOptions os_hooks;
   os_hooks.set();
   UninstallOsHooks(app_id, os_hooks, std::move(callback));
 }
 
-void OsIntegrationManager::UninstallOsHooks(const AppId& app_id,
+void OsIntegrationManager::UninstallOsHooks(const webapps::AppId& app_id,
                                             const OsHooksOptions& os_hooks,
                                             UninstallOsHooksCallback callback) {
   // If the "Execute" step is enabled for sub-managers, then the 'old' os
@@ -386,7 +386,7 @@
 }
 
 void OsIntegrationManager::UpdateOsHooks(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::StringPiece old_name,
     FileHandlerUpdateAction file_handlers_need_os_update,
     const WebAppInstallInfo& web_app_info,
@@ -436,24 +436,25 @@
 }
 
 void OsIntegrationManager::GetShortcutInfoForApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     WebAppShortcutManager::GetShortcutInfoCallback callback) {
   CHECK(shortcut_manager_);
   return shortcut_manager_->GetShortcutInfoForApp(app_id, std::move(callback));
 }
 
-bool OsIntegrationManager::IsFileHandlingAPIAvailable(const AppId& app_id) {
+bool OsIntegrationManager::IsFileHandlingAPIAvailable(
+    const webapps::AppId& app_id) {
   return true;
 }
 
 const apps::FileHandlers* OsIntegrationManager::GetEnabledFileHandlers(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   CHECK(file_handler_manager_);
   return file_handler_manager_->GetEnabledFileHandlers(app_id);
 }
 
 absl::optional<GURL> OsIntegrationManager::TranslateProtocolUrl(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& protocol_url) {
   if (!protocol_handler_manager_)
     return absl::optional<GURL>();
@@ -462,7 +463,7 @@
 }
 
 std::vector<custom_handlers::ProtocolHandler>
-OsIntegrationManager::GetAppProtocolHandlers(const AppId& app_id) {
+OsIntegrationManager::GetAppProtocolHandlers(const webapps::AppId& app_id) {
   if (!protocol_handler_manager_)
     return std::vector<custom_handlers::ProtocolHandler>();
 
@@ -507,7 +508,7 @@
   return nullptr;
 }
 
-void OsIntegrationManager::CreateShortcuts(const AppId& app_id,
+void OsIntegrationManager::CreateShortcuts(const webapps::AppId& app_id,
                                            bool add_to_desktop,
                                            ShortcutCreationReason reason,
                                            CreateShortcutsCallback callback) {
@@ -519,7 +520,7 @@
   }
 }
 
-void OsIntegrationManager::RegisterFileHandlers(const AppId& app_id,
+void OsIntegrationManager::RegisterFileHandlers(const webapps::AppId& app_id,
                                                 ResultCallback callback) {
   CHECK(file_handler_manager_);
   ResultCallback metrics_callback =
@@ -533,8 +534,9 @@
       app_id, std::move(metrics_callback));
 }
 
-void OsIntegrationManager::RegisterProtocolHandlers(const AppId& app_id,
-                                                    ResultCallback callback) {
+void OsIntegrationManager::RegisterProtocolHandlers(
+    const webapps::AppId& app_id,
+    ResultCallback callback) {
   if (!protocol_handler_manager_) {
     std::move(callback).Run(Result::kOk);
     return;
@@ -544,7 +546,7 @@
                                                         std::move(callback));
 }
 
-void OsIntegrationManager::RegisterUrlHandlers(const AppId& app_id,
+void OsIntegrationManager::RegisterUrlHandlers(const webapps::AppId& app_id,
                                                ResultCallback callback) {
   if (!url_handler_manager_) {
     std::move(callback).Run(Result::kOk);
@@ -555,7 +557,7 @@
 }
 
 void OsIntegrationManager::RegisterShortcutsMenu(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
     const ShortcutsMenuIconBitmaps& shortcuts_menu_icon_bitmaps,
     ResultCallback callback) {
@@ -584,7 +586,7 @@
 }
 
 void OsIntegrationManager::ReadAllShortcutsMenuIconsAndRegisterShortcutsMenu(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ResultCallback callback) {
   if (!ShouldRegisterShortcutsMenuWithOs()) {
     std::move(callback).Run(Result::kOk);
@@ -611,7 +613,7 @@
       app_id, shortcuts_menu_item_infos, std::move(metrics_callback));
 }
 
-void OsIntegrationManager::RegisterRunOnOsLogin(const AppId& app_id,
+void OsIntegrationManager::RegisterRunOnOsLogin(const webapps::AppId& app_id,
                                                 ResultCallback callback) {
   ResultCallback metrics_callback =
       base::BindOnce([](Result result) {
@@ -628,13 +630,14 @@
 }
 
 void OsIntegrationManager::MacAppShimOnAppInstalledForProfile(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
 #if BUILDFLAG(IS_MAC)
   AppShimRegistry::Get()->OnAppInstalledForProfile(app_id, profile_->GetPath());
 #endif
 }
 
-void OsIntegrationManager::AddAppToQuickLaunchBar(const AppId& app_id) {
+void OsIntegrationManager::AddAppToQuickLaunchBar(
+    const webapps::AppId& app_id) {
   CHECK(provider_);
   if (provider_->ui_manager().CanAddAppToQuickLaunchBar()) {
     provider_->ui_manager().AddAppToQuickLaunchBar(app_id);
@@ -642,7 +645,7 @@
 }
 
 void OsIntegrationManager::RegisterWebAppOsUninstallation(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& name) {
   if (ShouldRegisterUninstallationViaOsSettingsWithOs()) {
     RegisterUninstallationViaOsSettingsWithOs(app_id, name,
@@ -650,7 +653,7 @@
   }
 }
 
-bool OsIntegrationManager::UnregisterShortcutsMenu(const AppId& app_id,
+bool OsIntegrationManager::UnregisterShortcutsMenu(const webapps::AppId& app_id,
                                                    ResultCallback callback) {
   if (!ShouldRegisterShortcutsMenuWithOs()) {
     std::move(callback).Run(Result::kOk);
@@ -668,7 +671,7 @@
                                        std::move(metrics_callback));
 }
 
-void OsIntegrationManager::UnregisterRunOnOsLogin(const AppId& app_id,
+void OsIntegrationManager::UnregisterRunOnOsLogin(const webapps::AppId& app_id,
                                                   ResultCallback callback) {
   ResultCallback metrics_callback =
       base::BindOnce([](Result result) {
@@ -684,7 +687,7 @@
 }
 
 void OsIntegrationManager::DeleteShortcuts(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& shortcuts_data_dir,
     std::unique_ptr<ShortcutInfo> shortcut_info,
     ResultCallback callback) {
@@ -701,7 +704,7 @@
   }
 }
 
-void OsIntegrationManager::UnregisterFileHandlers(const AppId& app_id,
+void OsIntegrationManager::UnregisterFileHandlers(const webapps::AppId& app_id,
                                                   ResultCallback callback) {
   CHECK(file_handler_manager_);
   ResultCallback metrics_callback =
@@ -714,8 +717,9 @@
       app_id, std::move(metrics_callback));
 }
 
-void OsIntegrationManager::UnregisterProtocolHandlers(const AppId& app_id,
-                                                      ResultCallback callback) {
+void OsIntegrationManager::UnregisterProtocolHandlers(
+    const webapps::AppId& app_id,
+    ResultCallback callback) {
   if (!protocol_handler_manager_) {
     std::move(callback).Run(Result::kOk);
     return;
@@ -725,7 +729,7 @@
                                                           std::move(callback));
 }
 
-void OsIntegrationManager::UnregisterUrlHandlers(const AppId& app_id) {
+void OsIntegrationManager::UnregisterUrlHandlers(const webapps::AppId& app_id) {
   if (!url_handler_manager_)
     return;
 
@@ -733,13 +737,13 @@
 }
 
 void OsIntegrationManager::UnregisterWebAppOsUninstallation(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (ShouldRegisterUninstallationViaOsSettingsWithOs()) {
     UnregisterUninstallationViaOsSettingsWithOs(app_id, profile_->GetPath());
   }
 }
 
-void OsIntegrationManager::UpdateShortcuts(const AppId& app_id,
+void OsIntegrationManager::UpdateShortcuts(const webapps::AppId& app_id,
                                            base::StringPiece old_name,
                                            ResultCallback callback) {
   // If the "Execute" step is enabled for sub-managers, then the 'old' os
@@ -768,7 +772,7 @@
 }
 
 void OsIntegrationManager::UpdateShortcutsMenu(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const WebAppInstallInfo& web_app_info,
     ResultCallback callback) {
   if (web_app_info.shortcuts_menu_item_infos.empty()) {
@@ -781,7 +785,7 @@
 }
 
 void OsIntegrationManager::UpdateUrlHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceCallback<void(bool success)> callback) {
   // If the "Execute" step is enabled for sub-managers, then the 'old' os
   // integration path needs to be turned off so that os integration doesn't get
@@ -798,7 +802,7 @@
 }
 
 void OsIntegrationManager::UpdateFileHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     FileHandlerUpdateAction file_handlers_need_os_update,
     ResultCallback finished_callback) {
   // If the "Execute" step is enabled for sub-managers, then the 'old' os
@@ -825,7 +829,7 @@
   if (file_handlers_need_os_update == FileHandlerUpdateAction::kUpdate) {
     callback_after_removal = base::BindOnce(
         [](base::WeakPtr<OsIntegrationManager> os_integration_manager,
-           const AppId& app_id, ResultCallback finished_callback,
+           const webapps::AppId& app_id, ResultCallback finished_callback,
            Result result) {
           if (!os_integration_manager) {
             std::move(finished_callback).Run(Result::kError);
@@ -846,7 +850,7 @@
 }
 
 void OsIntegrationManager::UpdateProtocolHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool force_shortcut_updates_if_needed,
     base::OnceClosure callback) {
   // If the "Execute" step is enabled for sub-managers, then the 'old' os
@@ -884,13 +888,13 @@
 }
 
 void OsIntegrationManager::OnShortcutsUpdatedForProtocolHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure update_finished_callback) {
   // Update protocol handlers via complete uninstallation, then reinstallation.
   ResultCallback unregister_callback = base::BindOnce(
       [](base::WeakPtr<OsIntegrationManager> os_integration_manager,
-         const AppId& app_id, base::OnceClosure update_finished_callback,
-         Result result) {
+         const webapps::AppId& app_id,
+         base::OnceClosure update_finished_callback, Result result) {
         // Re-register protocol handlers regardless of `result`.
         // TODO(https://crbug.com/1250728): Report a UMA metric when
         // unregistering fails, either here, or at the point of failure. This
@@ -916,7 +920,8 @@
   UnregisterProtocolHandlers(app_id, std::move(unregister_callback));
 }
 
-void OsIntegrationManager::OnWebAppProfileWillBeDeleted(const AppId& app_id) {
+void OsIntegrationManager::OnWebAppProfileWillBeDeleted(
+    const webapps::AppId& app_id) {
   if (AreSubManagersExecuteEnabled()) {
     ForceUnregisterOsIntegrationOnSubManager(
         app_id, 0,
@@ -933,18 +938,18 @@
 }
 
 void OsIntegrationManager::SetForceUnregisterCalledForTesting(
-    base::RepeatingCallback<void(const AppId&)> on_force_unregister) {
+    base::RepeatingCallback<void(const webapps::AppId&)> on_force_unregister) {
   force_unregister_callback_for_testing_ = on_force_unregister;
 }
 
 std::unique_ptr<ShortcutInfo> OsIntegrationManager::BuildShortcutInfo(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   CHECK(shortcut_manager_);
   return shortcut_manager_->BuildShortcutInfo(app_id);
 }
 
 void OsIntegrationManager::StartSubManagerExecutionIfRequired(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     absl::optional<SynchronizeOsOptions> options,
     std::unique_ptr<proto::WebAppOsIntegrationState> desired_states,
     base::OnceClosure on_all_execution_done) {
@@ -983,7 +988,7 @@
 }
 
 void OsIntegrationManager::ExecuteNextSubmanager(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     absl::optional<SynchronizeOsOptions> options,
     proto::WebAppOsIntegrationState* desired_state,
     const proto::WebAppOsIntegrationState current_state,
@@ -1004,7 +1009,7 @@
 }
 
 void OsIntegrationManager::WriteStateToDB(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     std::unique_ptr<proto::WebAppOsIntegrationState> desired_states,
     base::OnceClosure callback) {
   // Exit early if the app is scheduled to be uninstalled or is already
@@ -1026,7 +1031,7 @@
 }
 
 void OsIntegrationManager::ForceUnregisterOsIntegrationOnSubManager(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     size_t index,
     base::OnceClosure final_callback) {
   CHECK(index < sub_managers_.size());
@@ -1043,7 +1048,7 @@
 }
 
 void OsIntegrationManager::OnShortcutsCreated(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     std::unique_ptr<WebAppInstallInfo> web_app_info,
     InstallOsHooksOptions options,
     scoped_refptr<OsHooksBarrier> barrier,
@@ -1110,7 +1115,7 @@
   }
 }
 
-void OsIntegrationManager::OnShortcutsDeleted(const AppId& app_id,
+void OsIntegrationManager::OnShortcutsDeleted(const webapps::AppId& app_id,
                                               ResultCallback callback,
                                               Result result) {
 #if BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/web_applications/os_integration/os_integration_manager.h b/chrome/browser/web_applications/os_integration/os_integration_manager.h
index d49cc53..800cf0b 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_manager.h
+++ b/chrome/browser/web_applications/os_integration/os_integration_manager.h
@@ -30,6 +30,7 @@
 #include "chrome/browser/web_applications/web_app_registrar_observer.h"
 #include "components/custom_handlers/protocol_handler.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -129,7 +130,7 @@
   // from this file once all OS Integration sub managers have been implemented,
   // connected to the web_app system and tested.
   virtual void Synchronize(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceClosure callback,
       absl::optional<SynchronizeOsOptions> options = absl::nullopt);
 
@@ -137,7 +138,7 @@
   // If provided |web_app_info| is a nullptr, it will read icons data from disk,
   // otherwise it will use (SkBitmaps) from |web_app_info|.
   // virtual for testing
-  virtual void InstallOsHooks(const AppId& app_id,
+  virtual void InstallOsHooks(const webapps::AppId& app_id,
                               InstallOsHooksCallback callback,
                               std::unique_ptr<WebAppInstallInfo> web_app_info,
                               InstallOsHooksOptions options);
@@ -147,20 +148,20 @@
   // Example: Running on OS login.
   // TODO(https://crbug.com/1108109) we should record uninstall result and allow
   // callback. virtual for testing
-  virtual void UninstallOsHooks(const AppId& app_id,
+  virtual void UninstallOsHooks(const webapps::AppId& app_id,
                                 const OsHooksOptions& os_hooks,
                                 UninstallOsHooksCallback callback);
 
   // Uninstall all OS hooks for the web app.
   // Used when uninstalling a web app.
   // virtual for testing
-  virtual void UninstallAllOsHooks(const AppId& app_id,
+  virtual void UninstallAllOsHooks(const webapps::AppId& app_id,
                                    UninstallOsHooksCallback callback);
 
   // Update all needed OS hooks for the web app.
   // virtual for testing
   virtual void UpdateOsHooks(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::StringPiece old_name,
       FileHandlerUpdateAction file_handlers_need_os_update,
       const WebAppInstallInfo& web_app_info,
@@ -174,18 +175,20 @@
 
   // Proxy calls for WebAppShortcutManager.
   void GetShortcutInfoForApp(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppShortcutManager::GetShortcutInfoCallback callback);
 
   // Proxy calls for WebAppFileHandlerManager.
-  bool IsFileHandlingAPIAvailable(const AppId& app_id);
-  const apps::FileHandlers* GetEnabledFileHandlers(const AppId& app_id) const;
+  bool IsFileHandlingAPIAvailable(const webapps::AppId& app_id);
+  const apps::FileHandlers* GetEnabledFileHandlers(
+      const webapps::AppId& app_id) const;
 
   // Proxy calls for WebAppProtocolHandlerManager.
-  virtual absl::optional<GURL> TranslateProtocolUrl(const AppId& app_id,
-                                                    const GURL& protocol_url);
+  virtual absl::optional<GURL> TranslateProtocolUrl(
+      const webapps::AppId& app_id,
+      const GURL& protocol_url);
   virtual std::vector<custom_handlers::ProtocolHandler> GetAppProtocolHandlers(
-      const AppId& app_id);
+      const webapps::AppId& app_id);
   virtual std::vector<custom_handlers::ProtocolHandler>
   GetAllowedHandlersForProtocol(const std::string& protocol);
   virtual std::vector<custom_handlers::ProtocolHandler>
@@ -209,31 +212,31 @@
   }
 
   virtual void UpdateUrlHandlers(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceCallback<void(bool success)> callback);
 
   virtual void UpdateFileHandlers(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       FileHandlerUpdateAction file_handlers_need_os_update,
       ResultCallback finished_callback);
 
   // Updates protocol handler registrations with the OS.
   // If `force_shortcut_updates_if_needed` is true, then also update the
   // application's shortcuts.
-  virtual void UpdateProtocolHandlers(const AppId& app_id,
+  virtual void UpdateProtocolHandlers(const webapps::AppId& app_id,
                                       bool force_shortcut_updates_if_needed,
                                       base::OnceClosure callback);
 
-  virtual void UpdateShortcuts(const AppId& app_id,
+  virtual void UpdateShortcuts(const webapps::AppId& app_id,
                                base::StringPiece old_name,
                                ResultCallback callback);
 
   // WebAppRegistrarObserver:
-  void OnWebAppProfileWillBeDeleted(const AppId& app_id) override;
+  void OnWebAppProfileWillBeDeleted(const webapps::AppId& app_id) override;
   void OnAppRegistrarDestroyed() override;
 
   void SetForceUnregisterCalledForTesting(
-      base::RepeatingCallback<void(const AppId&)> on_force_unregister);
+      base::RepeatingCallback<void(const webapps::AppId&)> on_force_unregister);
 
  protected:
   WebAppShortcutManager* shortcut_manager() { return shortcut_manager_.get(); }
@@ -257,62 +260,63 @@
     protocol_handler_manager_ = std::move(protocol_handler_manager);
   }
 
-  virtual void CreateShortcuts(const AppId& app_id,
+  virtual void CreateShortcuts(const webapps::AppId& app_id,
                                bool add_to_desktop,
                                ShortcutCreationReason reason,
                                CreateShortcutsCallback callback);
 
   // Installation:
-  virtual void RegisterFileHandlers(const AppId& app_id,
+  virtual void RegisterFileHandlers(const webapps::AppId& app_id,
                                     ResultCallback callback);
-  virtual void RegisterProtocolHandlers(const AppId& app_id,
+  virtual void RegisterProtocolHandlers(const webapps::AppId& app_id,
                                         ResultCallback callback);
-  virtual void RegisterUrlHandlers(const AppId& app_id,
+  virtual void RegisterUrlHandlers(const webapps::AppId& app_id,
                                    ResultCallback callback);
   virtual void RegisterShortcutsMenu(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
       const ShortcutsMenuIconBitmaps& shortcuts_menu_icon_bitmaps,
       ResultCallback callback);
   virtual void ReadAllShortcutsMenuIconsAndRegisterShortcutsMenu(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       ResultCallback callback);
-  virtual void RegisterRunOnOsLogin(const AppId& app_id,
+  virtual void RegisterRunOnOsLogin(const webapps::AppId& app_id,
                                     ResultCallback callback);
-  virtual void MacAppShimOnAppInstalledForProfile(const AppId& app_id);
-  virtual void AddAppToQuickLaunchBar(const AppId& app_id);
-  virtual void RegisterWebAppOsUninstallation(const AppId& app_id,
+  virtual void MacAppShimOnAppInstalledForProfile(const webapps::AppId& app_id);
+  virtual void AddAppToQuickLaunchBar(const webapps::AppId& app_id);
+  virtual void RegisterWebAppOsUninstallation(const webapps::AppId& app_id,
                                               const std::string& name);
 
   // Uninstallation:
-  virtual bool UnregisterShortcutsMenu(const AppId& app_id,
+  virtual bool UnregisterShortcutsMenu(const webapps::AppId& app_id,
                                        ResultCallback callback);
-  virtual void UnregisterRunOnOsLogin(const AppId& app_id,
+  virtual void UnregisterRunOnOsLogin(const webapps::AppId& app_id,
                                       ResultCallback callback);
-  virtual void DeleteShortcuts(const AppId& app_id,
+  virtual void DeleteShortcuts(const webapps::AppId& app_id,
                                const base::FilePath& shortcuts_data_dir,
                                std::unique_ptr<ShortcutInfo> shortcut_info,
                                ResultCallback callback);
-  virtual void UnregisterFileHandlers(const AppId& app_id,
+  virtual void UnregisterFileHandlers(const webapps::AppId& app_id,
                                       ResultCallback callback);
-  virtual void UnregisterProtocolHandlers(const AppId& app_id,
+  virtual void UnregisterProtocolHandlers(const webapps::AppId& app_id,
                                           ResultCallback callback);
-  virtual void UnregisterUrlHandlers(const AppId& app_id);
-  virtual void UnregisterWebAppOsUninstallation(const AppId& app_id);
+  virtual void UnregisterUrlHandlers(const webapps::AppId& app_id);
+  virtual void UnregisterWebAppOsUninstallation(const webapps::AppId& app_id);
 
   // Update:
-  virtual void UpdateShortcutsMenu(const AppId& app_id,
+  virtual void UpdateShortcutsMenu(const webapps::AppId& app_id,
                                    const WebAppInstallInfo& web_app_info,
                                    ResultCallback callback);
   // Utility methods:
-  virtual std::unique_ptr<ShortcutInfo> BuildShortcutInfo(const AppId& app_id);
+  virtual std::unique_ptr<ShortcutInfo> BuildShortcutInfo(
+      const webapps::AppId& app_id);
 
  private:
   class OsHooksBarrier;
 
   // Synchronize:
   void StartSubManagerExecutionIfRequired(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       absl::optional<SynchronizeOsOptions> options,
       std::unique_ptr<proto::WebAppOsIntegrationState> desired_states,
       base::OnceClosure on_all_execution_done);
@@ -322,7 +326,7 @@
   // managers are stored inside the sub_managers_ vector, and that consecutive
   // sub managers execute only if the one before it has finished executing.
   void ExecuteNextSubmanager(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       absl::optional<SynchronizeOsOptions> options,
       proto::WebAppOsIntegrationState* desired_state,
       const proto::WebAppOsIntegrationState current_state,
@@ -330,7 +334,7 @@
       base::OnceClosure on_all_execution_done_db_write);
 
   void WriteStateToDB(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       std::unique_ptr<proto::WebAppOsIntegrationState> desired_states,
       base::OnceClosure callback);
 
@@ -338,17 +342,17 @@
   // any OS integrations from the OS. This runs synchronously in the order that
   // the sub managers are stored inside the sub_managers_ vector.
   void ForceUnregisterOsIntegrationOnSubManager(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       size_t index,
       base::OnceClosure final_callback);
 
-  void OnShortcutsCreated(const AppId& app_id,
+  void OnShortcutsCreated(const webapps::AppId& app_id,
                           std::unique_ptr<WebAppInstallInfo> web_app_info,
                           InstallOsHooksOptions options,
                           scoped_refptr<OsHooksBarrier> barrier,
                           bool shortcuts_created);
 
-  void OnShortcutsDeleted(const AppId& app_id,
+  void OnShortcutsDeleted(const webapps::AppId& app_id,
                           ResultCallback callback,
                           Result result);
 
@@ -361,7 +365,7 @@
   // `update_finished_callback` is the callback provided in
   // `UpdateProtocolHandlers`.
   void OnShortcutsUpdatedForProtocolHandlers(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceClosure update_finished_callback);
 
   const raw_ptr<Profile> profile_;
@@ -376,7 +380,7 @@
   bool set_provider_called_ = false;
   bool first_synchronize_called_ = false;
 
-  base::RepeatingCallback<void(const AppId&)>
+  base::RepeatingCallback<void(const webapps::AppId&)>
       force_unregister_callback_for_testing_ = base::DoNothing();
 
   base::ScopedObservation<WebAppRegistrar, WebAppRegistrarObserver>
diff --git a/chrome/browser/web_applications/os_integration/os_integration_manager_unittest.cc b/chrome/browser/web_applications/os_integration/os_integration_manager_unittest.cc
index a4d8168..96777f3 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/os_integration_manager_unittest.cc
@@ -39,7 +39,8 @@
 const char kFakeAppUrl[] = "https://fake.com";
 const std::u16string kFakeAppTitle(u"fake title");
 
-std::unique_ptr<ShortcutInfo> CreateTestShorcutInfo(const AppId& app_id) {
+std::unique_ptr<ShortcutInfo> CreateTestShorcutInfo(
+    const webapps::AppId& app_id) {
   auto shortcut_info = std::make_unique<ShortcutInfo>();
   shortcut_info->profile_path = base::FilePath(kFakeProfilePath);
   shortcut_info->app_id = app_id;
@@ -80,7 +81,7 @@
         run_loop.Quit();
       });
 
-  const AppId app_id = "test";
+  const webapps::AppId app_id = "test";
 
   testing::StrictMock<MockOsIntegrationManager> manager;
   EXPECT_CALL(manager, MacAppShimOnAppInstalledForProfile(app_id)).Times(1);
@@ -106,7 +107,7 @@
         run_loop.Quit();
       });
 
-  const AppId app_id = "test";
+  const webapps::AppId app_id = "test";
 
   // Note - when features are enabled by default, more calls will needed to be
   // added here.
@@ -156,7 +157,7 @@
         run_loop.Quit();
       });
 
-  const AppId app_id = "test";
+  const webapps::AppId app_id = "test";
 
   const base::FilePath kExpectedShortcutPath =
       base::FilePath(kFakeProfilePath)
@@ -179,11 +180,11 @@
   EXPECT_CALL(manager, UnregisterRunOnOsLogin(app_id, testing::_)).Times(1);
 
   EXPECT_CALL(manager, UninstallAllOsHooks(testing::_, testing::_))
-      .WillOnce(
-          [&manager](const AppId& app_id, UninstallOsHooksCallback callback) {
-            return manager.OsIntegrationManager::UninstallAllOsHooks(
-                app_id, std::move(callback));
-          });
+      .WillOnce([&manager](const webapps::AppId& app_id,
+                           UninstallOsHooksCallback callback) {
+        return manager.OsIntegrationManager::UninstallAllOsHooks(
+            app_id, std::move(callback));
+      });
 
   manager.UninstallAllOsHooks(app_id, std::move(callback));
   run_loop.Run();
@@ -197,30 +198,30 @@
 }
 
 TEST_F(OsIntegrationManagerTest, UpdateProtocolHandlers) {
-  const AppId app_id = "test";
+  const webapps::AppId app_id = "test";
   testing::StrictMock<MockOsIntegrationManager> manager(
       std::make_unique<WebAppProtocolHandlerManager>(nullptr));
   base::RunLoop run_loop;
 
 #if !BUILDFLAG(IS_WIN)
   EXPECT_CALL(manager, UpdateShortcuts(app_id, base::StringPiece(), testing::_))
-      .WillOnce([](const AppId& app_id, base::StringPiece old_name,
+      .WillOnce([](const webapps::AppId& app_id, base::StringPiece old_name,
                    ResultCallback update_finished_callback) {
         std::move(update_finished_callback).Run(Result::kOk);
       });
 #endif
 
   EXPECT_CALL(manager, UnregisterProtocolHandlers(app_id, testing::_))
-      .WillOnce(
-          [](const AppId& app_id, ResultCallback update_finished_callback) {
-            std::move(update_finished_callback).Run(Result::kOk);
-          });
+      .WillOnce([](const webapps::AppId& app_id,
+                   ResultCallback update_finished_callback) {
+        std::move(update_finished_callback).Run(Result::kOk);
+      });
 
   EXPECT_CALL(manager, RegisterProtocolHandlers(app_id, testing::_))
-      .WillOnce(
-          [](const AppId& app_id, ResultCallback update_finished_callback) {
-            std::move(update_finished_callback).Run(Result::kOk);
-          });
+      .WillOnce([](const webapps::AppId& app_id,
+                   ResultCallback update_finished_callback) {
+        std::move(update_finished_callback).Run(Result::kOk);
+      });
 
   auto update_finished_callback =
       base::BindLambdaForTesting([&]() { run_loop.Quit(); });
diff --git a/chrome/browser/web_applications/os_integration/os_integration_sub_manager.h b/chrome/browser/web_applications/os_integration/os_integration_sub_manager.h
index 7636bfce..ffb1c211 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_sub_manager.h
+++ b/chrome/browser/web_applications/os_integration/os_integration_sub_manager.h
@@ -9,6 +9,7 @@
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
@@ -39,11 +40,11 @@
   virtual ~OsIntegrationSubManager() = default;
   // desired_state can still be empty after the configure_done has completed
   // running.
-  virtual void Configure(const AppId& app_id,
+  virtual void Configure(const webapps::AppId& app_id,
                          proto::WebAppOsIntegrationState& desired_state,
                          base::OnceClosure configure_done) = 0;
   virtual void Execute(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const absl::optional<SynchronizeOsOptions>& synchronize_options,
       const proto::WebAppOsIntegrationState& desired_state,
       const proto::WebAppOsIntegrationState& current_state,
@@ -52,7 +53,7 @@
   // Only invoked if the app is not in the database and the caller set
   // force_unregister_os_integration to true. Intended to clean up stale OS
   // state that was left over from an unsuccessful uninstall or stale OS data.
-  virtual void ForceUnregister(const AppId& app_id,
+  virtual void ForceUnregister(const webapps::AppId& app_id,
                                base::OnceClosure callback) = 0;
 };
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/os_integration/os_integration_test_override.cc b/chrome/browser/web_applications/os_integration/os_integration_test_override.cc
index 082f9a7..e3dec8a 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_test_override.cc
+++ b/chrome/browser/web_applications/os_integration/os_integration_test_override.cc
@@ -14,7 +14,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 namespace {
diff --git a/chrome/browser/web_applications/os_integration/os_integration_test_override.h b/chrome/browser/web_applications/os_integration/os_integration_test_override.h
index 157e094..4f87ef7d 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_test_override.h
+++ b/chrome/browser/web_applications/os_integration/os_integration_test_override.h
@@ -13,6 +13,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 #if BUILDFLAG(IS_WIN)
 class ShellLinkItem;
@@ -101,7 +102,7 @@
   // Creates a tuple of app_id to protocols and adds it to the vector
   // of registered protocols. There can be multiple entries for the same
   // app_id.
-  virtual void RegisterProtocolSchemes(const AppId& app_id,
+  virtual void RegisterProtocolSchemes(const webapps::AppId& app_id,
                                        std::vector<std::string> protocols) = 0;
 
  protected:
diff --git a/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.cc b/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.cc
index f4b3f03..c3f95f0c 100644
--- a/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.cc
+++ b/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.cc
@@ -55,7 +55,7 @@
 ProtocolHandlingSubManager::~ProtocolHandlingSubManager() = default;
 
 void ProtocolHandlingSubManager::Configure(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure configure_done) {
   DCHECK(!desired_state.has_protocols_handled());
@@ -82,7 +82,7 @@
 }
 
 void ProtocolHandlingSubManager::Execute(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const absl::optional<SynchronizeOsOptions>& synchronize_options,
     const proto::WebAppOsIntegrationState& desired_state,
     const proto::WebAppOsIntegrationState& current_state,
@@ -146,7 +146,7 @@
       base::IgnoreArgs<Result>(std::move(register_and_complete)));
 }
 
-void ProtocolHandlingSubManager::ForceUnregister(const AppId& app_id,
+void ProtocolHandlingSubManager::ForceUnregister(const webapps::AppId& app_id,
                                                  base::OnceClosure callback) {
   UnregisterProtocolHandlersWithOs(
       app_id, profile_path_,
diff --git a/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.h b/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.h
index a28555b3..2784afb 100644
--- a/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.h
+++ b/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -22,15 +23,15 @@
   ProtocolHandlingSubManager(const base::FilePath& profile_path,
                              WebAppProvider& provider);
   ~ProtocolHandlingSubManager() override;
-  void Configure(const AppId& app_id,
+  void Configure(const webapps::AppId& app_id,
                  proto::WebAppOsIntegrationState& desired_state,
                  base::OnceClosure configure_done) override;
-  void Execute(const AppId& app_id,
+  void Execute(const webapps::AppId& app_id,
                const absl::optional<SynchronizeOsOptions>& synchronize_options,
                const proto::WebAppOsIntegrationState& desired_state,
                const proto::WebAppOsIntegrationState& current_state,
                base::OnceClosure callback) override;
-  void ForceUnregister(const AppId& app_id,
+  void ForceUnregister(const webapps::AppId& app_id,
                        base::OnceClosure callback) override;
 
  private:
diff --git a/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager_unittest.cc
index 43c895b..eb4a334 100644
--- a/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/protocol_handling_sub_manager_unittest.cc
@@ -90,7 +90,7 @@
     WebAppTest::TearDown();
   }
 
-  web_app::AppId InstallWebAppWithProtocolHandlers(
+  webapps::AppId InstallWebAppWithProtocolHandlers(
       const std::vector<apps::ProtocolHandlerInfo>& protocol_handlers) {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
@@ -98,7 +98,8 @@
     info->title = u"Test App";
     info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
     info->protocol_handlers = protocol_handlers;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     // InstallFromInfoWithParams is used instead of InstallFromInfo, because
     // InstallFromInfo doesn't register OS integration.
     provider().scheduler().InstallFromInfoWithParams(
@@ -108,10 +109,10 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success)
-      return AppId();
+      return webapps::AppId();
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
  protected:
@@ -154,7 +155,8 @@
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
 
-  const AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  const webapps::AppId app_id =
+      InstallWebAppWithProtocolHandlers({protocol_handler});
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -182,7 +184,8 @@
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
 
-  const AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  const webapps::AppId app_id =
+      InstallWebAppWithProtocolHandlers({protocol_handler});
   test::UninstallAllWebApps(profile());
 
   auto state =
@@ -203,7 +206,7 @@
   protocol_handler2.url = GURL(handler_url2);
   protocol_handler2.protocol = "web+test+protocol";
 
-  const AppId app_id =
+  const webapps::AppId app_id =
       InstallWebAppWithProtocolHandlers({protocol_handler1, protocol_handler2});
   {
     base::test::TestFuture<void> disallowed_future;
@@ -263,7 +266,7 @@
 
 #if BUILDFLAG(IS_MAC)
   std::vector<std::string> GetAppShimRegisteredProtocolHandlers(
-      const AppId& app_id) {
+      const webapps::AppId& app_id) {
     std::vector<std::string> protocol_schemes;
     for (const auto& [file_path, handler] :
          AppShimRegistry::Get()->GetHandlersForApp(app_id)) {
@@ -293,7 +296,8 @@
       std::string(kWebAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  const AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  const webapps::AppId app_id =
+      InstallWebAppWithProtocolHandlers({protocol_handler});
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -333,7 +337,8 @@
       std::string(kWebAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  const AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  const webapps::AppId app_id =
+      InstallWebAppWithProtocolHandlers({protocol_handler});
   test::UninstallAllWebApps(profile());
 
   auto state =
@@ -369,7 +374,7 @@
   protocol_handler_disapproved.url = GURL(handler_url2);
   protocol_handler_disapproved.protocol = "web+test+protocol";
 
-  const AppId app_id = InstallWebAppWithProtocolHandlers(
+  const webapps::AppId app_id = InstallWebAppWithProtocolHandlers(
       {protocol_handler_approved, protocol_handler_disapproved});
   {
     base::test::TestFuture<void> disallowed_future;
@@ -433,7 +438,8 @@
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
 
-  const AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  const webapps::AppId app_id =
+      InstallWebAppWithProtocolHandlers({protocol_handler});
   {
     base::test::TestFuture<void> future;
     provider().scheduler().UpdateProtocolHandlerUserApproval(
@@ -474,9 +480,9 @@
 }
 
 TEST_P(ProtocolHandlingExecuteTest, MultipleSynchronizeEmptyData) {
-  const AppId app_id1 = InstallWebAppWithProtocolHandlers(
+  const webapps::AppId app_id1 = InstallWebAppWithProtocolHandlers(
       std::vector<apps::ProtocolHandlerInfo>());
-  const AppId app_id2 = InstallWebAppWithProtocolHandlers(
+  const webapps::AppId app_id2 = InstallWebAppWithProtocolHandlers(
       std::vector<apps::ProtocolHandlerInfo>());
   ASSERT_THAT(app_id1, testing::Eq(app_id2));
 
@@ -512,7 +518,8 @@
       std::string(kWebAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  const AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  const webapps::AppId app_id =
+      InstallWebAppWithProtocolHandlers({protocol_handler});
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -555,7 +562,8 @@
       std::string(kWebAppUrl.spec()) + "/testing=%s";
   protocol_handler.url = GURL(handler_url);
   protocol_handler.protocol = "web+test";
-  const AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+  const webapps::AppId app_id =
+      InstallWebAppWithProtocolHandlers({protocol_handler});
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
diff --git a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.cc b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.cc
index f750bc4..71a4cc44 100644
--- a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.cc
+++ b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
@@ -28,6 +27,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_thread.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -80,7 +80,7 @@
 RunOnOsLoginSubManager::~RunOnOsLoginSubManager() = default;
 
 void RunOnOsLoginSubManager::Configure(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure configure_done) {
   DCHECK(!desired_state.has_run_on_os_login());
@@ -102,7 +102,7 @@
 }
 
 void RunOnOsLoginSubManager::Execute(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const absl::optional<SynchronizeOsOptions>& synchronize_options,
     const proto::WebAppOsIntegrationState& desired_state,
     const proto::WebAppOsIntegrationState& current_state,
@@ -134,7 +134,7 @@
                      std::move(execute_done)));
 }
 
-void RunOnOsLoginSubManager::ForceUnregister(const AppId& app_id,
+void RunOnOsLoginSubManager::ForceUnregister(const webapps::AppId& app_id,
                                              base::OnceClosure callback) {
   if (!DoesRunOnOsLoginRequireExecution()) {
     std::move(callback).Run();
@@ -157,7 +157,7 @@
 }
 
 void RunOnOsLoginSubManager::StartUnregistration(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const proto::WebAppOsIntegrationState& current_state,
     const proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure registration_callback) {
@@ -190,7 +190,7 @@
 }
 
 void RunOnOsLoginSubManager::CreateShortcutInfoWithFavicons(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure execute_done) {
   if (!ShouldTriggerRunOnOsLoginRegistration(desired_state)) {
@@ -213,7 +213,7 @@
 }
 
 void RunOnOsLoginSubManager::OnShortcutInfoCreatedStartRegistration(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure execute_done,
     std::unique_ptr<ShortcutInfo> shortcut_info) {
diff --git a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h
index 97f166c..2a3a5db6 100644
--- a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h
+++ b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -26,33 +27,33 @@
   RunOnOsLoginSubManager(Profile& profile, WebAppProvider& provider);
   ~RunOnOsLoginSubManager() override;
 
-  void Configure(const AppId& app_id,
+  void Configure(const webapps::AppId& app_id,
                  proto::WebAppOsIntegrationState& desired_state,
                  base::OnceClosure configure_done) override;
 
-  void Execute(const AppId& app_id,
+  void Execute(const webapps::AppId& app_id,
                const absl::optional<SynchronizeOsOptions>& synchronize_options,
                const proto::WebAppOsIntegrationState& desired_state,
                const proto::WebAppOsIntegrationState& current_state,
                base::OnceClosure execute_done) override;
 
-  void ForceUnregister(const AppId& app_id,
+  void ForceUnregister(const webapps::AppId& app_id,
                        base::OnceClosure callback) override;
 
  private:
   // Unregistration logic.
-  void StartUnregistration(const AppId& app_id,
+  void StartUnregistration(const webapps::AppId& app_id,
                            const proto::WebAppOsIntegrationState& current_state,
                            const proto::WebAppOsIntegrationState& desired_state,
                            base::OnceClosure registration_callback);
 
   // Registration logic.
   void CreateShortcutInfoWithFavicons(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const proto::WebAppOsIntegrationState& desired_state,
       base::OnceClosure execute_done);
   void OnShortcutInfoCreatedStartRegistration(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const proto::WebAppOsIntegrationState& desired_state,
       base::OnceClosure execute_done,
       std::unique_ptr<ShortcutInfo> shortcut_info);
diff --git a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager_unittest.cc
index 1daee8ff..8a590ee 100644
--- a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager_unittest.cc
@@ -78,13 +78,14 @@
     WebAppTest::TearDown();
   }
 
-  AppId InstallWebApp() {
+  webapps::AppId InstallWebApp() {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
     info->start_url = kWebAppUrl;
     info->title = u"Test App";
     info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     // InstallFromInfoWithParams is used instead of InstallFromInfo, because
     // InstallFromInfo doesn't register OS integration.
     provider().scheduler().InstallFromInfoWithParams(
@@ -94,11 +95,11 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
   void SetWebAppSettingsListPref(const base::StringPiece pref) {
@@ -148,7 +149,7 @@
 
 TEST_P(RunOnOsLoginSubManagerConfigureTest,
        VerifyRunOnOsLoginSetProperlyOnInstall) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
 
   auto state = registrar().GetAppCurrentOsIntegrationState(app_id);
   ASSERT_TRUE(state.has_value());
@@ -166,7 +167,7 @@
 }
 
 TEST_P(RunOnOsLoginSubManagerConfigureTest, VerifyRunOnOsLoginSetFromCommand) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
 
   base::test::TestFuture<void> future;
   provider().scheduler().SetRunOnOsLoginMode(
@@ -188,7 +189,7 @@
 }
 
 TEST_P(RunOnOsLoginSubManagerConfigureTest, VerifyPolicySettingBlocked) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
 
   const char kWebAppSettingPolicyBlockedConfig[] = R"([{
     "manifest_id" : "https://example.com/path/index.html",
@@ -220,7 +221,7 @@
 }
 
 TEST_P(RunOnOsLoginSubManagerConfigureTest, VerifyPolicySettingWindowedMode) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
 
   const char kWebAppSettingPolicyWindowedConfig[] = R"([{
     "manifest_id" : "https://example.com/path/index.html",
@@ -252,7 +253,7 @@
 }
 
 TEST_P(RunOnOsLoginSubManagerConfigureTest, VerifyPolicySettingAllowedMode) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
 
   const char kWebAppSettingPolicyAllowedConfig[] = R"([{
     "manifest_id" : "https://example.com/path/index.html",
@@ -284,7 +285,7 @@
 }
 
 TEST_P(RunOnOsLoginSubManagerConfigureTest, StatesEmptyOnUninstall) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   test::UninstallAllWebApps(profile());
   auto state = registrar().GetAppCurrentOsIntegrationState(app_id);
   ASSERT_FALSE(state.has_value());
@@ -333,7 +334,7 @@
 };
 
 TEST_P(RunOnOsLoginSubManagerExecuteTest, InstallRunOnOsLoginNotRun) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   const std::string& app_name = registrar().GetAppShortName(app_id);
 
   auto state = registrar().GetAppCurrentOsIntegrationState(app_id);
@@ -354,7 +355,7 @@
 
 TEST_P(RunOnOsLoginSubManagerExecuteTest,
        InstallAndExecuteWindowedRunOnOsLogin) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   const std::string& app_name = registrar().GetAppShortName(app_id);
 
   base::test::TestFuture<void> future;
@@ -376,7 +377,7 @@
 }
 
 TEST_P(RunOnOsLoginSubManagerExecuteTest, BlockedPolicySettingNoOsIntegration) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   const std::string& app_name = registrar().GetAppShortName(app_id);
 
   const char kWebAppSettingPolicyBlockedConfig[] = R"([{
@@ -409,7 +410,7 @@
 
 TEST_P(RunOnOsLoginSubManagerExecuteTest,
        WindowedPolicySettingAllowsOsIntegration) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   const std::string& app_name = registrar().GetAppShortName(app_id);
 
   const char kWebAppSettingPolicyBlockedConfig[] = R"([{
@@ -441,7 +442,7 @@
 }
 
 TEST_P(RunOnOsLoginSubManagerExecuteTest, UpdateRunOnOsLoginMode) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   const std::string& app_name = registrar().GetAppShortName(app_id);
 
   base::test::TestFuture<void> future_windowed;
@@ -482,7 +483,7 @@
 }
 
 TEST_P(RunOnOsLoginSubManagerExecuteTest, UnregisterRunOnOsLogin) {
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   const std::string& app_name = registrar().GetAppShortName(app_id);
 
   base::test::TestFuture<void> future;
@@ -516,7 +517,7 @@
     GTEST_SKIP()
         << "Force unregistration is only for sub managers that are enabled";
   }
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   const std::string& app_name = registrar().GetAppShortName(app_id);
 
   base::test::TestFuture<void> future;
@@ -546,7 +547,7 @@
     GTEST_SKIP()
         << "Force unregistration is only for sub managers that are enabled";
   }
-  const AppId& app_id = InstallWebApp();
+  const webapps::AppId& app_id = InstallWebApp();
   const std::string& app_name = registrar().GetAppShortName(app_id);
 
   base::test::TestFuture<void> future;
diff --git a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.cc b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.cc
index 8005e03..0df93b7 100644
--- a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.cc
+++ b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.cc
@@ -64,7 +64,7 @@
 ShortcutMenuHandlingSubManager::~ShortcutMenuHandlingSubManager() = default;
 
 void ShortcutMenuHandlingSubManager::Configure(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure configure_done) {
   DCHECK(!desired_state.has_shortcut_menus());
@@ -91,7 +91,7 @@
 }
 
 void ShortcutMenuHandlingSubManager::Execute(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const absl::optional<SynchronizeOsOptions>& synchronize_options,
     const proto::WebAppOsIntegrationState& desired_state,
     const proto::WebAppOsIntegrationState& current_state,
@@ -126,7 +126,7 @@
 }
 
 void ShortcutMenuHandlingSubManager::ForceUnregister(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure callback) {
   if (!ShouldRegisterShortcutsMenuWithOs()) {
     std::move(callback).Run();
@@ -142,7 +142,7 @@
 }
 
 void ShortcutMenuHandlingSubManager::StoreShortcutMenuData(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     std::vector<WebAppShortcutsMenuItemInfo> shortcut_menu_item_info,
     proto::ShortcutMenus* shortcut_menus,
     WebAppIconManager::ShortcutIconDataVector downloaded_shortcut_menu_items) {
@@ -193,7 +193,7 @@
 }
 
 void ShortcutMenuHandlingSubManager::StartShortcutsMenuUnregistration(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const proto::WebAppOsIntegrationState& current_state,
     base::OnceClosure registration_callback) {
   if (!HasShortcutsMenuInfo(current_state)) {
@@ -210,7 +210,7 @@
 }
 
 void ShortcutMenuHandlingSubManager::ReadIconDataForShortcutsMenu(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure execute_complete) {
   if (!HasShortcutsMenuInfo(desired_state)) {
@@ -226,7 +226,7 @@
 }
 
 void ShortcutMenuHandlingSubManager::OnIconDataLoadedRegisterShortcutsMenu(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure execute_complete,
     ShortcutsMenuIconBitmaps shortcut_menu_icon_bitmaps) {
diff --git a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h
index ece83f9..9bee37d 100644
--- a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h
+++ b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
@@ -29,33 +30,33 @@
                                  WebAppProvider& provider);
   ~ShortcutMenuHandlingSubManager() override;
 
-  void Configure(const AppId& app_id,
+  void Configure(const webapps::AppId& app_id,
                  proto::WebAppOsIntegrationState& desired_state,
                  base::OnceClosure configure_done) override;
-  void Execute(const AppId& app_id,
+  void Execute(const webapps::AppId& app_id,
                const absl::optional<SynchronizeOsOptions>& synchronize_options,
                const proto::WebAppOsIntegrationState& desired_state,
                const proto::WebAppOsIntegrationState& current_state,
                base::OnceClosure execute_complete) override;
-  void ForceUnregister(const AppId& app_id,
+  void ForceUnregister(const webapps::AppId& app_id,
                        base::OnceClosure callback) override;
 
  private:
   void StoreShortcutMenuData(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       std::vector<WebAppShortcutsMenuItemInfo> shortcut_menu_item_info,
       proto::ShortcutMenus* shortcut_menus,
       WebAppIconManager::ShortcutIconDataVector data);
   void StartShortcutsMenuUnregistration(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const proto::WebAppOsIntegrationState& current_state,
       base::OnceClosure registration_callback);
   void ReadIconDataForShortcutsMenu(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const proto::WebAppOsIntegrationState& desired_state,
       base::OnceClosure execute_complete);
   void OnIconDataLoadedRegisterShortcutsMenu(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const proto::WebAppOsIntegrationState& desired_state,
       base::OnceClosure execute_complete,
       ShortcutsMenuIconBitmaps shortcut_menu_icon_bitmaps);
diff --git a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager_unittest.cc
index fa0567e..9d96b33a 100644
--- a/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/shortcut_menu_handling_sub_manager_unittest.cc
@@ -152,7 +152,7 @@
     return item_infos;
   }
 
-  web_app::AppId InstallWebAppWithShortcutMenuIcons(
+  webapps::AppId InstallWebAppWithShortcutMenuIcons(
       ShortcutsMenuIconBitmaps shortcuts_menu_icons) {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
@@ -162,7 +162,8 @@
     info->shortcuts_menu_icon_bitmaps = shortcuts_menu_icons;
     info->shortcuts_menu_item_infos =
         CreateShortcutMenuItemInfoFromBitmaps(shortcuts_menu_icons);
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     // InstallFromInfoWithParams is used instead of InstallFromInfo, because
     // InstallFromInfo doesn't register OS integration.
     provider().scheduler().InstallFromInfoWithParams(
@@ -172,11 +173,11 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
  protected:
@@ -214,7 +215,7 @@
 
   const std::vector<int> sizes = {icon_size::k64, icon_size::k128};
   const std::vector<SkColor> colors = {SK_ColorRED, SK_ColorRED};
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+  const webapps::AppId& app_id = InstallWebAppWithShortcutMenuIcons(
       MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
@@ -295,7 +296,7 @@
 
   const std::vector<int> sizes = {icon_size::k64, icon_size::k128};
   const std::vector<SkColor> colors = {SK_ColorRED, SK_ColorRED};
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+  const webapps::AppId& app_id = InstallWebAppWithShortcutMenuIcons(
       MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
@@ -330,7 +331,8 @@
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
                       num_menu_items);
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(icon_bitmaps);
+  const webapps::AppId& app_id =
+      InstallWebAppWithShortcutMenuIcons(icon_bitmaps);
 
   // Create a single WebAppShortcutsMenuItemInfo.
   WebAppShortcutsMenuItemInfo shortcut_info;
@@ -403,7 +405,7 @@
 
   const std::vector<int> sizes = {icon_size::k64, icon_size::k128};
   const std::vector<SkColor> colors = {SK_ColorRED, SK_ColorRED};
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+  const webapps::AppId& app_id = InstallWebAppWithShortcutMenuIcons(
       MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
@@ -463,7 +465,7 @@
 
   const std::vector<int> sizes = {icon_size::k64, icon_size::k128};
   const std::vector<SkColor> colors = {SK_ColorRED, SK_ColorRED};
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+  const webapps::AppId& app_id = InstallWebAppWithShortcutMenuIcons(
       MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
@@ -500,7 +502,7 @@
 
 TEST_P(ShortcutMenuHandlingSubManagerExecuteTest,
        EmptyDataDoesNotRegisterShortcutsMenu) {
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebAppWithShortcutMenuIcons(ShortcutsMenuIconBitmaps());
 
   auto state =
@@ -532,7 +534,7 @@
                                   icon_size::k256};
   const std::vector<SkColor> colors = {SK_ColorBLUE, SK_ColorBLUE,
                                        SK_ColorBLUE};
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+  const webapps::AppId& app_id = InstallWebAppWithShortcutMenuIcons(
       MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
@@ -589,7 +591,7 @@
   const int num_menu_items = 2;
   const std::vector<int> sizes = {icon_size::k32, icon_size::k48};
   const std::vector<SkColor> colors = {SK_ColorCYAN, SK_ColorCYAN};
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+  const webapps::AppId& app_id = InstallWebAppWithShortcutMenuIcons(
       MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
@@ -628,7 +630,7 @@
                                           icon_size::k256};
   const std::vector<SkColor> updated_colors = {SK_ColorYELLOW, SK_ColorYELLOW,
                                                SK_ColorYELLOW};
-  const AppId& updated_app_id =
+  const webapps::AppId& updated_app_id =
       InstallWebAppWithShortcutMenuIcons(MakeIconBitmaps(
           {{IconPurpose::ANY, updated_sizes, updated_colors},
            {IconPurpose::MASKABLE, updated_sizes, updated_colors},
@@ -676,7 +678,7 @@
 
   const std::vector<int> sizes = {icon_size::k64, icon_size::k128};
   const std::vector<SkColor> colors = {SK_ColorRED, SK_ColorRED};
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+  const webapps::AppId& app_id = InstallWebAppWithShortcutMenuIcons(
       MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
@@ -722,7 +724,7 @@
 
   const std::vector<int> sizes = {icon_size::k64, icon_size::k128};
   const std::vector<SkColor> colors = {SK_ColorRED, SK_ColorRED};
-  const AppId& app_id = InstallWebAppWithShortcutMenuIcons(
+  const webapps::AppId& app_id = InstallWebAppWithShortcutMenuIcons(
       MakeIconBitmaps({{IconPurpose::ANY, sizes, colors},
                        {IconPurpose::MASKABLE, sizes, colors},
                        {IconPurpose::MONOCHROME, sizes, colors}},
diff --git a/chrome/browser/web_applications/os_integration/shortcut_sub_manager.cc b/chrome/browser/web_applications/os_integration/shortcut_sub_manager.cc
index d518d83a..5be13ac 100644
--- a/chrome/browser/web_applications/os_integration/shortcut_sub_manager.cc
+++ b/chrome/browser/web_applications/os_integration/shortcut_sub_manager.cc
@@ -51,7 +51,7 @@
 ShortcutSubManager::~ShortcutSubManager() = default;
 
 void ShortcutSubManager::Configure(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure configure_done) {
   DCHECK(!desired_state.has_shortcut());
@@ -74,7 +74,7 @@
 }
 
 void ShortcutSubManager::Execute(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const absl::optional<SynchronizeOsOptions>& synchronize_options,
     const proto::WebAppOsIntegrationState& desired_state,
     const proto::WebAppOsIntegrationState& current_state,
@@ -224,7 +224,7 @@
   std::move(callback_for_no_update).Run();
 }
 
-void ShortcutSubManager::ForceUnregister(const AppId& app_id,
+void ShortcutSubManager::ForceUnregister(const webapps::AppId& app_id,
                                          base::OnceClosure callback) {
   base::FilePath shortcut_data_dir = GetOsIntegrationResourcesDirectoryForApp(
       profile_->GetPath(), app_id,
@@ -244,7 +244,7 @@
 }
 
 void ShortcutSubManager::CreateShortcut(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     absl::optional<SynchronizeOsOptions> synchronize_options,
     base::OnceClosure on_complete,
     std::unique_ptr<ShortcutInfo> shortcut_info) {
@@ -269,7 +269,7 @@
 }
 
 void ShortcutSubManager::UpdateShortcut(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     absl::optional<SynchronizeOsOptions> synchronize_options,
     const std::u16string& old_app_title,
     base::OnceClosure on_complete,
@@ -297,7 +297,7 @@
       }).Then(std::move(on_complete)));
 }
 
-void ShortcutSubManager::OnShortcutsDeleted(const AppId& app_id,
+void ShortcutSubManager::OnShortcutsDeleted(const webapps::AppId& app_id,
                                             base::OnceClosure final_callback,
                                             bool success) {
   ResultCallback final_result_callback =
diff --git a/chrome/browser/web_applications/os_integration/shortcut_sub_manager.h b/chrome/browser/web_applications/os_integration/shortcut_sub_manager.h
index 6b5c4c6..a6cf810e 100644
--- a/chrome/browser/web_applications/os_integration/shortcut_sub_manager.h
+++ b/chrome/browser/web_applications/os_integration/shortcut_sub_manager.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -31,28 +32,28 @@
  public:
   ShortcutSubManager(Profile& profile, WebAppProvider& provider);
   ~ShortcutSubManager() override;
-  void Configure(const AppId& app_id,
+  void Configure(const webapps::AppId& app_id,
                  proto::WebAppOsIntegrationState& desired_state,
                  base::OnceClosure configure_done) override;
-  void Execute(const AppId& app_id,
+  void Execute(const webapps::AppId& app_id,
                const absl::optional<SynchronizeOsOptions>& synchronize_options,
                const proto::WebAppOsIntegrationState& desired_state,
                const proto::WebAppOsIntegrationState& current_state,
                base::OnceClosure callback) override;
-  void ForceUnregister(const AppId& app_id,
+  void ForceUnregister(const webapps::AppId& app_id,
                        base::OnceClosure callback) override;
 
  private:
-  void CreateShortcut(const AppId& app_id,
+  void CreateShortcut(const webapps::AppId& app_id,
                       absl::optional<SynchronizeOsOptions> synchronize_options,
                       base::OnceClosure on_complete,
                       std::unique_ptr<ShortcutInfo> shortcut_info);
-  void UpdateShortcut(const AppId& app_id,
+  void UpdateShortcut(const webapps::AppId& app_id,
                       absl::optional<SynchronizeOsOptions> synchronize_options,
                       const std::u16string& old_app_title,
                       base::OnceClosure on_complete,
                       std::unique_ptr<ShortcutInfo> shortcut_info);
-  void OnShortcutsDeleted(const AppId& app_id,
+  void OnShortcutsDeleted(const webapps::AppId& app_id,
                           base::OnceClosure final_callback,
                           bool success);
   void StoreIconDataFromDisk(proto::ShortcutDescription* shortcut,
diff --git a/chrome/browser/web_applications/os_integration/shortcut_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/shortcut_sub_manager_unittest.cc
index 882a1f82..a2bde35 100644
--- a/chrome/browser/web_applications/os_integration/shortcut_sub_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/shortcut_sub_manager_unittest.cc
@@ -80,7 +80,7 @@
     WebAppTest::TearDown();
   }
 
-  web_app::AppId InstallWebAppWithShortcuts(
+  webapps::AppId InstallWebAppWithShortcuts(
       std::map<SquareSizePx, SkBitmap> icon_map) {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
@@ -88,7 +88,8 @@
     info->title = u"Test App";
     info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
     info->icon_bitmaps.any = std::move(icon_map);
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     provider().scheduler().InstallFromInfoWithParams(
         std::move(info), /*overwrite_existing_manifest_fields=*/true,
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
@@ -96,11 +97,11 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
  protected:
@@ -146,7 +147,8 @@
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
   icon_map[icon_size::k512] =
       CreateSolidColorIcon(icon_size::k512, SK_ColorYELLOW);
-  const AppId& app_id = InstallWebAppWithShortcuts(std::move(icon_map));
+  const webapps::AppId& app_id =
+      InstallWebAppWithShortcuts(std::move(icon_map));
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -177,7 +179,8 @@
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
   icon_map[icon_size::k512] =
       CreateSolidColorIcon(icon_size::k512, SK_ColorYELLOW);
-  const AppId& app_id = InstallWebAppWithShortcuts(std::move(icon_map));
+  const webapps::AppId& app_id =
+      InstallWebAppWithShortcuts(std::move(icon_map));
 
   test::UninstallAllWebApps(profile());
   auto state =
@@ -217,7 +220,8 @@
 #endif
   }
 
-  SkColor GetShortcutColor(const AppId& app_id, const std::string& app_name) {
+  SkColor GetShortcutColor(const webapps::AppId& app_id,
+                           const std::string& app_name) {
     if (!HasShortcutsOsIntegration()) {
       return SK_ColorTRANSPARENT;
     }
@@ -253,7 +257,7 @@
 #endif
   }
 
-  AppId UpdateInstalledWebAppWithNewIcons(
+  webapps::AppId UpdateInstalledWebAppWithNewIcons(
       std::map<SquareSizePx, SkBitmap> updated_icons) {
     std::unique_ptr<WebAppInstallInfo> updated_info =
         std::make_unique<WebAppInstallInfo>();
@@ -263,22 +267,22 @@
         web_app::mojom::UserDisplayMode::kStandalone;
     updated_info->icon_bitmaps.any = std::move(updated_icons);
 
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode,
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode,
                            OsHooksErrors>
         update_future;
     provider().install_finalizer().FinalizeUpdate(*updated_info,
                                                   update_future.GetCallback());
     bool success = update_future.Wait();
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(update_future.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessAlreadyInstalled);
     EXPECT_TRUE(update_future.Get<OsHooksErrors>().none());
-    return update_future.Get<AppId>();
+    return update_future.Get<webapps::AppId>();
   }
 
-  AppId InstallWebAppWithIconsNoShortcuts(
+  webapps::AppId InstallWebAppWithIconsNoShortcuts(
       std::map<SquareSizePx, SkBitmap> icon_map) {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
@@ -286,7 +290,8 @@
     info->title = u"Test App";
     info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
     info->icon_bitmaps.any = std::move(icon_map);
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     // InstallFromInfo() does not trigger OS integration.
     provider().scheduler().InstallFromInfo(
         std::move(info), /*overwrite_existing_manifest_fields=*/true,
@@ -295,11 +300,11 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
  private:
@@ -312,7 +317,8 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id = InstallWebAppWithShortcuts(std::move(icon_map));
+  const webapps::AppId& app_id =
+      InstallWebAppWithShortcuts(std::move(icon_map));
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -343,7 +349,8 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorYELLOW);
-  const AppId& app_id = InstallWebAppWithShortcuts(std::move(icon_map));
+  const webapps::AppId& app_id =
+      InstallWebAppWithShortcuts(std::move(icon_map));
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -367,7 +374,7 @@
   std::map<SquareSizePx, SkBitmap> updated_icon_map;
   updated_icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorBLUE);
-  const AppId& updated_app_id =
+  const webapps::AppId& updated_app_id =
       UpdateInstalledWebAppWithNewIcons(std::move(updated_icon_map));
   EXPECT_EQ(updated_app_id, app_id);
 
@@ -401,7 +408,8 @@
   // Install an app with icons but no shortcuts.
   std::map<SquareSizePx, SkBitmap> icon_map;
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
-  const AppId& app_id = InstallWebAppWithIconsNoShortcuts(std::move(icon_map));
+  const webapps::AppId& app_id =
+      InstallWebAppWithIconsNoShortcuts(std::move(icon_map));
 
   // Call synchronize with empty options to set up the current_states, but
   // without any shortcut locations defined.
@@ -432,7 +440,7 @@
   std::map<SquareSizePx, SkBitmap> new_icons;
   new_icons[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorYELLOW);
-  const AppId& expected_app_id =
+  const webapps::AppId& expected_app_id =
       InstallWebAppWithShortcuts(std::move(new_icons));
   ASSERT_EQ(expected_app_id, app_id);
 
@@ -469,7 +477,8 @@
       CreateSolidColorIcon(icon_size::k16, SK_ColorYELLOW);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorRED);
-  const AppId& app_id = InstallWebAppWithShortcuts(std::move(icon_map));
+  const webapps::AppId& app_id =
+      InstallWebAppWithShortcuts(std::move(icon_map));
 
   auto state =
       provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
@@ -508,7 +517,8 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id = InstallWebAppWithShortcuts(std::move(icon_map));
+  const webapps::AppId& app_id =
+      InstallWebAppWithShortcuts(std::move(icon_map));
   const std::string& app_name =
       provider().registrar_unsafe().GetAppShortName(app_id);
 
@@ -546,7 +556,8 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id = InstallWebAppWithShortcuts(std::move(icon_map));
+  const webapps::AppId& app_id =
+      InstallWebAppWithShortcuts(std::move(icon_map));
   const std::string& app_name =
       provider().registrar_unsafe().GetAppShortName(app_id);
 
diff --git a/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.cc b/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.cc
index c2050aed..ffc3afd 100644
--- a/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.cc
+++ b/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.cc
@@ -46,7 +46,7 @@
     ~UninstallationViaOsSettingsSubManager() = default;
 
 void UninstallationViaOsSettingsSubManager::Configure(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     proto::WebAppOsIntegrationState& desired_state,
     base::OnceClosure configure_done) {
   DCHECK(!desired_state.has_uninstall_registration());
@@ -72,7 +72,7 @@
 }
 
 void UninstallationViaOsSettingsSubManager::Execute(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const absl::optional<SynchronizeOsOptions>& synchronize_options,
     const proto::WebAppOsIntegrationState& desired_state,
     const proto::WebAppOsIntegrationState& current_state,
@@ -107,7 +107,7 @@
 }
 
 void UninstallationViaOsSettingsSubManager::ForceUnregister(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure callback) {
   if (IsOsUninstallationSupported()) {
     CompleteUnregistration(app_id);
@@ -116,7 +116,7 @@
 }
 
 void UninstallationViaOsSettingsSubManager::CompleteUnregistration(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   bool result =
       UnregisterUninstallationViaOsSettingsWithOs(app_id, profile_path_);
   base::UmaHistogramBoolean("WebApp.OsSettingsUninstallUnregistration.Result",
diff --git a/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.h b/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.h
index 4a13592..a713d1a 100644
--- a/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.h
+++ b/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h"
 #include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
@@ -26,19 +27,19 @@
                                         WebAppProvider& provider);
   ~UninstallationViaOsSettingsSubManager() override;
 
-  void Configure(const AppId& app_id,
+  void Configure(const webapps::AppId& app_id,
                  proto::WebAppOsIntegrationState& desired_state,
                  base::OnceClosure configure_done) override;
-  void Execute(const AppId& app_id,
+  void Execute(const webapps::AppId& app_id,
                const absl::optional<SynchronizeOsOptions>& synchronize_options,
                const proto::WebAppOsIntegrationState& desired_state,
                const proto::WebAppOsIntegrationState& current_state,
                base::OnceClosure callback) override;
-  void ForceUnregister(const AppId& app_id,
+  void ForceUnregister(const webapps::AppId& app_id,
                        base::OnceClosure callback) override;
 
  private:
-  void CompleteUnregistration(const AppId& app_id);
+  void CompleteUnregistration(const webapps::AppId& app_id);
   const base::FilePath profile_path_;
   const raw_ref<WebAppProvider> provider_;
   base::WeakPtrFactory<UninstallationViaOsSettingsSubManager> weak_factory_{
diff --git a/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc
index 9aaa6c83..d4502c7 100644
--- a/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc
@@ -89,14 +89,15 @@
     WebAppTest::TearDown();
   }
 
-  web_app::AppId InstallWebApp(webapps::WebappInstallSource install_source) {
+  webapps::AppId InstallWebApp(webapps::WebappInstallSource install_source) {
     std::unique_ptr<WebAppInstallInfo> info =
         std::make_unique<WebAppInstallInfo>();
     info->start_url = kWebAppUrl;
     info->title = u"Test App";
     info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
     auto source = install_source;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     // InstallFromInfoWithParams is used instead of InstallFromInfo, because
     // InstallFromInfo doesn't register OS integration.
     provider().scheduler().InstallFromInfoWithParams(
@@ -105,11 +106,11 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
   OsIntegrationTestOverrideImpl& test_override() const {
@@ -135,7 +136,7 @@
 }
 
 TEST_P(UninstallationViaOsSettingsSubManagerTest, TestUserUninstallable) {
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebApp(webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
 
   auto state =
@@ -160,7 +161,7 @@
 }
 
 TEST_P(UninstallationViaOsSettingsSubManagerTest, TestNotUserUninstallable) {
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebApp(webapps::WebappInstallSource::EXTERNAL_POLICY);
 
   auto state =
@@ -188,7 +189,7 @@
 }
 
 TEST_P(UninstallationViaOsSettingsSubManagerTest, UninstallApp) {
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebApp(webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
   test::UninstallAllWebApps(profile());
   auto state =
@@ -200,7 +201,7 @@
 // the app has been uninstalled.
 TEST_P(UninstallationViaOsSettingsSubManagerTest,
        OsStatesCleanupAfterAppUninstallation) {
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebApp(webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
 
   auto state =
diff --git a/chrome/browser/web_applications/os_integration/url_handler_manager.h b/chrome/browser/web_applications/os_integration/url_handler_manager.h
index 3bb9073..2ca4e07e 100644
--- a/chrome/browser/web_applications/os_integration/url_handler_manager.h
+++ b/chrome/browser/web_applications/os_integration/url_handler_manager.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_origin_association_manager.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -30,13 +31,13 @@
   UrlHandlerManager& operator=(const UrlHandlerManager&) = delete;
 
   // Returns Result::kOk if registration succeeds, Result::kError otherwise.
-  virtual void RegisterUrlHandlers(const AppId& app_id,
+  virtual void RegisterUrlHandlers(const webapps::AppId& app_id,
                                    ResultCallback callback) = 0;
   // Returns true if unregistration succeeds, false otherwise.
-  virtual bool UnregisterUrlHandlers(const AppId& app_id) = 0;
+  virtual bool UnregisterUrlHandlers(const webapps::AppId& app_id) = 0;
   // Returns true if update succeeds, false otherwise.
   virtual void UpdateUrlHandlers(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceCallback<void(bool success)> callback) = 0;
 
   void SetAssociationManagerForTesting(
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc
index 36bcf54..5fb7359 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc
@@ -65,7 +65,7 @@
 }
 
 void WebAppFileHandlerManager::EnableAndRegisterOsFileHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ResultCallback callback) {
   SetOsIntegrationState(app_id, OsIntegrationState::kEnabled);
 
@@ -91,7 +91,7 @@
 }
 
 void WebAppFileHandlerManager::DisableAndUnregisterOsFileHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ResultCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
@@ -120,7 +120,7 @@
 }
 
 const apps::FileHandlers* WebAppFileHandlerManager::GetEnabledFileHandlers(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   if (ShouldOsIntegrationBeEnabled(app_id) &&
       !provider_->registrar_unsafe().IsAppFileHandlerPermissionBlocked(
           app_id)) {
@@ -138,7 +138,7 @@
 }
 
 const apps::FileHandlers* WebAppFileHandlerManager::GetAllFileHandlers(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   return web_app && !web_app->file_handlers().empty()
              ? &web_app->file_handlers()
@@ -151,7 +151,7 @@
 
 WebAppFileHandlerManager::LaunchInfos
 WebAppFileHandlerManager::GetMatchingFileHandlerUrls(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<base::FilePath>& launch_files) {
   LaunchInfos launch_infos;
   if (launch_files.empty() ||
@@ -200,14 +200,14 @@
 }
 
 void WebAppFileHandlerManager::SetOsIntegrationState(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     OsIntegrationState os_state) {
   ScopedRegistryUpdate update = provider_->sync_bridge_unsafe().BeginUpdate();
   update->UpdateApp(app_id)->SetFileHandlerOsIntegrationState(os_state);
 }
 
 bool WebAppFileHandlerManager::ShouldOsIntegrationBeEnabled(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   return !ShouldRegisterFileHandlersWithOs() ||
          (provider_ && provider_->registrar_unsafe()
                            .ExpectThatFileHandlersAreRegisteredWithOs(app_id));
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h
index 53dc253..bba4493d 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -44,25 +45,26 @@
   // each client to be created. Some or all of `launch_files` may not result in
   // launches, but no file will be represented in more than one launch.
   LaunchInfos GetMatchingFileHandlerUrls(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<base::FilePath>& launch_files);
 
   // Enables and registers OS specific file handlers for OSs that need them.
   // Currently on Chrome OS, file handlers are enabled and registered as long as
   // the app is installed.
-  void EnableAndRegisterOsFileHandlers(const AppId& app_id,
+  void EnableAndRegisterOsFileHandlers(const webapps::AppId& app_id,
                                        ResultCallback callback);
 
   // Disables file handlers for all OSs and unregisters OS specific file
   // handlers for OSs that need them. On Chrome OS file handlers are registered
   // separately but they are still enabled and disabled here.
-  void DisableAndUnregisterOsFileHandlers(const AppId& app_id,
+  void DisableAndUnregisterOsFileHandlers(const webapps::AppId& app_id,
                                           ResultCallback callback);
 
   // Gets all enabled file handlers for |app_id|. |nullptr| if the app has no
   // enabled file handlers. Note: The lifetime of the file handlers are tied to
   // the app they belong to.
-  const apps::FileHandlers* GetEnabledFileHandlers(const AppId& app_id) const;
+  const apps::FileHandlers* GetEnabledFileHandlers(
+      const webapps::AppId& app_id) const;
 
   // Returns true when the system supports file type association icons.
   static bool IconsEnabled();
@@ -73,7 +75,7 @@
   // Note: The lifetime of the file handlers are tied to the app they belong to.
   // `virtual` for testing.
   virtual const apps::FileHandlers* GetAllFileHandlers(
-      const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
   virtual bool IsDisabledForTesting();
 
@@ -82,12 +84,13 @@
   // the OS. In theory, this should match the actual OS integration state (e.g.
   // the contents of the .desktop file on Linux), however, that's only enforced
   // on a best-effort basis.
-  void SetOsIntegrationState(const AppId& app_id, OsIntegrationState os_state);
+  void SetOsIntegrationState(const webapps::AppId& app_id,
+                             OsIntegrationState os_state);
 
   // Indicates whether file handlers should be OS-registered for an app. As with
   // `SetOsIntegrationState()`, there may be a mismatch with the actual OS
   // registry.
-  bool ShouldOsIntegrationBeEnabled(const AppId& app_id) const;
+  bool ShouldOsIntegrationBeEnabled(const webapps::AppId& app_id) const;
 
   static bool disable_automatic_file_handler_cleanup_for_testing_;
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc
index 578c1b2..8598956 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc
@@ -191,12 +191,12 @@
     return *file_handler_manager_;
   }
 
-  const AppId& app_id() const { return app_id_; }
+  const webapps::AppId& app_id() const { return app_id_; }
 
  private:
   raw_ptr<FakeWebAppFileHandlerManager> file_handler_manager_ = nullptr;
 
-  AppId app_id_;
+  webapps::AppId app_id_;
 };
 
 TEST_F(WebAppFileHandlerManagerTest, FileHandlersAreNotAvailableUnlessEnabled) {
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration.cc
index 1a20b1c..54abb2eb 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration.cc
@@ -22,7 +22,7 @@
   return false;
 }
 
-void RegisterFileHandlersWithOs(const AppId& app_id,
+void RegisterFileHandlersWithOs(const webapps::AppId& app_id,
                                 const std::string& app_name,
                                 const base::FilePath& profile_path,
                                 const apps::FileHandlers& file_handlers,
@@ -32,7 +32,7 @@
   std::move(callback).Run(Result::kOk);
 }
 
-void UnregisterFileHandlersWithOs(const AppId& app_id,
+void UnregisterFileHandlersWithOs(const webapps::AppId& app_id,
                                   const base::FilePath& profile_path,
                                   ResultCallback callback) {
   DCHECK(ShouldRegisterFileHandlersWithOs());
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration.h b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration.h
index d79e3cc2..f56aba67 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration.h
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -31,7 +32,7 @@
 // This may also involve creating a shim app to launch Chrome from.
 // Note: Some operating systems (such as Chrome OS) may not need to do any work
 // here.
-void RegisterFileHandlersWithOs(const AppId& app_id,
+void RegisterFileHandlersWithOs(const webapps::AppId& app_id,
                                 const std::string& app_name,
                                 const base::FilePath& profile_path,
                                 const apps::FileHandlers& file_handlers,
@@ -39,7 +40,7 @@
 
 // Undo the file extensions registration for the PWA with specified |app_id|.
 // If a shim app was required, also removes the shim app.
-void UnregisterFileHandlersWithOs(const AppId& app_id,
+void UnregisterFileHandlersWithOs(const webapps::AppId& app_id,
                                   const base::FilePath& profile_path,
                                   ResultCallback callback);
 
@@ -54,7 +55,7 @@
 // specified in the manifest are only .csv and .md, .txt files are also
 // registered as file handlers, and the file is launched.
 // TODO(crbug.com/1431463): Implement stricter handling w.r.t file extensions.
-void InstallMimeInfoOnLinux(const AppId& app_id,
+void InstallMimeInfoOnLinux(const webapps::AppId& app_id,
                             const base::FilePath& profile_path,
                             const apps::FileHandlers& file_handlers,
                             ResultCallback done_callback);
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux.cc
index 49125027..c0db58e 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux.cc
@@ -151,7 +151,7 @@
   return success;
 }
 
-void UninstallMimeInfoOnLinux(const AppId& app_id,
+void UninstallMimeInfoOnLinux(const webapps::AppId& app_id,
                               const base::FilePath& profile_path,
                               ResultCallback on_done) {
   base::FilePath filename =
@@ -181,7 +181,7 @@
   return false;
 }
 
-void RegisterFileHandlersWithOs(const AppId& app_id,
+void RegisterFileHandlersWithOs(const webapps::AppId& app_id,
                                 const std::string& app_name,
                                 const base::FilePath& profile_path,
                                 const apps::FileHandlers& file_handlers,
@@ -191,13 +191,13 @@
                          std::move(callback));
 }
 
-void UnregisterFileHandlersWithOs(const AppId& app_id,
+void UnregisterFileHandlersWithOs(const webapps::AppId& app_id,
                                   const base::FilePath& profile_path,
                                   ResultCallback callback) {
   UninstallMimeInfoOnLinux(app_id, profile_path, std::move(callback));
 }
 
-void InstallMimeInfoOnLinux(const AppId& app_id,
+void InstallMimeInfoOnLinux(const webapps::AppId& app_id,
                             const base::FilePath& profile_path,
                             const apps::FileHandlers& file_handlers,
                             ResultCallback done_callback) {
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux_browsertest.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux_browsertest.cc
index 9da17bff..80b4f3ff 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux_browsertest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux_browsertest.cc
@@ -21,11 +21,11 @@
 #include "chrome/browser/web_applications/external_install_options.h"
 #include "chrome/browser/web_applications/test/os_integration_test_override_impl.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -128,9 +128,9 @@
   InstallApp(install_options);
 
   loop.Run();
-  absl::optional<AppId> app_id = WebAppProvider::GetForTest(profile())
-                                     ->registrar_unsafe()
-                                     .LookupExternalAppId(url);
+  absl::optional<webapps::AppId> app_id = WebAppProvider::GetForTest(profile())
+                                              ->registrar_unsafe()
+                                              .LookupExternalAppId(url);
   EXPECT_TRUE(app_id.has_value());
 
   base::FilePath expected_filename =
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_mac.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_mac.cc
index 56938ce..acd28fc 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_mac.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_mac.cc
@@ -8,8 +8,8 @@
 #include "chrome/browser/web_applications/app_shim_registry_mac.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -22,7 +22,7 @@
   return false;
 }
 
-void RegisterFileHandlersWithOs(const AppId& app_id,
+void RegisterFileHandlersWithOs(const webapps::AppId& app_id,
                                 const std::string& app_name,
                                 const base::FilePath& profile_path,
                                 const apps::FileHandlers& file_handlers,
@@ -38,7 +38,7 @@
   std::move(callback).Run(Result::kOk);
 }
 
-void UnregisterFileHandlersWithOs(const AppId& app_id,
+void UnregisterFileHandlersWithOs(const webapps::AppId& app_id,
                                   const base::FilePath& profile_path,
                                   ResultCallback callback) {
   // File handler information is embedded in the app shims. When those are
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_win.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_win.cc
index e7aeefb..8778ece 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_win.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_win.cc
@@ -31,7 +31,7 @@
   return false;
 }
 
-void RegisterFileHandlersWithOsTask(const AppId& app_id,
+void RegisterFileHandlersWithOsTask(const webapps::AppId& app_id,
                                     const std::wstring& app_name,
                                     const base::FilePath& profile_path,
                                     const apps::FileHandlers& file_handlers,
@@ -94,7 +94,7 @@
       GetProgIdForApp(profile_path, app_id), file_handler_progids);
 }
 
-void RegisterFileHandlersWithOs(const AppId& app_id,
+void RegisterFileHandlersWithOs(const webapps::AppId& app_id,
                                 const std::string& app_name,
                                 const base::FilePath& profile_path,
                                 const apps::FileHandlers& file_handlers,
@@ -120,7 +120,7 @@
   base::DeleteFile(launcher_path);
 }
 
-void UnregisterFileHandlersWithOs(const AppId& app_id,
+void UnregisterFileHandlersWithOs(const webapps::AppId& app_id,
                                   const base::FilePath& profile_path,
                                   ResultCallback callback) {
   // The app-specific-launcher file name must be calculated before cleaning up
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_win_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_win_unittest.cc
index 8a42e03..1e1404aa 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_win_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_win_unittest.cc
@@ -87,7 +87,7 @@
   TestingProfileManager* testing_profile_manager() {
     return testing_profile_manager_.get();
   }
-  const AppId& app_id() const { return app_id_; }
+  const webapps::AppId& app_id() const { return app_id_; }
 
   const std::wstring file_handler1_prog_id() { return file_handler1_prog_id_; }
   const std::wstring file_handler2_prog_id() { return file_handler2_prog_id_; }
@@ -160,7 +160,7 @@
   // Returns the expected app launcher path inside the subdirectory for
   // |app_id|.
   base::FilePath GetLauncherPathForApp(Profile* profile,
-                                       const AppId app_id,
+                                       const webapps::AppId app_id,
                                        const std::string& sanitized_app_name) {
     base::FilePath web_app_dir(GetOsIntegrationResourcesDirectoryForApp(
         profile->GetPath(), app_id, GURL()));
@@ -177,7 +177,7 @@
       content::BrowserTaskEnvironment::IO_MAINLOOP};
   raw_ptr<TestingProfile> profile_ = nullptr;
   std::unique_ptr<TestingProfileManager> testing_profile_manager_;
-  const AppId app_id_ = "app_id";
+  const webapps::AppId app_id_ = "app_id";
   // These are set in SetUp() and are the ProgIds for file handlers in the
   // default profile.
   std::wstring file_handler1_prog_id_;
diff --git a/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win.cc b/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win.cc
index b8e8b6a..9c9532b 100644
--- a/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win.cc
@@ -23,10 +23,10 @@
 #include "chrome/browser/shell_integration.h"
 #include "chrome/browser/web_applications/chrome_pwa_launcher/chrome_pwa_launcher_util.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut_win.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/install_static/install_util.h"
 #include "chrome/installer/util/shell_util.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/filename_util.h"
 
@@ -46,7 +46,7 @@
 // only installed in exactly one other profile, it will need its app name
 // updated.
 bool IsWebAppLauncherRegisteredWithWindows(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& cur_profile_path,
     base::FilePath* only_profile_with_app_installed) {
   ProfileManager* profile_manager = g_browser_process->profile_manager();
@@ -90,7 +90,7 @@
   return app_name_extension;
 }
 
-Result UpdateAppRegistration(const AppId& app_id,
+Result UpdateAppRegistration(const webapps::AppId& app_id,
                              const std::wstring& app_name,
                              const base::FilePath& profile_path,
                              const std::wstring& prog_id,
@@ -140,7 +140,7 @@
 // registries. Changes to how they are generated will be disruptive to
 // previously written values, and should therefore be avoided if possible.
 std::wstring GetProgId(const base::FilePath& profile_path,
-                       const AppId& app_id,
+                       const webapps::AppId& app_id,
                        const absl::optional<std::set<std::string>>&
                            file_extensions = absl::nullopt) {
   // On system-level Win7 installs of the browser we need a user-specific part
@@ -173,7 +173,7 @@
 
 }  // namespace
 
-base::CommandLine GetAppLauncherCommand(const AppId& app_id,
+base::CommandLine GetAppLauncherCommand(const webapps::AppId& app_id,
                                         const base::FilePath& app_launcher_path,
                                         const base::FilePath& profile_path) {
   base::CommandLine app_launcher_command(app_launcher_path);
@@ -183,7 +183,7 @@
 }
 
 std::wstring GetAppNameExtensionForNextInstall(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path) {
   // Return a profile-specific app name extension only if duplicate |app_id|
   // installations exist in other profiles.
@@ -220,13 +220,13 @@
 // Windows registry, the mapping between a given profile+app_id and a prog_id
 // can not be changed.
 std::wstring GetProgIdForApp(const base::FilePath& profile_path,
-                             const AppId& app_id) {
+                             const webapps::AppId& app_id) {
   return GetProgId(profile_path, app_id);
 }
 
 std::wstring GetProgIdForAppFileHandler(
     const base::FilePath& profile_path,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::set<std::string>& file_extensions) {
   return GetProgId(profile_path, app_id, file_extensions);
 }
@@ -268,7 +268,7 @@
 }
 
 void CheckAndUpdateExternalInstallations(const base::FilePath& cur_profile_path,
-                                         const AppId& app_id,
+                                         const webapps::AppId& app_id,
                                          ResultCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win.h b/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win.h
index 429c844..23742b9 100644
--- a/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win.h
+++ b/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win.h
@@ -13,18 +13,19 @@
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut_win.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
 
-base::CommandLine GetAppLauncherCommand(const AppId& app_id,
+base::CommandLine GetAppLauncherCommand(const webapps::AppId& app_id,
                                         const base::FilePath& app_launcher_path,
                                         const base::FilePath& profile_path);
 
 // Returns the extension required for new installations of |app_id| based on
 // current state of duplicate installations of |app_id| in other profiles.
 std::wstring GetAppNameExtensionForNextInstall(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path);
 
 base::FilePath GetAppSpecificLauncherFilename(const std::wstring& app_name);
@@ -34,7 +35,7 @@
 // Windows registry, the mapping between a given profile+app_id and a prog_id
 // can not be changed.
 std::wstring GetProgIdForApp(const base::FilePath& profile_path,
-                             const AppId& app_id);
+                             const webapps::AppId& app_id);
 
 // Returns the prog_id for a file handler for |app_id| that handles the given
 // |file_extensions|. An app's handled file extensions are encoded into its
@@ -47,7 +48,7 @@
 // file_extensions combination can't be changed.
 std::wstring GetProgIdForAppFileHandler(
     const base::FilePath& profile_path,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::set<std::string>& file_extensions);
 
 // Makes an app-specific copy of chrome_pwa_launcher.exe that lives in the web
@@ -61,7 +62,7 @@
 // Checks if there is an installation of this app in another profile that needs
 // to be updated with a profile specific name and executes required update.
 void CheckAndUpdateExternalInstallations(const base::FilePath& cur_profile_path,
-                                         const AppId& app_id,
+                                         const webapps::AppId& app_id,
                                          ResultCallback callback);
 
 // Result of file handler registration process.
diff --git a/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win_unittest.cc
index e605fe1..190b2d2 100644
--- a/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_handler_registration_utils_win_unittest.cc
@@ -30,8 +30,9 @@
 namespace {
 
 constexpr unsigned int kMaxProgIdLen = 39;
-const AppId app_id1 = "app_id12345678901234567890123456789012345678901234";
-const AppId app_id2 = "different_appid";
+const webapps::AppId app_id1 =
+    "app_id12345678901234567890123456789012345678901234";
+const webapps::AppId app_id2 = "different_appid";
 
 }  // namespace
 
@@ -63,11 +64,11 @@
   TestingProfileManager* testing_profile_manager() const {
     return testing_profile_manager_.get();
   }
-  const AppId& app_id() const { return app_id_; }
+  const webapps::AppId& app_id() const { return app_id_; }
   const std::wstring& app_name() const { return app_name_; }
 
   // Adds a launcher file and OS registry entries for the given app parameters.
-  void RegisterApp(const AppId& app_id,
+  void RegisterApp(const webapps::AppId& app_id,
                    const std::wstring& app_name,
                    const std::wstring& app_name_extension,
                    const base::FilePath& profile_path) {
@@ -94,7 +95,7 @@
 
   // Tests that an app with |app_id| is registered with the expected name,
   // icon and extension.
-  void TestRegisteredApp(const AppId& app_id,
+  void TestRegisteredApp(const webapps::AppId& app_id,
                          const std::wstring& expected_app_name,
                          const std::wstring& expected_app_name_extension,
                          const base::FilePath& profile_path) {
@@ -127,7 +128,7 @@
       content::BrowserTaskEnvironment::IO_MAINLOOP};
   raw_ptr<TestingProfile> profile_ = nullptr;
   std::unique_ptr<TestingProfileManager> testing_profile_manager_;
-  const AppId app_id_ = "app_id";
+  const webapps::AppId app_id_ = "app_id";
   const std::wstring app_name_ = L"app_name";
 };
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.cc
index 3493457..f098e35 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.cc
@@ -33,7 +33,7 @@
 }
 
 absl::optional<GURL> WebAppProtocolHandlerManager::TranslateProtocolUrl(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& protocol_url) const {
   std::vector<ProtocolHandler> handlers = GetAppProtocolHandlers(app_id);
 
@@ -67,7 +67,7 @@
 
 std::vector<ProtocolHandler>
 WebAppProtocolHandlerManager::GetAppProtocolHandlers(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   std::vector<apps::ProtocolHandlerInfo> infos =
       GetAppProtocolHandlerInfos(app_id);
 
@@ -87,7 +87,7 @@
   std::vector<ProtocolHandler> protocol_handlers;
 
   for (const WebApp& web_app : provider_->registrar_unsafe().GetApps()) {
-    AppId app_id = web_app.app_id();
+    webapps::AppId app_id = web_app.app_id();
 
     if (!provider_->registrar_unsafe().IsAllowedLaunchProtocol(app_id,
                                                                protocol)) {
@@ -113,7 +113,7 @@
   std::vector<ProtocolHandler> protocol_handlers;
 
   for (const WebApp& web_app : provider_->registrar_unsafe().GetApps()) {
-    AppId app_id = web_app.app_id();
+    webapps::AppId app_id = web_app.app_id();
 
     if (!provider_->registrar_unsafe().IsDisallowedLaunchProtocol(app_id,
                                                                   protocol)) {
@@ -134,7 +134,7 @@
 }
 
 void WebAppProtocolHandlerManager::RegisterOsProtocolHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ResultCallback callback) {
   if (!provider_->registrar_unsafe().IsLocallyInstalled(app_id)) {
     std::move(callback).Run(Result::kOk);
@@ -149,7 +149,7 @@
 }
 
 void WebAppProtocolHandlerManager::UnregisterOsProtocolHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceCallback<void(Result)> callback) {
   UnregisterProtocolHandlersWithOs(app_id, profile_->GetPath(),
                                    std::move(callback));
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.h b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.h
index 9502a71..dcc703d 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.h
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.h
@@ -11,6 +11,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/custom_handlers/protocol_handler.h"
 #include "components/services/app_service/public/cpp/protocol_handler_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 #include <vector>
@@ -38,7 +39,7 @@
   // for the app indicated by |app_id|, this method will translate the protocol
   // to a full app URL.
   // If no matching handler is installed, no URL is returned.
-  absl::optional<GURL> TranslateProtocolUrl(const AppId& app_id,
+  absl::optional<GURL> TranslateProtocolUrl(const webapps::AppId& app_id,
                                             const GURL& protocol_url) const;
 
   // Gets the list of handlers with launch permissions for a given protocol.
@@ -57,14 +58,15 @@
 
   // Gets all protocol handlers for |app_id| as custom handler objects.
   std::vector<custom_handlers::ProtocolHandler> GetAppProtocolHandlers(
-      const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
   // Registers OS specific protocol handlers for OSs that need them, using the
   // protocol handler information supplied in the app manifest.
-  void RegisterOsProtocolHandlers(const AppId& app_id, ResultCallback callback);
+  void RegisterOsProtocolHandlers(const webapps::AppId& app_id,
+                                  ResultCallback callback);
 
   // Unregisters OS specific protocol handlers for an app.
-  void UnregisterOsProtocolHandlers(const AppId& app_id,
+  void UnregisterOsProtocolHandlers(const webapps::AppId& app_id,
                                     ResultCallback callback);
 
  private:
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
index afdf323e..6fe9a5c 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
@@ -43,13 +43,13 @@
 
   WebAppRegistrar& app_registrar() { return provider().registrar_unsafe(); }
 
-  AppId CreateWebAppWithProtocolHandlers(
+  webapps::AppId CreateWebAppWithProtocolHandlers(
       const GURL& start_url,
       std::vector<apps::ProtocolHandlerInfo> protocol_handler_infos,
       base::flat_set<std::string> allowed_launch_protocols = {},
       base::flat_set<std::string> disallowed_launch_protocols = {}) {
     auto web_app = test::CreateWebApp(start_url);
-    const AppId app_id = web_app->app_id();
+    const webapps::AppId app_id = web_app->app_id();
     web_app->SetProtocolHandlers(protocol_handler_infos);
     web_app->SetAllowedLaunchProtocols(allowed_launch_protocols);
     web_app->SetDisallowedLaunchProtocols(disallowed_launch_protocols);
@@ -86,7 +86,7 @@
       CreateDefaultProtocolHandlerInfos();
 
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   web_app->SetProtocolHandlers(protocol_handler_infos);
 
   ASSERT_EQ(
@@ -109,7 +109,7 @@
        GetAppProtocolHandlerInfosDisallowedProtocols) {
   std::vector<apps::ProtocolHandlerInfo> protocol_handler_infos =
       CreateDefaultProtocolHandlerInfos();
-  const AppId app_id = CreateWebAppWithProtocolHandlers(
+  const webapps::AppId app_id = CreateWebAppWithProtocolHandlers(
       GURL("https://example.com/path"), protocol_handler_infos, {},
       {"web+test"});
   std::vector<apps::ProtocolHandlerInfo> handler_infos =
@@ -119,7 +119,7 @@
 }
 
 TEST_F(WebAppProtocolHandlerManagerTest, TranslateProtocolUrl) {
-  const AppId app_id = CreateWebAppWithProtocolHandlers(
+  const webapps::AppId app_id = CreateWebAppWithProtocolHandlers(
       GURL("https://example.com/path"), CreateDefaultProtocolHandlerInfos());
 
   absl::optional<GURL> translated_url =
@@ -138,7 +138,7 @@
   std::vector<apps::ProtocolHandlerInfo> protocol_handler_infos =
       CreateDefaultProtocolHandlerInfos();
 
-  const AppId app_id = CreateWebAppWithProtocolHandlers(
+  const webapps::AppId app_id = CreateWebAppWithProtocolHandlers(
       GURL("https://example.com/path"), protocol_handler_infos);
 
   std::vector<ProtocolHandler> handlers =
@@ -156,10 +156,10 @@
       CreateProtocolHandlerInfo("web+test",
                                 GURL("http://example2.com/test=%s"))};
 
-  const AppId app_id1 = CreateWebAppWithProtocolHandlers(
+  const webapps::AppId app_id1 = CreateWebAppWithProtocolHandlers(
       GURL("https://example.com/path"), CreateDefaultProtocolHandlerInfos(),
       {"web+test"});
-  const AppId app_id2 = CreateWebAppWithProtocolHandlers(
+  const webapps::AppId app_id2 = CreateWebAppWithProtocolHandlers(
       GURL("https://example2.com/path"), protocol_handler_infos, {"web+test"});
   std::vector<ProtocolHandler> handlers =
       protocol_handler_manager().GetAllowedHandlersForProtocol("web+test");
@@ -180,10 +180,10 @@
       CreateProtocolHandlerInfo("web+test",
                                 GURL("http://example2.com/test=%s"))};
 
-  const AppId app_id1 = CreateWebAppWithProtocolHandlers(
+  const webapps::AppId app_id1 = CreateWebAppWithProtocolHandlers(
       GURL("https://example.com/path"), CreateDefaultProtocolHandlerInfos(), {},
       {"web+test"});
-  const AppId app_id2 = CreateWebAppWithProtocolHandlers(
+  const webapps::AppId app_id2 = CreateWebAppWithProtocolHandlers(
       GURL("https://example2.com/path"), protocol_handler_infos, {},
       {"web+test"});
   std::vector<ProtocolHandler> handlers =
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration.cc
index bda692e..40ababd 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration.cc
@@ -7,7 +7,7 @@
 #include "base/files/file_path.h"
 #include "base/task/sequenced_task_runner.h"
 #include "build/build_config.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -17,7 +17,7 @@
 #if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_MAC)
 // Registers a protocol handler for the web app with the OS.
 void RegisterProtocolHandlersWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     const base::FilePath profile_path,
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers,
@@ -27,7 +27,7 @@
 }
 
 // Unregisters protocol handlers for a web app with the OS.
-void UnregisterProtocolHandlersWithOs(const AppId& app_id,
+void UnregisterProtocolHandlersWithOs(const webapps::AppId& app_id,
                                       const base::FilePath profile_path,
                                       ResultCallback callback) {
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration.h b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration.h
index 6be165a..7194cb1 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration.h
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration.h
@@ -13,17 +13,18 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/protocol_handler_info.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
 void RegisterProtocolHandlersWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     const base::FilePath profile_path,
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers,
     ResultCallback callback);
 
-void UnregisterProtocolHandlersWithOs(const AppId& app_id,
+void UnregisterProtocolHandlersWithOs(const webapps::AppId& app_id,
                                       const base::FilePath profile_path,
                                       ResultCallback callback);
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_mac.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_mac.cc
index c2b60cd..be2b277 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_mac.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_mac.cc
@@ -7,12 +7,12 @@
 #include "base/files/file_path.h"
 #include "base/task/sequenced_task_runner.h"
 #include "chrome/browser/web_applications/app_shim_registry_mac.h"
-#include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
 void RegisterProtocolHandlersWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     const base::FilePath profile_path,
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers,
@@ -32,7 +32,7 @@
       FROM_HERE, base::BindOnce(std::move(callback), Result::kOk));
 }
 
-void UnregisterProtocolHandlersWithOs(const AppId& app_id,
+void UnregisterProtocolHandlersWithOs(const webapps::AppId& app_id,
                                       const base::FilePath profile_path,
                                       ResultCallback callback) {
   AppShimRegistry::Get()->SaveProtocolHandlersForAppAndProfile(
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win.cc
index 717030b0..57bae8d5 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win.cc
@@ -41,7 +41,7 @@
 namespace {
 
 void RegisterProtocolHandlersWithOSInBackground(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::wstring& app_name,
     const base::FilePath profile_path,
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers,
@@ -98,7 +98,7 @@
 }
 
 void UnregisterProtocolHandlersWithOsInBackground(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path) {
   base::AssertLongCPUWorkAllowed();
 
@@ -133,7 +133,7 @@
 }  // namespace
 
 void RegisterProtocolHandlersWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     const base::FilePath profile_path,
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers,
@@ -158,7 +158,7 @@
                      std::move(callback)));
 }
 
-void UnregisterProtocolHandlersWithOs(const AppId& app_id,
+void UnregisterProtocolHandlersWithOs(const webapps::AppId& app_id,
                                       const base::FilePath profile_path,
                                       ResultCallback callback) {
   scoped_refptr<OsIntegrationTestOverride> os_override =
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win_unittest.cc
index 0119680..ff2d83e 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win_unittest.cc
@@ -73,7 +73,7 @@
   // Ensures that URLAssociations entries are created for a given protocol.
   // "HKEY_CURRENT_USER\Software\<prog_id>\Capabilities\URLAssociations\<protocol>".
   bool ProgIdRegisteredForProtocol(const std::string& protocol,
-                                   const AppId& app_id,
+                                   const webapps::AppId& app_id,
                                    Profile* profile) {
     std::wstring prog_id = GetProgIdForApp(profile->GetPath(), app_id);
 
@@ -97,7 +97,7 @@
     return association_exists && entry_matches;
   }
 
-  void AddAndVerifyProtocolAssociations(const AppId& app_id,
+  void AddAndVerifyProtocolAssociations(const webapps::AppId& app_id,
                                         const std::string& app_name,
                                         const std::string& app_url,
                                         Profile* profile,
@@ -150,7 +150,7 @@
   // Returns the expected app launcher path inside the subdirectory for
   // |app_id|.
   base::FilePath GetLauncherPathForApp(Profile* profile,
-                                       const AppId app_id,
+                                       const webapps::AppId app_id,
                                        const std::string& sanitized_app_name) {
     base::FilePath web_app_dir(GetOsIntegrationResourcesDirectoryForApp(
         profile->GetPath(), app_id, GURL()));
diff --git a/chrome/browser/web_applications/os_integration/web_app_run_on_os_login.h b/chrome/browser/web_applications/os_integration/web_app_run_on_os_login.h
index ef9ce00..632afd3 100644
--- a/chrome/browser/web_applications/os_integration/web_app_run_on_os_login.h
+++ b/chrome/browser/web_applications/os_integration/web_app_run_on_os_login.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace base {
 class FilePath;
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut.cc b/chrome/browser/web_applications/os_integration/web_app_shortcut.cc
index 81a4d6d1..606df5e1 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut.cc
@@ -189,7 +189,7 @@
 }
 
 std::unique_ptr<ShortcutInfo> BuildShortcutInfoWithoutFavicon(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& start_url,
     const base::FilePath& profile_path,
     const std::string& profile_name,
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut.h b/chrome/browser/web_applications/os_integration/web_app_shortcut.h
index 15bfd90..b6fc88c 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut.h
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "ui/gfx/image/image_family.h"
 #include "url/gurl.h"
 
@@ -94,7 +95,7 @@
 };
 
 std::unique_ptr<ShortcutInfo> BuildShortcutInfoWithoutFavicon(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& start_url,
     const base::FilePath& profile_path,
     const std::string& profile_name,
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_linux.cc b/chrome/browser/web_applications/os_integration/web_app_shortcut_linux.cc
index aa7a389..a30a6d7b 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut_linux.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_linux.cc
@@ -38,10 +38,10 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_test_override.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/common/auto_start_linux.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_constants.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_linux_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_shortcut_linux_unittest.cc
index 6a54e33a..4a598762 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut_linux_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_linux_unittest.cc
@@ -29,9 +29,9 @@
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
 #include "chrome/browser/web_applications/test/web_app_test.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/common/chrome_constants.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/image/image_skia.h"
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.cc b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.cc
index 3712cf2..ebe5aaf 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.cc
@@ -123,7 +123,7 @@
 }
 
 void WebAppShortcutManager::UpdateShortcuts(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::StringPiece old_name,
     ResultCallback update_finished_callback) {
   DCHECK(CanCreateShortcuts());
@@ -173,7 +173,7 @@
   suppress_shortcuts_for_testing_ = true;
 }
 
-void WebAppShortcutManager::CreateShortcuts(const AppId& app_id,
+void WebAppShortcutManager::CreateShortcuts(const webapps::AppId& app_id,
                                             bool add_to_desktop,
                                             ShortcutCreationReason reason,
                                             CreateShortcutsCallback callback) {
@@ -191,7 +191,7 @@
 }
 
 void WebAppShortcutManager::DeleteShortcuts(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& shortcuts_data_dir,
     std::unique_ptr<ShortcutInfo> shortcut_info,
     ResultCallback callback) {
@@ -206,7 +206,7 @@
 }
 
 void WebAppShortcutManager::ReadAllShortcutsMenuIconsAndRegisterShortcutsMenu(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
     ResultCallback callback) {
   provider_->icon_manager().ReadAllShortcutsMenuIcons(
@@ -218,7 +218,7 @@
 }
 
 void WebAppShortcutManager::RegisterShortcutsMenuWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
     const ShortcutsMenuIconBitmaps& shortcuts_menu_icon_bitmaps,
     ResultCallback callback) {
@@ -247,7 +247,7 @@
 }
 
 void WebAppShortcutManager::UnregisterShortcutsMenuWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ResultCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!web_app::ShouldRegisterShortcutsMenuWithOs()) {
@@ -259,7 +259,7 @@
                                          std::move(callback));
 }
 
-void WebAppShortcutManager::OnShortcutsCreated(const AppId& app_id,
+void WebAppShortcutManager::OnShortcutsCreated(const webapps::AppId& app_id,
                                                CreateShortcutsCallback callback,
                                                bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -269,7 +269,7 @@
   std::move(callback).Run(success);
 }
 
-void WebAppShortcutManager::OnShortcutsDeleted(const AppId& app_id,
+void WebAppShortcutManager::OnShortcutsDeleted(const webapps::AppId& app_id,
                                                ResultCallback callback,
                                                bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -304,7 +304,7 @@
 }
 
 void WebAppShortcutManager::OnShortcutsMenuIconsReadRegisterShortcutsMenu(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
     ResultCallback callback,
     ShortcutsMenuIconBitmaps shortcuts_menu_icon_bitmaps) {
@@ -331,14 +331,14 @@
 }
 
 std::unique_ptr<ShortcutInfo> WebAppShortcutManager::BuildShortcutInfo(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   const WebApp* app = provider_->registrar_unsafe().GetAppById(app_id);
   DCHECK(app);
   return BuildShortcutInfoForWebApp(app);
 }
 
 void WebAppShortcutManager::GetShortcutInfoForApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     GetShortcutInfoCallback callback) {
   const WebApp* app = provider_->registrar_unsafe().GetAppById(app_id);
 
@@ -374,7 +374,7 @@
 }
 
 void WebAppShortcutManager::OnIconsRead(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     GetShortcutInfoCallback callback,
     std::map<SquareSizePx, SkBitmap> icon_bitmaps) {
   // |icon_bitmaps| can be empty here if no icon found.
@@ -496,7 +496,8 @@
   if (suppress_shortcuts_for_testing_)
     return;
 
-  std::vector<AppId> app_ids = provider_->registrar_unsafe().GetAppIds();
+  std::vector<webapps::AppId> app_ids =
+      provider_->registrar_unsafe().GetAppIds();
   auto done_callback = base::BarrierClosure(
       app_ids.size() + 1,
       base::BindOnce(&WebAppShortcutManager::SetCurrentAppShortcutsVersion,
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h
index 634035e..9e9f4d42 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h
@@ -62,15 +62,15 @@
   void SuppressShortcutsForTesting();
 
   bool CanCreateShortcuts() const;
-  void CreateShortcuts(const AppId& app_id,
+  void CreateShortcuts(const webapps::AppId& app_id,
                        bool add_to_desktop,
                        ShortcutCreationReason reason,
                        CreateShortcutsCallback callback);
   // Fetch already-updated shortcut data and deploy to OS integration.
-  void UpdateShortcuts(const AppId& app_id,
+  void UpdateShortcuts(const webapps::AppId& app_id,
                        base::StringPiece old_name,
                        ResultCallback update_finished_callback);
-  void DeleteShortcuts(const AppId& app_id,
+  void DeleteShortcuts(const webapps::AppId& app_id,
                        const base::FilePath& shortcuts_data_dir,
                        std::unique_ptr<ShortcutInfo> shortcut_info,
                        ResultCallback callback);
@@ -88,18 +88,18 @@
   // TODO(crbug.com/1098471): Consider unifying this method and
   // RegisterShortcutsMenuWithOs() below.
   void ReadAllShortcutsMenuIconsAndRegisterShortcutsMenu(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
       ResultCallback callback);
 
   // Registers a shortcuts menu for the web app's icon with the OS.
   void RegisterShortcutsMenuWithOs(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
       const ShortcutsMenuIconBitmaps& shortcuts_menu_icon_bitmaps,
       ResultCallback callback);
 
-  void UnregisterShortcutsMenuWithOs(const AppId& app_id,
+  void UnregisterShortcutsMenuWithOs(const webapps::AppId& app_id,
                                      ResultCallback callback);
 
   // Builds initial ShortcutInfo without |ShortcutInfo::favicon| being read.
@@ -107,7 +107,8 @@
   //
   // TODO(crbug.com/1225132): Get rid of |BuildShortcutInfo| method: inline it
   // or make it private.
-  virtual std::unique_ptr<ShortcutInfo> BuildShortcutInfo(const AppId& app_id);
+  virtual std::unique_ptr<ShortcutInfo> BuildShortcutInfo(
+      const webapps::AppId& app_id);
 
   // The result of a call to GetShortcutInfo.
   using GetShortcutInfoCallback =
@@ -116,7 +117,7 @@
   // |app_id| including all the icon bitmaps. Returns nullptr if app_id is
   // uninstalled or becomes uninstalled during the asynchronous read of icons.
   // virtual for testing.
-  virtual void GetShortcutInfoForApp(const AppId& app_id,
+  virtual void GetShortcutInfoForApp(const webapps::AppId& app_id,
                                      GetShortcutInfoCallback callback);
 
   // Sets a callback to be called when this class determines that all shortcuts
@@ -132,14 +133,14 @@
       UpdateShortcutsForAllAppsCallback callback);
 
  private:
-  void OnIconsRead(const AppId& app_id,
+  void OnIconsRead(const webapps::AppId& app_id,
                    GetShortcutInfoCallback callback,
                    std::map<SquareSizePx, SkBitmap> icon_bitmaps);
 
-  void OnShortcutsCreated(const AppId& app_id,
+  void OnShortcutsCreated(const webapps::AppId& app_id,
                           CreateShortcutsCallback callback,
                           bool success);
-  void OnShortcutsDeleted(const AppId& app_id,
+  void OnShortcutsDeleted(const webapps::AppId& app_id,
                           ResultCallback callback,
                           bool success);
 
@@ -155,7 +156,7 @@
       std::unique_ptr<ShortcutInfo> info);
 
   void OnShortcutsMenuIconsReadRegisterShortcutsMenu(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
       ResultCallback callback,
       ShortcutsMenuIconBitmaps shortcuts_menu_icon_bitmaps);
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager_mac_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager_mac_unittest.cc
index b77c3f5..ce940a6 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut_manager_mac_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_manager_mac_unittest.cc
@@ -77,7 +77,7 @@
     return provider_->os_integration_manager().shortcut_manager_for_testing();
   }
 
-  void CreateShortcutForApp(AppId app_id) {
+  void CreateShortcutForApp(webapps::AppId app_id) {
     base::RunLoop loop;
     shortcut_manager().CreateShortcuts(
         app_id, /*add_to_desktop=*/false, SHORTCUT_CREATION_AUTOMATED,
@@ -136,10 +136,10 @@
   EXPECT_TRUE(done_update_callback_.is_null());
 
   // Install two apps, but only create shortcuts for one.
-  AppId app_id1 =
+  webapps::AppId app_id1 =
       test::InstallDummyWebApp(profile(), kTestApp1Name, kTestApp1Url);
   CreateShortcutForApp(app_id1);
-  AppId app_id2 =
+  webapps::AppId app_id2 =
       test::InstallDummyWebApp(profile(), kTestApp2Name, kTestApp2Url);
 
   base::FilePath app1_path = GetShortcutPath(kTestApp1Name);
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu.cc b/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu.cc
index 90aaf65..7173d11 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu.cc
@@ -16,7 +16,7 @@
 }
 
 void RegisterShortcutsMenuWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path,
     const base::FilePath& shortcut_data_dir,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
@@ -27,7 +27,7 @@
   std::move(callback).Run(Result::kOk);
 }
 
-bool UnregisterShortcutsMenuWithOs(const AppId& app_id,
+bool UnregisterShortcutsMenuWithOs(const webapps::AppId& app_id,
                                    const base::FilePath& profile_path,
                                    RegisterShortcutsMenuCallback callback) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu.h b/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu.h
index 45e9590..7b69393 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu.h
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu.h
@@ -10,6 +10,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace base {
 class FilePath;
@@ -25,7 +26,7 @@
 
 // Does an OS specific registration of a Shortcuts Menu for the web app's icon.
 void RegisterShortcutsMenuWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path,
     const base::FilePath& shortcut_data_dir,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
@@ -34,7 +35,7 @@
 
 // Deletes the ShortcutsMenu from the OS. This should be called during the
 // uninstallation process. Returns true if there were no errors.
-bool UnregisterShortcutsMenuWithOs(const AppId& app_id,
+bool UnregisterShortcutsMenuWithOs(const webapps::AppId& app_id,
                                    const base::FilePath& profile_path,
                                    RegisterShortcutsMenuCallback callback);
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu_win.cc b/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu_win.cc
index 99de9011..fb5cd99 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu_win.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu_win.cc
@@ -27,10 +27,10 @@
 #include "chrome/browser/web_applications/os_integration/os_integration_test_override.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/win/jumplist_updater.h"
 #include "chrome/common/chrome_switches.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/icon_util.h"
 #include "ui/gfx/image/image.h"
@@ -157,7 +157,7 @@
 }
 
 std::wstring GenerateAppUserModelId(const base::FilePath& profile_path,
-                                    const AppId& app_id) {
+                                    const webapps::AppId& app_id) {
   std::wstring app_name =
       base::UTF8ToWide(GenerateApplicationNameFromAppId(app_id));
   return shell_integration::win::GetAppUserModelIdForApp(app_name,
@@ -169,7 +169,7 @@
 }
 
 bool RegisterShortcutsMenuWithOsTask(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path,
     const base::FilePath& shortcut_data_dir,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
@@ -230,7 +230,7 @@
 }
 
 void RegisterShortcutsMenuWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path,
     const base::FilePath& shortcut_data_dir,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos,
@@ -245,7 +245,7 @@
                      std::move(callback)));
 }
 
-bool UnregisterShortcutsMenuWithOs(const AppId& app_id,
+bool UnregisterShortcutsMenuWithOs(const webapps::AppId& app_id,
                                    const base::FilePath& profile_path,
                                    RegisterShortcutsMenuCallback callback) {
   scoped_refptr<OsIntegrationTestOverride> test_override =
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu_win.h b/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu_win.h
index 77e31777..9615d3080 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu_win.h
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcuts_menu_win.h
@@ -21,7 +21,7 @@
     UpdateJumpListForTesting updateJumpListForTesting);
 
 std::wstring GenerateAppUserModelId(const base::FilePath& profile_path,
-                                    const AppId& app_id);
+                                    const webapps::AppId& app_id);
 
 namespace internals {
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_stubs.cc b/chrome/browser/web_applications/os_integration/web_app_stubs.cc
index 3fe4b2e..d802cd1 100644
--- a/chrome/browser/web_applications/os_integration/web_app_stubs.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_stubs.cc
@@ -28,7 +28,7 @@
   return false;
 }
 
-void RegisterFileHandlersWithOs(const AppId& app_id,
+void RegisterFileHandlersWithOs(const webapps::AppId& app_id,
                                 const std::string& app_name,
                                 const base::FilePath& profile_path,
                                 const apps::FileHandlers& file_handlers,
@@ -37,7 +37,7 @@
   std::move(callback).Run(Result::kError);
 }
 
-void UnregisterFileHandlersWithOs(const AppId& app_id,
+void UnregisterFileHandlersWithOs(const webapps::AppId& app_id,
                                   const base::FilePath& profile_path,
                                   ResultCallback callback) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.cc b/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.cc
index 4b0dd33..096e74dd 100644
--- a/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.cc
@@ -19,7 +19,7 @@
 }
 
 bool RegisterUninstallationViaOsSettingsWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     const base::FilePath& profile_path) {
   NOTREACHED();
@@ -27,7 +27,7 @@
 }
 
 bool UnregisterUninstallationViaOsSettingsWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path) {
   NOTREACHED();
   return true;
diff --git a/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.h b/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.h
index 1878df8..5c7084ef 100644
--- a/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.h
+++ b/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.h
@@ -11,6 +11,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace base {
 class FilePath;
@@ -20,7 +21,7 @@
 
 #if BUILDFLAG(IS_WIN)
 std::wstring GetUninstallStringKeyForTesting(const base::FilePath& profile_path,
-                                             const AppId& app_id);
+                                             const webapps::AppId& app_id);
 #endif
 
 // True if uninstallation via os settings are managed externally by the
@@ -34,7 +35,7 @@
 // there like any other native apps.
 // Returns if the operation was successful.
 bool RegisterUninstallationViaOsSettingsWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     const base::FilePath& profile_path);
 
@@ -42,7 +43,7 @@
 // Returns true if the operation had no errors. The registry key not existing is
 // not considered an error, and return true.
 bool UnregisterUninstallationViaOsSettingsWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path);
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration_win.cc b/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration_win.cc
index 305f6cb..e5b3cda 100644
--- a/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration_win.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration_win.cc
@@ -30,7 +30,7 @@
 // all web apps installed in all profiles across all browser installations
 // for the user.
 std::wstring GetUninstallStringKey(const base::FilePath& profile_path,
-                                   const AppId& app_id) {
+                                   const webapps::AppId& app_id) {
   // We don't normalize (lower/upper) cases here mainly because people
   // don't change shortcut file case. If anyone changes the file name
   // or case, then it is the user's responsibility to clean up the apps.
@@ -48,7 +48,7 @@
 class UninstallationViaOsSettingsHelper {
  public:
   UninstallationViaOsSettingsHelper(const base::FilePath& profile_path,
-                                    const AppId& app_id)
+                                    const webapps::AppId& app_id)
       : profile_path_(profile_path), app_id_(app_id) {}
 
   UninstallationViaOsSettingsHelper(
@@ -99,13 +99,13 @@
 
  private:
   const base::FilePath profile_path_;
-  const AppId app_id_;
+  const webapps::AppId app_id_;
 };
 
 }  // namespace
 
 std::wstring GetUninstallStringKeyForTesting(const base::FilePath& profile_path,
-                                             const AppId& app_id) {
+                                             const webapps::AppId& app_id) {
   return GetUninstallStringKey(profile_path, app_id);
 }
 
@@ -114,7 +114,7 @@
 }
 
 bool RegisterUninstallationViaOsSettingsWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     const base::FilePath& profile_path) {
   DCHECK(ShouldRegisterUninstallationViaOsSettingsWithOs());
@@ -136,7 +136,7 @@
 }
 
 bool UnregisterUninstallationViaOsSettingsWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::FilePath& profile_path) {
   DCHECK(ShouldRegisterUninstallationViaOsSettingsWithOs());
 
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
index 1af7d7bea..ffd0522 100644
--- a/chrome/browser/web_applications/policy/web_app_policy_manager.cc
+++ b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_prefs_utils.h"
@@ -50,6 +49,7 @@
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -269,7 +269,8 @@
 void WebAppPolicyManager::OnDisableListPolicyChanged() {
 #if BUILDFLAG(IS_CHROMEOS)
   PopulateDisabledWebAppsIdsLists();
-  std::vector<AppId> app_ids = provider_->registrar_unsafe().GetAppIds();
+  std::vector<webapps::AppId> app_ids =
+      provider_->registrar_unsafe().GetAppIds();
   WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(profile_);
   for (const auto& id : app_ids) {
     const bool is_disabled = base::Contains(disabled_web_apps_, id);
@@ -292,11 +293,13 @@
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-const std::set<AppId>& WebAppPolicyManager::GetDisabledWebAppsIds() const {
+const std::set<webapps::AppId>& WebAppPolicyManager::GetDisabledWebAppsIds()
+    const {
   return disabled_web_apps_;
 }
 
-bool WebAppPolicyManager::IsWebAppInDisabledList(const AppId& app_id) const {
+bool WebAppPolicyManager::IsWebAppInDisabledList(
+    const webapps::AppId& app_id) const {
   return base::Contains(GetDisabledWebAppsIds(), app_id);
 }
 
@@ -355,7 +358,7 @@
                                     WebAppManagement::kPolicy)
             .has_value();
 
-    absl::optional<AppId> app_id =
+    absl::optional<webapps::AppId> app_id =
         provider_->registrar_unsafe().LookupExternalAppId(
             install_options.install_url);
 
@@ -510,12 +513,12 @@
 
 void WebAppPolicyManager::ApplyRunOnOsLoginPolicySettings(
     base::OnceClosure policy_settings_applied_callback) {
-  std::vector<AppId> app_ids_to_sync =
+  std::vector<webapps::AppId> app_ids_to_sync =
       provider_->registrar_unsafe().GetAppIds();
   auto callback_for_sync_commands = base::BarrierClosure(
       app_ids_to_sync.size(), std::move(policy_settings_applied_callback));
   WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(profile_);
-  for (const AppId& app_id : app_ids_to_sync) {
+  for (const webapps::AppId& app_id : app_ids_to_sync) {
     provider->scheduler().SyncRunOnOsLoginMode(app_id,
                                                callback_for_sync_commands);
   }
@@ -528,14 +531,15 @@
     return;
   }
 
-  base::flat_set<AppId> app_ids_for_force_unregistration;
+  base::flat_set<webapps::AppId> app_ids_for_force_unregistration;
   for (const auto& [manifest_string, setting] : settings_by_url_) {
     const GURL manifest_id = GURL(manifest_string);
     if (!manifest_id.is_valid()) {
       continue;
     }
 
-    const AppId& app_id = web_app::GenerateAppIdFromManifestId(manifest_id);
+    const webapps::AppId& app_id =
+        web_app::GenerateAppIdFromManifestId(manifest_id);
     if (!provider_->registrar_unsafe().IsLocallyInstalled(app_id)) {
       continue;
     }
@@ -652,7 +656,7 @@
 }
 
 RunOnOsLoginPolicy WebAppPolicyManager::GetUrlRunOnOsLoginPolicy(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   return GetUrlRunOnOsLoginPolicyByManifestId(
       provider_->registrar_unsafe().GetComputedManifestId(app_id).spec());
 }
@@ -710,9 +714,9 @@
   // policy-installed URL as start_url, so they are covered by the first case.
   // Second case first:
   if (manifest->id.is_valid()) {
-    const AppId& app_id = GenerateAppIdFromManifestId(manifest->id);
+    const webapps::AppId& app_id = GenerateAppIdFromManifestId(manifest->id);
     // List of policy-installed apps and their install URLs:
-    base::flat_map<AppId, base::flat_set<GURL>> policy_installed_apps =
+    base::flat_map<webapps::AppId, base::flat_set<GURL>> policy_installed_apps =
         provider_->registrar_unsafe().GetExternallyInstalledApps(
             ExternalInstallSource::kExternalPolicy);
     if (base::Contains(policy_installed_apps, app_id)) {
@@ -738,7 +742,8 @@
     OverrideManifest(install_url, manifest);
 }
 
-bool WebAppPolicyManager::IsPreventCloseEnabled(const AppId& app_id) const {
+bool WebAppPolicyManager::IsPreventCloseEnabled(
+    const webapps::AppId& app_id) const {
 #if BUILDFLAG(IS_CHROMEOS)
   if (!base::FeatureList::IsEnabled(
           features::kDesktopPWAsEnforceWebAppSettingsPolicy) ||
@@ -746,7 +751,7 @@
     return false;
   }
 
-  const ManifestId manifest_id =
+  const webapps::ManifestId manifest_id =
       provider_->registrar_unsafe().GetComputedManifestId(app_id);
   auto it = settings_by_url_.find(manifest_id.spec());
   if (it != settings_by_url_.end()) {
@@ -942,7 +947,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   DCHECK(system_web_apps_delegate_map_);
   for (const ash::SystemWebAppType& app_type : disabled_system_apps_) {
-    absl::optional<AppId> app_id =
+    absl::optional<webapps::AppId> app_id =
         GetAppIdForSystemApp(provider_->registrar_unsafe(),
                              *system_web_apps_delegate_map_, app_type);
     if (app_id.has_value()) {
@@ -966,7 +971,7 @@
 }
 
 bool WebAppPolicyManager::IsMaybeErrorLoadedPolicyApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& policy_install_url) {
   if (!base::FeatureList::IsEnabled(features::kMigrateErrorLoadedPolicyApps)) {
     return false;
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.h b/chrome/browser/web_applications/policy/web_app_policy_manager.h
index 4c1226c..6998e21 100644
--- a/chrome/browser/web_applications/policy/web_app_policy_manager.h
+++ b/chrome/browser/web_applications/policy/web_app_policy_manager.h
@@ -89,15 +89,16 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Gets ids of web apps disabled by SystemFeaturesDisableList policy.
-  const std::set<AppId>& GetDisabledWebAppsIds() const;
+  const std::set<webapps::AppId>& GetDisabledWebAppsIds() const;
 
   // Checks if web app is disabled by SystemFeaturesDisableList policy.
-  bool IsWebAppInDisabledList(const AppId& app_id) const;
+  bool IsWebAppInDisabledList(const webapps::AppId& app_id) const;
 
   // Checks if UI mode of disabled web apps is hidden.
   bool IsDisabledAppsModeHidden() const;
 
-  RunOnOsLoginPolicy GetUrlRunOnOsLoginPolicy(const AppId& app_id) const;
+  RunOnOsLoginPolicy GetUrlRunOnOsLoginPolicy(
+      const webapps::AppId& app_id) const;
 
   void SetOnAppsSynchronizedCompletedCallbackForTesting(
       base::OnceClosure callback);
@@ -109,7 +110,7 @@
   void MaybeOverrideManifest(content::RenderFrameHost* frame_host,
                              blink::mojom::ManifestPtr& manifest) const;
 
-  bool IsPreventCloseEnabled(const AppId& app_id) const;
+  bool IsPreventCloseEnabled(const webapps::AppId& app_id) const;
 
   void RefreshPolicyInstalledAppsForTesting();
 
@@ -194,7 +195,7 @@
   // to an app that is installed with an invalid start URL. This has an unique
   // id compared to its default app counterpart (if any), and is hence treated
   // as a valid app w.r.t to the web apps system even though it is invalid.
-  bool IsMaybeErrorLoadedPolicyApp(const AppId& app_id,
+  bool IsMaybeErrorLoadedPolicyApp(const webapps::AppId& app_id,
                                    const GURL& policy_install_url);
 
   raw_ptr<Profile> profile_ = nullptr;
@@ -214,7 +215,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // List of disabled system and progressive web apps, containing app ids.
-  std::set<AppId> disabled_web_apps_;
+  std::set<webapps::AppId> disabled_web_apps_;
 
   // Testing callbacks
   base::OnceClosure refresh_policy_settings_completed_;
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager_browsertest.cc b/chrome/browser/web_applications/policy/web_app_policy_manager_browsertest.cc
index cfa32906..dc8c807c 100644
--- a/chrome/browser/web_applications/policy/web_app_policy_manager_browsertest.cc
+++ b/chrome/browser/web_applications/policy/web_app_policy_manager_browsertest.cc
@@ -22,7 +22,6 @@
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_prefs_utils.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -31,6 +30,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/prefs/pref_service.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/test/browser_test.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
@@ -205,7 +205,7 @@
   future.Get();
 
   const GURL start_url = https_server()->GetURL("/web_apps/basic.html");
-  const AppId app_id = GenerateAppIdFromManifestId(
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(
       GenerateManifestIdFromStartUrlOnly(start_url));
   const WebApp* app = provider.registrar_unsafe().GetAppById(app_id);
 
@@ -220,7 +220,7 @@
 // Scenario: App with install_url kInstallUrl has a start_url kStartUrl
 // specified in manifest. Next time we navigate to kStartUrl, but we still
 // need to override the manifest even though the policy key is kInstallUrl.
-// This is done by matching the AppId.
+// This is done by matching the webapps::AppId.
 // TODO(crbug.com/1415979): Flaky on Mac.
 #if BUILDFLAG(IS_MAC)
 #define MAYBE_MismatchedInstallAndStartUrl DISABLED_MismatchedInstallAndStartUrl
@@ -301,7 +301,7 @@
   web_app_info_default->title = u"Example Default App";
   web_app_info_default->user_display_mode = mojom::UserDisplayMode::kStandalone;
   web_app_info_default->install_url = default_install_url;
-  const AppId& app_id_default =
+  const webapps::AppId& app_id_default =
       test::InstallWebApp(profile(), std::move(web_app_info_default), true,
                           webapps::WebappInstallSource::EXTERNAL_DEFAULT);
 
@@ -314,7 +314,7 @@
   web_app_info_policy->user_display_mode = mojom::UserDisplayMode::kStandalone;
   web_app_info_policy->install_url = policy_install_url;
 
-  const AppId& app_id_policy =
+  const webapps::AppId& app_id_policy =
       test::InstallWebApp(profile(), std::move(web_app_info_policy), true,
                           webapps::WebappInstallSource::EXTERNAL_POLICY);
   EXPECT_NE(app_id_default, app_id_policy);
@@ -363,7 +363,7 @@
   web_app_info_default->title = u"Example Default App";
   web_app_info_default->user_display_mode = mojom::UserDisplayMode::kStandalone;
   web_app_info_default->install_url = default_install_url;
-  const AppId& app_id_default =
+  const webapps::AppId& app_id_default =
       test::InstallWebApp(profile(), std::move(web_app_info_default), true,
                           webapps::WebappInstallSource::EXTERNAL_DEFAULT);
 
@@ -374,7 +374,7 @@
   web_app_info_policy->user_display_mode = mojom::UserDisplayMode::kStandalone;
   web_app_info_policy->install_url = policy_install_url;
 
-  const AppId& app_id_policy =
+  const webapps::AppId& app_id_policy =
       test::InstallWebApp(profile(), std::move(web_app_info_policy), true,
                           webapps::WebappInstallSource::EXTERNAL_POLICY);
   EXPECT_NE(app_id_default, app_id_policy);
@@ -412,7 +412,8 @@
   auto install_info = std::make_unique<WebAppInstallInfo>();
   install_info->start_url = GURL("https://some.app.com");
   install_info->title = u"some app";
-  AppId old_app_id = test::InstallWebApp(profile(), std::move(install_info));
+  webapps::AppId old_app_id =
+      test::InstallWebApp(profile(), std::move(install_info));
 
   WebAppTestUninstallObserver uninstall_observer(profile());
   uninstall_observer.BeginListening({old_app_id});
@@ -470,7 +471,7 @@
                                     std::move(app_list));
   EXPECT_TRUE(future.Wait());
 
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, GURL(kInstallUrl));
 
   // This test should pass on all platforms, including on a ChromeOS
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc
index 76a5d36..a843ec0 100644
--- a/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc
+++ b/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc
@@ -381,7 +381,7 @@
         base::BindLambdaForTesting(
             [this](const ExternalInstallOptions& install_options) {
               const GURL& install_url = install_options.install_url;
-              const AppId app_id = GenerateAppId(
+              const webapps::AppId app_id = GenerateAppId(
                   /*manifest_id=*/absl::nullopt, install_url);
               if (app_registrar().GetAppById(app_id) &&
                   install_options.force_reinstall) {
@@ -406,7 +406,7 @@
         base::BindLambdaForTesting(
             [this](const GURL& app_url,
                    ExternalInstallSource install_source) -> bool {
-              absl::optional<AppId> app_id =
+              absl::optional<webapps::AppId> app_id =
                   app_registrar().LookupExternalAppId(app_url);
               if (app_id) {
                 UnregisterApp(*app_id);
@@ -527,7 +527,7 @@
     update->CreateApp(std::move(web_app));
   }
 
-  void UnregisterApp(const AppId& app_id) {
+  void UnregisterApp(const webapps::AppId& app_id) {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
     update->DeleteApp(app_id);
   }
@@ -934,7 +934,7 @@
 
   EXPECT_EQ(install_requests, expected_install_options_list);
 
-  base::flat_map<AppId, base::flat_set<GURL>> apps =
+  base::flat_map<webapps::AppId, base::flat_set<GURL>> apps =
       app_registrar().GetExternallyInstalledApps(
           ExternalInstallSource::kExternalPolicy);
   EXPECT_EQ(1u, apps.size());
@@ -1217,7 +1217,7 @@
             externally_managed_app_manager().uninstall_requests());
 
   // There should be exactly 1 app remaining.
-  base::flat_map<AppId, base::flat_set<GURL>> apps =
+  base::flat_map<webapps::AppId, base::flat_set<GURL>> apps =
       app_registrar().GetExternallyInstalledApps(
           ExternalInstallSource::kExternalPolicy);
   EXPECT_EQ(1u, apps.size());
@@ -1571,7 +1571,7 @@
     return bitmap;
   }
 
-  web_app::AppId InstallWebAppWithShortcuts(
+  webapps::AppId InstallWebAppWithShortcuts(
       std::map<SquareSizePx, SkBitmap> icon_map,
       const GURL manifest_id) {
     std::unique_ptr<WebAppInstallInfo> info =
@@ -1583,7 +1583,8 @@
     info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone;
     info->icon_bitmaps.any = std::move(icon_map);
     info->manifest_id = manifest_id;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+        result;
     provider().scheduler().InstallFromInfoWithParams(
         std::move(info), /*overwrite_existing_manifest_fields=*/true,
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
@@ -1591,11 +1592,11 @@
     bool success = result.Wait();
     EXPECT_TRUE(success);
     if (!success) {
-      return AppId();
+      return webapps::AppId();
     }
     EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
-    return result.Get<AppId>();
+    return result.Get<webapps::AppId>();
   }
 
   bool IsOsIntegrationAllowed() {
@@ -1625,7 +1626,7 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebAppWithShortcuts(std::move(icon_map), kWebAppUrl);
   const std::string& app_name =
       provider().registrar_unsafe().GetAppShortName(app_id);
@@ -1661,7 +1662,7 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebAppWithShortcuts(std::move(icon_map), kWebAppUrl);
   const std::string& app_name =
       provider().registrar_unsafe().GetAppShortName(app_id);
@@ -1697,7 +1698,7 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebAppWithShortcuts(std::move(icon_map), kWebAppUrl);
   const std::string& app_name =
       provider().registrar_unsafe().GetAppShortName(app_id);
@@ -1733,7 +1734,7 @@
   icon_map[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id =
+  const webapps::AppId& app_id =
       InstallWebAppWithShortcuts(std::move(icon_map), kWebAppUrl);
   const std::string& app_name =
       provider().registrar_unsafe().GetAppShortName(app_id);
@@ -1790,7 +1791,7 @@
   icon_map1[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map1[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id1 =
+  const webapps::AppId& app_id1 =
       InstallWebAppWithShortcuts(std::move(icon_map1), kWebAppUrl);
   const std::string& app_name1 =
       provider().registrar_unsafe().GetAppShortName(app_id1);
@@ -1804,7 +1805,7 @@
       CreateSolidColorIcon(icon_size::k24, SK_ColorGREEN);
   icon_map2[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorCYAN);
-  const AppId& app_id2 =
+  const webapps::AppId& app_id2 =
       InstallWebAppWithShortcuts(std::move(icon_map2), manifest_id2);
   const std::string& app_name2 =
       provider().registrar_unsafe().GetAppShortName(app_id2);
@@ -1846,7 +1847,7 @@
   icon_map1[icon_size::k24] = CreateSolidColorIcon(icon_size::k24, SK_ColorRED);
   icon_map1[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorGREEN);
-  const AppId& app_id1 =
+  const webapps::AppId& app_id1 =
       InstallWebAppWithShortcuts(std::move(icon_map1), kWebAppUrl);
   const std::string& app_name1 =
       provider().registrar_unsafe().GetAppShortName(app_id1);
@@ -1860,7 +1861,7 @@
       CreateSolidColorIcon(icon_size::k24, SK_ColorGREEN);
   icon_map2[icon_size::k128] =
       CreateSolidColorIcon(icon_size::k128, SK_ColorCYAN);
-  const AppId& app_id2 =
+  const webapps::AppId& app_id2 =
       InstallWebAppWithShortcuts(std::move(icon_map2), manifest_id2);
   const std::string& app_name2 =
       provider().registrar_unsafe().GetAppShortName(app_id2);
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.cc b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
index ff223e71..c4a6df4 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_manager.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
@@ -301,7 +301,7 @@
 
   // Remove if any apps to replace are blocked or force installed by admin
   // policy.
-  for (const AppId& app_id : options.uninstall_and_replace) {
+  for (const webapps::AppId& app_id : options.uninstall_and_replace) {
     if (extensions::IsExtensionBlockedByPolicy(profile, app_id)) {
       return {.type = SynchronizeDecision::kUninstall,
               .reason = DisabledReason::kUninstallReplacingAppBlockedByPolicy,
@@ -326,7 +326,7 @@
   // default extension apps are not performing new installation.
   if (options.gate_on_feature && !options.uninstall_and_replace.empty() &&
       !extensions::DidPreinstalledAppsPerformNewInstallation(profile)) {
-    for (const AppId& app_id : options.uninstall_and_replace) {
+    for (const webapps::AppId& app_id : options.uninstall_and_replace) {
       // First time migration and the app to replace is uninstalled as it passed
       // the last code block. Save the information that the app was
       // uninstalled by user.
@@ -378,7 +378,7 @@
 
   // Ensure install if any apps to replace are installed as installation
   // includes uninstall_and_replace-ing the specified apps.
-  for (const AppId& app_id : options.uninstall_and_replace) {
+  for (const webapps::AppId& app_id : options.uninstall_and_replace) {
     if (extensions::IsExtensionInstalled(profile, app_id)) {
       return {
           .type = SynchronizeDecision::kInstall,
@@ -447,7 +447,7 @@
   }
 
   // Ignore if any apps to replace were previously uninstalled.
-  for (const AppId& app_id : options.uninstall_and_replace) {
+  for (const webapps::AppId& app_id : options.uninstall_and_replace) {
     if (extensions::IsExternalExtensionUninstalled(profile, app_id)) {
       return {.type = SynchronizeDecision::kIgnore,
               .reason = DisabledReason::kIgnoreReplacingAppUninstalledByUser,
@@ -932,7 +932,7 @@
     std::vector<ExternalInstallOptions> desired_apps_install_options) {
   DCHECK(provider_);
 
-  std::map<InstallUrl, std::vector<AppId>> desired_uninstalls;
+  std::map<InstallUrl, std::vector<webapps::AppId>> desired_uninstalls;
   for (const auto& entry : desired_apps_install_options) {
     if (!entry.uninstall_and_replace.empty()) {
       desired_uninstalls.emplace(entry.install_url,
@@ -949,7 +949,7 @@
 
 void PreinstalledWebAppManager::OnExternalWebAppsSynchronized(
     ExternallyManagedAppManager::SynchronizeCallback callback,
-    std::map<InstallUrl, std::vector<AppId>> desired_uninstalls,
+    std::map<InstallUrl, std::vector<webapps::AppId>> desired_uninstalls,
     std::map<InstallUrl, ExternallyManagedAppManager::InstallResult>
         install_results,
     std::map<InstallUrl, bool> uninstall_results) {
@@ -987,7 +987,7 @@
       continue;
     }
 
-    for (const AppId& replace_id : iter->second) {
+    for (const webapps::AppId& replace_id : iter->second) {
       // We mark the app as migrated to a web app as long as the
       // installation was successful, even if the previous app was not
       // installed. This ensures we properly re-install apps if the
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.h b/chrome/browser/web_applications/preinstalled_web_app_manager.h
index 2a62585..6234fdb0 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_manager.h
+++ b/chrome/browser/web_applications/preinstalled_web_app_manager.h
@@ -149,7 +149,8 @@
                    std::vector<ExternalInstallOptions>);
   void OnExternalWebAppsSynchronized(
       ExternallyManagedAppManager::SynchronizeCallback callback,
-      std::map<InstallUrl, std::vector<AppId>> desired_uninstall_and_replaces,
+      std::map<InstallUrl, std::vector<webapps::AppId>>
+          desired_uninstall_and_replaces,
       std::map<InstallUrl, ExternallyManagedAppManager::InstallResult>
           install_results,
       std::map<InstallUrl, bool> uninstall_results);
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
index 5f2aad9..32218a77 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
@@ -306,7 +306,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL start_url = embedded_test_server()->GetURL("/web_apps/basic.html");
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 
   constexpr char kAppConfigTemplate[] =
@@ -344,7 +345,8 @@
       "/web_apps/query_params_in_start_url.html");
   GURL start_url = embedded_test_server()->GetURL(
       "/web_apps/query_params_in_start_url.html?query_params=in&start=url");
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 
   constexpr char kAppConfigTemplate[] =
@@ -380,7 +382,8 @@
   GURL start_url = embedded_test_server()->GetURL("/web_apps/basic.html");
   GURL launch_url = embedded_test_server()->GetURL(
       "/web_apps/basic.html?more=than&one=query&param");
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 
   constexpr char kAppConfigTemplate[] =
@@ -415,7 +418,8 @@
       "/web_apps/query_params_in_start_url.html");
   GURL start_url = embedded_test_server()->GetURL(
       "/web_apps/query_params_in_start_url.html?query_params=in&start=url");
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 
   constexpr char kAppConfigTemplate[] =
@@ -572,8 +576,8 @@
       SyncPreinstalledAppConfig(GURL{kSimpleManifestStartUrl}, prev_app_config),
       webapps::InstallResultCode::kSuccessNewInstall);
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
-                               GURL{kSimpleManifestStartUrl});
+  webapps::AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
+                                        GURL{kSimpleManifestStartUrl});
   EXPECT_TRUE(registrar().IsInstalled(app_id));
 }
 
@@ -592,8 +596,8 @@
       SyncPreinstalledAppConfig(GURL{kSimpleManifestStartUrl}, next_app_config),
       webapps::InstallResultCode::kSuccessAlreadyInstalled);
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
-                               GURL{kSimpleManifestStartUrl});
+  webapps::AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
+                                        GURL{kSimpleManifestStartUrl});
   EXPECT_TRUE(registrar().IsInstalled(app_id));
 }
 
@@ -611,8 +615,8 @@
                                       prev_app_config),
             webapps::InstallResultCode::kNotValidManifestForWebApp);
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
-                               GURL{kNoManifestTestPageStartUrl});
+  webapps::AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
+                                        GURL{kNoManifestTestPageStartUrl});
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 }
 
@@ -631,8 +635,8 @@
                                       next_app_config),
             absl::nullopt);
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
-                               GURL{kNoManifestTestPageStartUrl});
+  webapps::AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
+                                        GURL{kNoManifestTestPageStartUrl});
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 }
 
@@ -660,7 +664,8 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), app_config),
             webapps::InstallResultCode::kSuccessNewInstall);
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
   EXPECT_TRUE(registrar().IsInstalled(app_id));
 }
 
@@ -677,7 +682,8 @@
 
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), app_config), absl::nullopt);
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 }
 
@@ -691,7 +697,8 @@
 
   std::string app_config = base::ReplaceStringPlaceholders(
       kFeatureNameOrInstalledConfig, {GetAppUrl().spec()}, nullptr);
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
 
   {
     base::AutoReset<bool> enable_feature =
@@ -723,7 +730,8 @@
         "user_type": ["unmanaged"]
       })",
       {GetAppUrl().spec()}, nullptr);
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
 
   // Preinstall web app.
   {
@@ -793,7 +801,8 @@
         "user_type": ["unmanaged"]
       })",
       {GetAppUrl().spec()}, nullptr);
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
   ASSERT_FALSE(registrar().IsInstalled(app_id));
   UserUninstalledPreinstalledWebAppPrefs prefs(profile()->GetPrefs());
   prefs.Add(app_id, {GetAppUrl()});
@@ -828,7 +837,8 @@
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), app_config),
             webapps::InstallResultCode::kSuccessNewInstall);
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
   EXPECT_TRUE(registrar().IsInstalledByDefaultManagement(app_id));
 
   // Simulate the effects of https://crbug.com/1359205 by adding an installed
@@ -856,7 +866,7 @@
   constexpr char kAppStartUrl[] = "https://offline-site.com/start.html";
   constexpr char kAppScope[] = "https://offline-site.com/";
 
-  AppId app_id =
+  webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, GURL(kAppStartUrl));
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 
@@ -908,7 +918,7 @@
       "/web_apps/offline-only-start-url-that-does-not-exist.html");
   GURL scope = embedded_test_server()->GetURL("/web_apps/");
 
-  AppId offline_app_id =
+  webapps::AppId offline_app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, offline_start_url);
   EXPECT_FALSE(registrar().IsInstalled(offline_app_id));
 
@@ -935,7 +945,8 @@
   EXPECT_FALSE(registrar().IsInstalled(offline_app_id));
 
   // basic.html's manifest start_url is basic.html.
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, install_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, install_url);
   EXPECT_TRUE(registrar().IsInstalled(app_id));
   EXPECT_EQ(registrar().GetAppShortName(app_id), "Basic web app");
   EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), install_url);
@@ -953,7 +964,7 @@
   constexpr char kAppStartUrl[] = "https://offline-site.com/start.html";
   constexpr char kAppScope[] = "https://offline-site.com/";
 
-  AppId app_id =
+  webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, GURL(kAppStartUrl));
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 
@@ -1006,7 +1017,8 @@
       "/web_apps/offline-only-start-url-that-does-not-exist.html");
   GURL scope = embedded_test_server()->GetURL("/web_apps/");
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   EXPECT_FALSE(registrar().IsInstalled(app_id));
 
   constexpr char kAppConfigTemplate[] =
@@ -1124,7 +1136,8 @@
                                           {GetAppUrl().spec()}, nullptr)),
             webapps::InstallResultCode::kSuccessNewInstall);
 
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
   EXPECT_TRUE(registrar().WasInstalledByOem(app_id));
 
   // Wait for app service to see the newly installed app.
@@ -1176,7 +1189,8 @@
         "user_type": ["unmanaged"]
       })",
       {GetAppUrl().spec()}, nullptr);
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
   const auto& ignore_configs = manager().debug_info()->ignore_configs;
   constexpr char kErrorMessage[] =
       " ignore because the device does not have a built-in touchscreen with "
@@ -1214,7 +1228,8 @@
         "user_type": ["unmanaged"]
       })",
       {GetAppUrl().spec()}, nullptr);
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
 
   EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), manifest),
             webapps::InstallResultCode::kSuccessNewInstall);
@@ -1244,7 +1259,8 @@
         "user_type": ["unmanaged"]
       })",
       {GetAppUrl().spec()}, nullptr);
-  AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
+  webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, GetAppUrl());
 
   // Clear out the device list and re-initialize it after a delay. Web app
   // installation should wait for this to be ready.
@@ -1300,14 +1316,14 @@
       kAppConfigTemplate, {preinstalled_app_start_url.spec()}, nullptr);
   EXPECT_EQ(SyncPreinstalledAppConfig(preinstalled_app_start_url, app_config),
             webapps::InstallResultCode::kSuccessOfflineOnlyInstall);
-  AppId preinstalled_app_id =
+  webapps::AppId preinstalled_app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, preinstalled_app_start_url);
 
   // Install user app.
   auto install_info = std::make_unique<WebAppInstallInfo>();
   install_info->start_url = user_app_start_url;
   install_info->title = u"Test user app";
-  AppId user_app_id =
+  webapps::AppId user_app_id =
       web_app::test::InstallWebApp(profile(), std::move(install_info));
 
   // Put apps in app list folder.
@@ -1345,7 +1361,7 @@
   GURL start_url = install_url;
   GURL scope = embedded_test_server()->GetURL("/web_apps/");
 
-  const AppId app_id = InstallWebAppFromPage(browser(), install_url);
+  const webapps::AppId app_id = InstallWebAppFromPage(browser(), install_url);
 
   const WebApp* web_app = registrar().GetAppById(app_id);
   ASSERT_TRUE(web_app);
diff --git a/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
index 243a437b3..bf9f5cf 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
@@ -114,7 +114,7 @@
     return embedded_test_server()->GetURL(kWebAppPath);
   }
 
-  AppId GetWebAppId() const {
+  webapps::AppId GetWebAppId() const {
     return GenerateAppId(/*manifest_id=*/absl::nullopt, GetWebAppUrl());
   }
 
@@ -139,7 +139,7 @@
     // We uninstall all web apps, as Ash is not restarted between Lacros tests.
     auto* const provider = WebAppProvider::GetForTest(profile());
     const WebAppRegistrar& registrar = provider->registrar_unsafe();
-    std::vector<AppId> app_ids = registrar.GetAppIds();
+    std::vector<webapps::AppId> app_ids = registrar.GetAppIds();
     for (const auto& app_id : app_ids) {
       if (!registrar.IsInstalled(app_id)) {
         continue;
@@ -520,7 +520,7 @@
 
   // Check UI preferences have migrated across.
   {
-    const AppId web_app_id = GetWebAppId();
+    const webapps::AppId web_app_id = GetWebAppId();
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     // Chrome OS shelf/list position should migrate.
@@ -815,7 +815,7 @@
   auto& test_controller =
       lacros_service->GetRemote<crosapi::mojom::TestController>();
 
-  AppId old_app_id;
+  webapps::AppId old_app_id;
   {
     auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = embedded_test_server()->GetURL("/webapps/migration/old/");
@@ -833,7 +833,7 @@
     ASSERT_TRUE(future.Wait());
   }
 
-  AppId new_app_id;
+  webapps::AppId new_app_id;
   {
     auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = embedded_test_server()->GetURL("/webapps/migration/new/");
@@ -841,7 +841,7 @@
 
     WebAppInstallParams install_params;
     install_params.bypass_service_worker_check = true;
-    base::test::TestFuture<const AppId&, webapps::InstallResultCode,
+    base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode,
                            bool /*did_uninstall_and_replace*/>
         future;
     WebAppProvider::GetForTest(profile())
@@ -855,7 +855,7 @@
     EXPECT_EQ(future.Get<webapps::InstallResultCode>(),
               webapps::InstallResultCode::kSuccessNewInstall);
     EXPECT_TRUE(future.Get<bool /*did_uninstall_and_replace*/>());
-    new_app_id = future.Get<AppId>();
+    new_app_id = future.Get<webapps::AppId>();
     apps::AppReadinessWaiter(profile(), new_app_id).Await();
   }
 
diff --git a/chrome/browser/web_applications/preinstalled_web_app_window_experiment.cc b/chrome/browser/web_applications/preinstalled_web_app_window_experiment.cc
index 2a31084..b25e31f 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_window_experiment.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_window_experiment.cc
@@ -47,9 +47,9 @@
 
 namespace utils = preinstalled_web_app_window_experiment_utils;
 
-base::flat_set<AppId> GetLaunchedPreinstalledAppIds(
+base::flat_set<webapps::AppId> GetLaunchedPreinstalledAppIds(
     WebAppRegistrar& registrar) {
-  std::vector<AppId> app_ids;
+  std::vector<webapps::AppId> app_ids;
   for (const WebApp& web_app : registrar.GetApps()) {
     if (web_app.IsPreinstalledApp() && !web_app.last_launch_time().is_null()) {
       app_ids.push_back(web_app.app_id());
@@ -58,10 +58,10 @@
   return app_ids;
 }
 
-std::vector<AppId> SetSupportedLinksPreferenceForPreinstalledApps(
+std::vector<webapps::AppId> SetSupportedLinksPreferenceForPreinstalledApps(
     WebAppRegistrar& registrar,
     apps::AppServiceProxy& proxy) {
-  std::vector<AppId> apps_affected;
+  std::vector<webapps::AppId> apps_affected;
   for (const WebApp& web_app : registrar.GetApps()) {
     if (web_app.IsPreinstalledApp()) {
       proxy.SetSupportedLinksPreference(web_app.app_id());
@@ -84,10 +84,10 @@
   UserDisplayMode display_mode = opt_display_mode.value();
 
   // Exclude any apps for which the user has explicitly set a display mode.
-  base::flat_set<AppId> user_set_apps =
+  base::flat_set<webapps::AppId> user_set_apps =
       utils::GetAppIdsWithUserOverridenDisplayModePref(pref_service);
 
-  std::vector<std::pair<AppId, UserDisplayMode>> overrides;
+  std::vector<std::pair<webapps::AppId, UserDisplayMode>> overrides;
   for (const WebApp& web_app : registrar.GetApps()) {
     if (web_app.IsPreinstalledApp() &&
         !user_set_apps.contains(web_app.app_id())) {
@@ -121,21 +121,21 @@
 
   // Set all default apps to the experiment display mode, unless the user has
   // manually set the display mode for that app.
-  base::flat_set<AppId> user_set_apps =
+  base::flat_set<webapps::AppId> user_set_apps =
       utils::GetAppIdsWithUserOverridenDisplayModePref(pref_service);
-  std::vector<AppId> experiment_overrides;
+  std::vector<webapps::AppId> experiment_overrides;
   for (const WebApp& web_app : provider.registrar_unsafe().GetApps()) {
     if (web_app.IsPreinstalledApp() &&
         !user_set_apps.contains(web_app.app_id())) {
       experiment_overrides.emplace_back(web_app.app_id());
     }
   }
-  for (const AppId& app_id : experiment_overrides) {
+  for (const webapps::AppId& app_id : experiment_overrides) {
     provider.scheduler().ScheduleCallbackWithLock(
         "PreinstalledWebAppWindowExperiment:PersistStateFromPrefsToWebAppDb",
         std::make_unique<AppLockDescription>(app_id),
         base::BindOnce(
-            [](AppId app_id, mojom::UserDisplayMode display_mode,
+            [](webapps::AppId app_id, mojom::UserDisplayMode display_mode,
                AppLock& lock) {
               lock.sync_bridge().SetAppUserDisplayMode(
                   app_id, display_mode,
@@ -233,7 +233,7 @@
   // Make the UserGroup setting persist even if the experiment settings change.
   utils::SetUserGroupPref(profile_->GetPrefs(), utils::GetUserGroup());
 
-  base::flat_set<AppId> launched_before =
+  base::flat_set<webapps::AppId> launched_before =
       GetLaunchedPreinstalledAppIds(registrar_unsafe());
   utils::SetHasLaunchedAppsBeforePref(profile_->GetPrefs(), launched_before);
 
@@ -289,7 +289,7 @@
 }
 
 void PreinstalledWebAppWindowExperiment::OnWebAppUserDisplayModeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     UserDisplayMode user_display_mode) {
   auto* app = registrar_unsafe().GetAppById(app_id);
   if (!app || !app->IsPreinstalledApp()) {
diff --git a/chrome/browser/web_applications/preinstalled_web_app_window_experiment.h b/chrome/browser/web_applications/preinstalled_web_app_window_experiment.h
index 4c705ce7..6bf3adb8 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_window_experiment.h
+++ b/chrome/browser/web_applications/preinstalled_web_app_window_experiment.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registrar_observer.h"
 #include "components/services/app_service/public/cpp/preferred_apps_list_handle.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -76,7 +77,7 @@
   // WebAppRegistrarObserver:
   void OnAppRegistrarDestroyed() override;
   void OnWebAppUserDisplayModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       mojom::UserDisplayMode user_display_mode) override;
 
   // PreferredAppsListHandle::Observer:
@@ -89,7 +90,8 @@
 
   // Set of apps for which the experiment called `SetSupportedLinksPreference`
   // and hasn't yet observed a resulting `OnPreferredAppChanged`.
-  base::flat_set<AppId> apps_that_experiment_setup_set_supported_links_;
+  base::flat_set<webapps::AppId>
+      apps_that_experiment_setup_set_supported_links_;
 
   const raw_ptr<Profile> profile_;
   base::OneShotEvent preinstalled_apps_installed_;
diff --git a/chrome/browser/web_applications/preinstalled_web_app_window_experiment_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_window_experiment_browsertest.cc
index c6950b2..d424ea0 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_window_experiment_browsertest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_window_experiment_browsertest.cc
@@ -38,7 +38,6 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_database_factory.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -54,6 +53,7 @@
 #include "components/sync/test/mock_model_type_change_processor.h"
 #include "components/user_manager/user_names.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -127,7 +127,7 @@
 
   // WebAppRegistrarObserver:
   void OnWebAppUserDisplayModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       UserDisplayMode user_display_mode) override {
     recorded_display_mode_changes_[app_id] = user_display_mode;
   }
@@ -216,8 +216,8 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
   }
 
-  std::map<AppId, UserDisplayMode> recorded_display_mode_changes_;
-  std::map<AppId, bool> recorded_link_capturing_changes_;
+  std::map<webapps::AppId, UserDisplayMode> recorded_display_mode_changes_;
+  std::map<webapps::AppId, bool> recorded_link_capturing_changes_;
 
  private:
   std::unique_ptr<KeyedService> CreateFakeWebAppProvider(Profile* profile) {
@@ -353,7 +353,7 @@
 IN_PROC_BROWSER_TEST_F(PreinstalledWebAppWindowExperimentBrowserTestWindow,
                        IneligibleDueToNonRecentApp) {
   // Install an app and set install time as if installed a long time ago.
-  AppId app_id = test::InstallDummyWebApp(
+  webapps::AppId app_id = test::InstallDummyWebApp(
       browser()->profile(), "non-recent app", GURL("https://example.com"));
   auto& fake_provider = static_cast<FakeWebAppProvider&>(provider());
   WebApp* app = fake_provider.GetRegistrarMutable().GetAppByIdMutable(app_id);
@@ -373,9 +373,9 @@
 IN_PROC_BROWSER_TEST_F(PreinstalledWebAppWindowExperimentBrowserTestWindow,
                        IneligibleDueToSyncInstalledApp) {
   // Install an app as if it came from sync.
-  AppId app_id = test::InstallDummyWebApp(browser()->profile(), "app from sync",
-                                          GURL("https://example.com"),
-                                          webapps::WebappInstallSource::SYNC);
+  webapps::AppId app_id = test::InstallDummyWebApp(
+      browser()->profile(), "app from sync", GURL("https://example.com"),
+      webapps::WebappInstallSource::SYNC);
 
   // Allow eligibility check to happen.
   SimulateSyncReady();
@@ -390,7 +390,7 @@
 IN_PROC_BROWSER_TEST_F(PreinstalledWebAppWindowExperimentBrowserTestWindow,
                        IneligibleDueToPendingSyncInstalledApp) {
   // Install an app and set as if just received from sync.
-  AppId app_id = test::InstallDummyWebApp(
+  webapps::AppId app_id = test::InstallDummyWebApp(
       browser()->profile(), "non-recent app", GURL("https://example.com"));
   auto& fake_provider = static_cast<FakeWebAppProvider&>(provider());
   WebApp* app = fake_provider.GetRegistrarMutable().GetAppByIdMutable(app_id);
@@ -413,13 +413,13 @@
   AwaitPreinstalledAppsInstalled();
 
   // Install an app and set launch time as if recently launched.
-  AppId launched_app_id = test::InstallDummyWebApp(
+  webapps::AppId launched_app_id = test::InstallDummyWebApp(
       browser()->profile(), "launched app", GURL("https://example1.com"),
       webapps::WebappInstallSource::INTERNAL_DEFAULT);
   provider().sync_bridge_unsafe().SetAppLastLaunchTime(launched_app_id,
                                                        base::Time::Now());
 
-  AppId unlaunched_app_id = test::InstallDummyWebApp(
+  webapps::AppId unlaunched_app_id = test::InstallDummyWebApp(
       browser()->profile(), "unlaunched app", GURL("https://example2.com"),
       webapps::WebappInstallSource::INTERNAL_DEFAULT);
 
@@ -448,11 +448,12 @@
   AwaitPreinstalledAppsInstalled();
 
   // Use a real preinstalled app if available, otherwise install a fake one.
-  // AppId must match a known preinstalled app for metrics to be recorded.
+  // webapps::AppId must match a known preinstalled app for metrics to be
+  // recorded.
   if (!provider().registrar_unsafe().IsInstalled(kGoogleDriveAppId)) {
     // Install an app and set supported links preference so experiment setting
     // it won't cause any observations.
-    AppId app_id = test::InstallDummyWebApp(
+    webapps::AppId app_id = test::InstallDummyWebApp(
         browser()->profile(), "launched app",
         GURL("https://drive.google.com/?lfhs=2"),
         webapps::WebappInstallSource::INTERNAL_DEFAULT);
@@ -497,11 +498,12 @@
   AwaitPreinstalledAppsInstalled();
 
   // Use a real preinstalled app if available, otherwise install a fake one.
-  // AppId must match a known preinstalled app for metrics to be recorded.
+  // webapps::AppId must match a known preinstalled app for metrics to be
+  // recorded.
   if (!provider().registrar_unsafe().IsInstalled(kGoogleDriveAppId)) {
     // Install an app and set supported links preference so experiment setting
     // it won't cause any observations.
-    AppId app_id = test::InstallDummyWebApp(
+    webapps::AppId app_id = test::InstallDummyWebApp(
         browser()->profile(), "launched app",
         GURL("https://drive.google.com/?lfhs=2"),
         webapps::WebappInstallSource::INTERNAL_DEFAULT);
@@ -578,7 +580,7 @@
     EXPECT_THAT(recorded_display_mode_changes_, IsEmpty());
     EXPECT_THAT(recorded_link_capturing_changes_, IsEmpty());
     // No apps expected to be installed/installing.
-    std::vector<AppId> app_ids;
+    std::vector<webapps::AppId> app_ids;
     for (const WebApp& app : registrar.GetAppsIncludingStubs()) {
       app_ids.emplace_back(app.app_id());
     }
@@ -671,14 +673,14 @@
 
   // User-overridden apps should be recorded.
   PrefService* pref_service = browser()->profile()->GetPrefs();
-  base::flat_set<AppId> overridden_apps =
+  base::flat_set<webapps::AppId> overridden_apps =
       preinstalled_web_app_window_experiment_utils::
           GetAppIdsWithUserOverridenDisplayModePref(pref_service);
   if (GetUserGroupTestParam() == UserGroup::kUnknown) {
     EXPECT_THAT(overridden_apps, IsEmpty());
   } else {
     EXPECT_EQ(overridden_apps,
-              base::flat_set<AppId>(
+              base::flat_set<webapps::AppId>(
                   {kGoogleDriveAppId, kYoutubeAppId, kGoogleCalendarAppId}));
   }
 
diff --git a/chrome/browser/web_applications/preinstalled_web_app_window_experiment_utils.cc b/chrome/browser/web_applications/preinstalled_web_app_window_experiment_utils.cc
index 3afb81d..a828400 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_window_experiment_utils.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_window_experiment_utils.cc
@@ -244,7 +244,7 @@
 // Apps launched before experiment:
 ///////////////////////////////////////////////////////////////////////////////
 
-bool HasLaunchedAppBeforeExperiment(const AppId& app_id,
+bool HasLaunchedAppBeforeExperiment(const webapps::AppId& app_id,
                                     PrefService* pref_service) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
@@ -256,12 +256,12 @@
 
 void SetHasLaunchedAppsBeforePref(
     PrefService* pref_service,
-    const base::flat_set<AppId>& preinstalled_apps_launched_before) {
+    const base::flat_set<webapps::AppId>& preinstalled_apps_launched_before) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   ScopedListPrefUpdate update(pref_service, kAppIdsLaunchedBeforePrefKey);
   update->clear();
-  for (const AppId& app_id : preinstalled_apps_launched_before) {
+  for (const webapps::AppId& app_id : preinstalled_apps_launched_before) {
     update->Append(app_id);
   }
 }
@@ -270,14 +270,14 @@
 // Display mode:
 ///////////////////////////////////////////////////////////////////////////////
 
-base::flat_set<AppId> GetAppIdsWithUserOverridenDisplayModePref(
+base::flat_set<webapps::AppId> GetAppIdsWithUserOverridenDisplayModePref(
     PrefService* pref_service) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   const base::Value::List& user_overridden_app_ids =
       pref_service->GetList(kAppIdsWithUserOverriddenDisplayModePrefKey);
 
-  std::vector<AppId> app_ids;
+  std::vector<webapps::AppId> app_ids;
   for (auto& app_id_value : user_overridden_app_ids) {
     if (app_id_value.is_string()) {
       app_ids.push_back(app_id_value.GetString());
@@ -288,7 +288,7 @@
 
 // Add `app_id` to list of apps with user-overridden display mode.
 void SetUserOverridenDisplayModePref(PrefService* pref_service,
-                                     const AppId& app_id) {
+                                     const webapps::AppId& app_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   ScopedListPrefUpdate update(pref_service,
diff --git a/chrome/browser/web_applications/preinstalled_web_app_window_experiment_utils.h b/chrome/browser/web_applications/preinstalled_web_app_window_experiment_utils.h
index f207cf5..abd988c 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_window_experiment_utils.h
+++ b/chrome/browser/web_applications/preinstalled_web_app_window_experiment_utils.h
@@ -10,6 +10,7 @@
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom-forward.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/common/chrome_features.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -71,19 +72,20 @@
 
 // Returns whether the given preinstalled app was launched before the
 // experiment began.
-bool HasLaunchedAppBeforeExperiment(const AppId& preinstalled_app_id,
+bool HasLaunchedAppBeforeExperiment(const webapps::AppId& preinstalled_app_id,
                                     PrefService* pref_service);
 
-void SetHasLaunchedAppsBeforePref(PrefService* pref_service,
-                                  const base::flat_set<AppId>& app_ids);
+void SetHasLaunchedAppsBeforePref(
+    PrefService* pref_service,
+    const base::flat_set<webapps::AppId>& app_ids);
 
 // Display mode:
 
-base::flat_set<AppId> GetAppIdsWithUserOverridenDisplayModePref(
+base::flat_set<webapps::AppId> GetAppIdsWithUserOverridenDisplayModePref(
     PrefService* pref_service);
 
 void SetUserOverridenDisplayModePref(PrefService* pref_service,
-                                     const AppId& app_id);
+                                     const webapps::AppId& app_id);
 
 // Histograms:
 
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h
index 6598284f..570d0fd 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h
+++ b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h
@@ -27,8 +27,8 @@
   ~PreinstalledWebAppMigration();
 
   GURL install_url;
-  AppId expected_web_app_id;
-  AppId old_chrome_app_id;
+  webapps::AppId expected_web_app_id;
+  webapps::AppId old_chrome_app_id;
 };
 
 // Returns the list of preinstalled web apps that are migrations away from their
diff --git a/chrome/browser/web_applications/test/fake_os_integration_manager.cc b/chrome/browser/web_applications/test/fake_os_integration_manager.cc
index 46af1b7c..1de34dc 100644
--- a/chrome/browser/web_applications/test/fake_os_integration_manager.cc
+++ b/chrome/browser/web_applications/test/fake_os_integration_manager.cc
@@ -43,14 +43,15 @@
 
 FakeOsIntegrationManager::~FakeOsIntegrationManager() = default;
 
-void FakeOsIntegrationManager::SetNextCreateShortcutsResult(const AppId& app_id,
-                                                            bool success) {
+void FakeOsIntegrationManager::SetNextCreateShortcutsResult(
+    const webapps::AppId& app_id,
+    bool success) {
   CHECK(!base::Contains(next_create_shortcut_results_, app_id));
   next_create_shortcut_results_[app_id] = success;
 }
 
 void FakeOsIntegrationManager::InstallOsHooks(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     InstallOsHooksCallback callback,
     std::unique_ptr<WebAppInstallInfo> web_app_info,
     InstallOsHooksOptions options) {
@@ -92,7 +93,7 @@
 }
 
 void FakeOsIntegrationManager::UninstallOsHooks(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const OsHooksOptions& os_hooks,
     UninstallOsHooksCallback callback) {
   if (os_hooks[OsHookType::kRunOnOsLogin]) {
@@ -104,7 +105,7 @@
 }
 
 void FakeOsIntegrationManager::UninstallAllOsHooks(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     UninstallOsHooksCallback callback) {
   OsHooksOptions os_hooks;
   os_hooks.set();
@@ -112,7 +113,7 @@
 }
 
 void FakeOsIntegrationManager::UpdateOsHooks(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::StringPiece old_name,
     FileHandlerUpdateAction file_handlers_need_os_update,
     const WebAppInstallInfo& web_app_info,
@@ -126,7 +127,7 @@
 }
 
 void FakeOsIntegrationManager::Synchronize(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure callback,
     absl::optional<SynchronizeOsOptions> options) {
   // Holding a scoped_supress ensures that execution is skipped during the
@@ -170,18 +171,18 @@
 TestShortcutManager::~TestShortcutManager() = default;
 
 std::unique_ptr<ShortcutInfo> TestShortcutManager::BuildShortcutInfo(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   return nullptr;
 }
 
 void TestShortcutManager::SetShortcutInfoForApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     std::unique_ptr<ShortcutInfo> shortcut_info) {
   shortcut_info_map_[app_id] = std::move(shortcut_info);
 }
 
 void TestShortcutManager::GetShortcutInfoForApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     GetShortcutInfoCallback callback) {
   if (shortcut_info_map_.find(app_id) != shortcut_info_map_.end()) {
     std::move(callback).Run(std::move(shortcut_info_map_[app_id]));
diff --git a/chrome/browser/web_applications/test/fake_os_integration_manager.h b/chrome/browser/web_applications/test/fake_os_integration_manager.h
index 2b5aa18..dfc5448 100644
--- a/chrome/browser/web_applications/test/fake_os_integration_manager.h
+++ b/chrome/browser/web_applications/test/fake_os_integration_manager.h
@@ -9,6 +9,7 @@
 
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
@@ -29,16 +30,16 @@
   ~FakeOsIntegrationManager() override;
 
   // OsIntegrationManager:
-  void InstallOsHooks(const AppId& app_id,
+  void InstallOsHooks(const webapps::AppId& app_id,
                       InstallOsHooksCallback callback,
                       std::unique_ptr<WebAppInstallInfo> web_app_info,
                       InstallOsHooksOptions options) override;
-  void UninstallOsHooks(const AppId& app_id,
+  void UninstallOsHooks(const webapps::AppId& app_id,
                         const OsHooksOptions& os_hooks,
                         UninstallOsHooksCallback callback) override;
-  void UninstallAllOsHooks(const AppId& app_id,
+  void UninstallAllOsHooks(const webapps::AppId& app_id,
                            UninstallOsHooksCallback callback) override;
-  void UpdateOsHooks(const AppId& app_id,
+  void UpdateOsHooks(const webapps::AppId& app_id,
                      base::StringPiece old_name,
                      FileHandlerUpdateAction file_handlers_need_os_update,
                      const WebAppInstallInfo& web_app_info,
@@ -51,7 +52,7 @@
   //
   // See OsIntegrationSynchronizeCommandTest as an example of using this
   // function.
-  void Synchronize(const AppId& app_id,
+  void Synchronize(const webapps::AppId& app_id,
                    base::OnceClosure callback,
                    absl::optional<SynchronizeOsOptions> options) override;
 
@@ -95,7 +96,7 @@
     return last_options_;
   }
 
-  void SetNextCreateShortcutsResult(const AppId& app_id, bool success);
+  void SetNextCreateShortcutsResult(const webapps::AppId& app_id, bool success);
 
   void SetFileHandlerManager(
       std::unique_ptr<WebAppFileHandlerManager> file_handler_manager);
@@ -120,7 +121,7 @@
   absl::optional<InstallOsHooksOptions> last_options_;
 
   bool can_create_shortcuts_ = true;
-  std::map<AppId, bool> next_create_shortcut_results_;
+  std::map<webapps::AppId, bool> next_create_shortcut_results_;
 };
 
 // Stub test shortcut manager.
@@ -128,10 +129,11 @@
  public:
   explicit TestShortcutManager(Profile* profile);
   ~TestShortcutManager() override;
-  std::unique_ptr<ShortcutInfo> BuildShortcutInfo(const AppId& app_id) override;
-  void SetShortcutInfoForApp(const AppId& app_id,
+  std::unique_ptr<ShortcutInfo> BuildShortcutInfo(
+      const webapps::AppId& app_id) override;
+  void SetShortcutInfoForApp(const webapps::AppId& app_id,
                              std::unique_ptr<ShortcutInfo> shortcut_info);
-  void GetShortcutInfoForApp(const AppId& app_id,
+  void GetShortcutInfoForApp(const webapps::AppId& app_id,
                              GetShortcutInfoCallback callback) override;
   void GetAppExistingShortCutLocation(
       ShortcutLocationCallback callback,
@@ -141,7 +143,7 @@
     existing_shortcut_locations_[app_url] = locations;
   }
 
-  std::map<AppId, std::unique_ptr<ShortcutInfo>> shortcut_info_map_;
+  std::map<webapps::AppId, std::unique_ptr<ShortcutInfo>> shortcut_info_map_;
   std::map<GURL, ShortcutLocations> existing_shortcut_locations_;
 };
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/test/fake_url_handler_manager.cc b/chrome/browser/web_applications/test/fake_url_handler_manager.cc
index fef482e..bdcb5e8 100644
--- a/chrome/browser/web_applications/test/fake_url_handler_manager.cc
+++ b/chrome/browser/web_applications/test/fake_url_handler_manager.cc
@@ -13,17 +13,18 @@
 
 FakeUrlHandlerManager::~FakeUrlHandlerManager() = default;
 
-void FakeUrlHandlerManager::RegisterUrlHandlers(const AppId& app_id,
+void FakeUrlHandlerManager::RegisterUrlHandlers(const webapps::AppId& app_id,
                                                 ResultCallback callback) {
   std::move(callback).Run(Result::kOk);
 }
 
-bool FakeUrlHandlerManager::UnregisterUrlHandlers(const AppId& app_id) {
+bool FakeUrlHandlerManager::UnregisterUrlHandlers(
+    const webapps::AppId& app_id) {
   return true;
 }
 
 void FakeUrlHandlerManager::UpdateUrlHandlers(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceCallback<void(bool success)> callback) {
   std::move(callback).Run(true);
 }
diff --git a/chrome/browser/web_applications/test/fake_url_handler_manager.h b/chrome/browser/web_applications/test/fake_url_handler_manager.h
index 3e2c88e..f65fec6d 100644
--- a/chrome/browser/web_applications/test/fake_url_handler_manager.h
+++ b/chrome/browser/web_applications/test/fake_url_handler_manager.h
@@ -8,6 +8,7 @@
 #include "chrome/browser/web_applications/os_integration/url_handler_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -19,11 +20,11 @@
   explicit FakeUrlHandlerManager(Profile* profile);
   ~FakeUrlHandlerManager() override;
 
-  void RegisterUrlHandlers(const AppId& app_id,
+  void RegisterUrlHandlers(const webapps::AppId& app_id,
                            ResultCallback callback) override;
-  bool UnregisterUrlHandlers(const AppId& app_id) override;
+  bool UnregisterUrlHandlers(const webapps::AppId& app_id) override;
   void UpdateUrlHandlers(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceCallback<void(bool success)> callback) override;
 };
 
diff --git a/chrome/browser/web_applications/test/fake_web_app_database_factory.cc b/chrome/browser/web_applications/test/fake_web_app_database_factory.cc
index 8a524804..df373a7 100644
--- a/chrome/browser/web_applications/test/fake_web_app_database_factory.cc
+++ b/chrome/browser/web_applications/test/fake_web_app_database_factory.cc
@@ -46,7 +46,7 @@
           auto app = WebAppDatabase::ParseWebApp(record.id, record.value);
           DCHECK(app);
 
-          AppId app_id = app->app_id();
+          webapps::AppId app_id = app->app_id();
           registry.emplace(std::move(app_id), std::move(app));
         }
         run_loop.Quit();
@@ -56,8 +56,8 @@
   return registry;
 }
 
-std::set<AppId> FakeWebAppDatabaseFactory::ReadAllAppIds() {
-  std::set<AppId> app_ids;
+std::set<webapps::AppId> FakeWebAppDatabaseFactory::ReadAllAppIds() {
+  std::set<webapps::AppId> app_ids;
 
   Registry registry = ReadRegistry();
   for (Registry::value_type& kv : registry)
@@ -77,7 +77,7 @@
     GURL start_url(proto->sync_data().start_url());
     DCHECK(!start_url.is_empty());
     DCHECK(start_url.is_valid());
-    AppId app_id =
+    webapps::AppId app_id =
         GenerateAppId(proto->sync_data().relative_manifest_id(), start_url);
     write_batch->WriteData(app_id, proto->SerializeAsString());
   }
diff --git a/chrome/browser/web_applications/test/fake_web_app_database_factory.h b/chrome/browser/web_applications/test/fake_web_app_database_factory.h
index 25f5341..e7286e85 100644
--- a/chrome/browser/web_applications/test/fake_web_app_database_factory.h
+++ b/chrome/browser/web_applications/test/fake_web_app_database_factory.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/web_app_database_factory.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace syncer {
 class ModelTypeStore;
@@ -36,7 +37,7 @@
 
   Registry ReadRegistry();
 
-  std::set<AppId> ReadAllAppIds();
+  std::set<webapps::AppId> ReadAllAppIds();
 
   void WriteProtos(const std::vector<std::unique_ptr<WebAppProto>>& protos);
   void WriteRegistry(const Registry& registry);
diff --git a/chrome/browser/web_applications/test/fake_web_app_file_handler_manager.cc b/chrome/browser/web_applications/test/fake_web_app_file_handler_manager.cc
index 4ced6fc..e6210e5 100644
--- a/chrome/browser/web_applications/test/fake_web_app_file_handler_manager.cc
+++ b/chrome/browser/web_applications/test/fake_web_app_file_handler_manager.cc
@@ -17,7 +17,7 @@
 FakeWebAppFileHandlerManager::~FakeWebAppFileHandlerManager() = default;
 
 const apps::FileHandlers* FakeWebAppFileHandlerManager::GetAllFileHandlers(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   if (base::Contains(file_handlers_, app_id))
     return &file_handlers_.at(app_id);
 
@@ -29,7 +29,7 @@
 }
 
 void FakeWebAppFileHandlerManager::InstallFileHandler(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& action,
     const AcceptMap& accept,
     absl::optional<apps::FileHandler::LaunchType> launch_type,
diff --git a/chrome/browser/web_applications/test/fake_web_app_file_handler_manager.h b/chrome/browser/web_applications/test/fake_web_app_file_handler_manager.h
index 3185fdbe..11c8cb7 100644
--- a/chrome/browser/web_applications/test/fake_web_app_file_handler_manager.h
+++ b/chrome/browser/web_applications/test/fake_web_app_file_handler_manager.h
@@ -12,6 +12,7 @@
 #include "base/containers/flat_set.h"
 #include "chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
@@ -28,7 +29,7 @@
   ~FakeWebAppFileHandlerManager() override;
 
   const apps::FileHandlers* GetAllFileHandlers(
-      const AppId& app_id) const override;
+      const webapps::AppId& app_id) const override;
 
   bool IsDisabledForTesting() override;
 
@@ -41,14 +42,14 @@
   // enabled, not whether this specific file handler should be enabled. If any
   // file handler is enabled, all of them will be.
   void InstallFileHandler(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const GURL& handler,
       const AcceptMap& accept,
       absl::optional<apps::FileHandler::LaunchType> launch_type,
       bool enable = true);
 
  private:
-  std::map<AppId, apps::FileHandlers> file_handlers_;
+  std::map<webapps::AppId, apps::FileHandlers> file_handlers_;
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/test/fake_web_app_ui_manager.cc b/chrome/browser/web_applications/test/fake_web_app_ui_manager.cc
index 88c605f..5ce0cc5 100644
--- a/chrome/browser/web_applications/test/fake_web_app_ui_manager.cc
+++ b/chrome/browser/web_applications/test/fake_web_app_ui_manager.cc
@@ -27,7 +27,7 @@
 
 void FakeWebAppUiManager::Shutdown() {}
 
-void FakeWebAppUiManager::SetNumWindowsForApp(const AppId& app_id,
+void FakeWebAppUiManager::SetNumWindowsForApp(const webapps::AppId& app_id,
                                               size_t num_windows_for_app) {
   app_id_to_num_windows_map_[app_id] = num_windows_for_app;
 
@@ -47,7 +47,7 @@
 }
 
 void FakeWebAppUiManager::SetOnNotifyOnAllAppWindowsClosedCallback(
-    base::RepeatingCallback<void(AppId)> callback) {
+    base::RepeatingCallback<void(webapps::AppId)> callback) {
   notify_on_all_app_windows_closed_callback_ = std::move(callback);
 }
 
@@ -60,7 +60,7 @@
   return nullptr;
 }
 
-size_t FakeWebAppUiManager::GetNumWindowsForApp(const AppId& app_id) {
+size_t FakeWebAppUiManager::GetNumWindowsForApp(const webapps::AppId& app_id) {
   if (!app_id_to_num_windows_map_.contains(app_id)) {
     return 0;
   }
@@ -68,7 +68,7 @@
 }
 
 void FakeWebAppUiManager::NotifyOnAllAppWindowsClosed(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure callback) {
   notify_on_all_app_windows_closed_callback_.Run(app_id);
 
@@ -85,25 +85,27 @@
   return false;
 }
 
-void FakeWebAppUiManager::AddAppToQuickLaunchBar(const AppId& app_id) {}
+void FakeWebAppUiManager::AddAppToQuickLaunchBar(const webapps::AppId& app_id) {
+}
 
-bool FakeWebAppUiManager::IsAppInQuickLaunchBar(const AppId& app_id) const {
+bool FakeWebAppUiManager::IsAppInQuickLaunchBar(
+    const webapps::AppId& app_id) const {
   return false;
 }
 
 bool FakeWebAppUiManager::IsInAppWindow(content::WebContents* web_contents,
-                                        const AppId* app_id) const {
+                                        const webapps::AppId* app_id) const {
   return false;
 }
 
 bool FakeWebAppUiManager::CanReparentAppTabToWindow(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool shortcut_created) const {
   return true;
 }
 
 void FakeWebAppUiManager::ReparentAppTabToWindow(content::WebContents* contents,
-                                                 const AppId& app_id,
+                                                 const webapps::AppId& app_id,
                                                  bool shortcut_created) {
   ++num_reparent_tab_calls_;
 }
@@ -148,9 +150,10 @@
 }
 
 #if BUILDFLAG(IS_CHROMEOS)
-void FakeWebAppUiManager::MigrateLauncherState(const AppId& from_app_id,
-                                               const AppId& to_app_id,
-                                               base::OnceClosure callback) {
+void FakeWebAppUiManager::MigrateLauncherState(
+    const webapps::AppId& from_app_id,
+    const webapps::AppId& to_app_id,
+    base::OnceClosure callback) {
   std::move(callback).Run();
 }
 
@@ -172,7 +175,7 @@
     content::WebContents* web_contents) {}
 
 void FakeWebAppUiManager::PresentUserUninstallDialog(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     BrowserWindow* parent_window,
     UninstallCompleteCallback callback) {
@@ -180,7 +183,7 @@
 }
 
 void FakeWebAppUiManager::PresentUserUninstallDialog(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     gfx::NativeWindow parent_window,
     UninstallCompleteCallback callback) {
@@ -188,7 +191,7 @@
 }
 
 void FakeWebAppUiManager::PresentUserUninstallDialog(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     gfx::NativeWindow parent_window,
     UninstallCompleteCallback callback,
diff --git a/chrome/browser/web_applications/test/fake_web_app_ui_manager.h b/chrome/browser/web_applications/test/fake_web_app_ui_manager.h
index 491f69d2..f5ba6acd 100644
--- a/chrome/browser/web_applications/test/fake_web_app_ui_manager.h
+++ b/chrome/browser/web_applications/test/fake_web_app_ui_manager.h
@@ -30,36 +30,37 @@
   void Start() override;
   void Shutdown() override;
 
-  void SetNumWindowsForApp(const AppId& app_id, size_t num_windows_for_app);
+  void SetNumWindowsForApp(const webapps::AppId& app_id,
+                           size_t num_windows_for_app);
   void SetOnNotifyOnAllAppWindowsClosedCallback(
-      base::RepeatingCallback<void(AppId)> callback);
+      base::RepeatingCallback<void(webapps::AppId)> callback);
   int num_reparent_tab_calls() const { return num_reparent_tab_calls_; }
 
   void SetOnLaunchWebAppCallback(OnLaunchWebAppCallback callback);
 
   // WebAppUiManager:
   WebAppUiManagerImpl* AsImpl() override;
-  size_t GetNumWindowsForApp(const AppId& app_id) override;
-  void CloseAppWindows(const AppId& app_id) override {}
-  void NotifyOnAllAppWindowsClosed(const AppId& app_id,
+  size_t GetNumWindowsForApp(const webapps::AppId& app_id) override;
+  void CloseAppWindows(const webapps::AppId& app_id) override {}
+  void NotifyOnAllAppWindowsClosed(const webapps::AppId& app_id,
                                    base::OnceClosure callback) override;
   bool CanAddAppToQuickLaunchBar() const override;
-  void AddAppToQuickLaunchBar(const AppId& app_id) override;
-  bool IsAppInQuickLaunchBar(const AppId& app_id) const override;
+  void AddAppToQuickLaunchBar(const webapps::AppId& app_id) override;
+  bool IsAppInQuickLaunchBar(const webapps::AppId& app_id) const override;
   bool IsInAppWindow(content::WebContents* web_contents,
-                     const AppId* app_id) const override;
+                     const webapps::AppId* app_id) const override;
   void NotifyOnAssociatedAppChanged(
       content::WebContents* web_contents,
-      const absl::optional<AppId>& previous_app_id,
-      const absl::optional<AppId>& new_app_id) const override {}
-  bool CanReparentAppTabToWindow(const AppId& app_id,
+      const absl::optional<webapps::AppId>& previous_app_id,
+      const absl::optional<webapps::AppId>& new_app_id) const override {}
+  bool CanReparentAppTabToWindow(const webapps::AppId& app_id,
                                  bool shortcut_created) const override;
   void ReparentAppTabToWindow(content::WebContents* contents,
-                              const AppId& app_id,
+                              const webapps::AppId& app_id,
                               bool shortcut_created) override;
   void ShowWebAppFileLaunchDialog(
       const std::vector<base::FilePath>& file_paths,
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppLaunchAcceptanceCallback launch_callback) override {}
   void ShowWebAppIdentityUpdateDialog(
       const std::string& app_id,
@@ -71,7 +72,7 @@
       const SkBitmap& new_icon,
       content::WebContents* web_contents,
       AppIdentityDialogCallback callback) override;
-  void ShowWebAppSettings(const AppId& app_id) override {}
+  void ShowWebAppSettings(const webapps::AppId& app_id) override {}
 
   base::Value LaunchWebApp(apps::AppLaunchParams params,
                            LaunchWebAppWindowSetting launch_setting,
@@ -79,8 +80,8 @@
                            LaunchWebAppCallback callback,
                            AppLock& lock) override;
 #if BUILDFLAG(IS_CHROMEOS)
-  void MigrateLauncherState(const AppId& from_app_id,
-                            const AppId& to_app_id,
+  void MigrateLauncherState(const webapps::AppId& from_app_id,
+                            const webapps::AppId& to_app_id,
                             base::OnceClosure callback) override;
 
   void DisplayRunOnOsLoginNotification(
@@ -91,33 +92,33 @@
   void TriggerInstallDialog(content::WebContents* web_contents) override;
 
   void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       BrowserWindow* parent_window,
       UninstallCompleteCallback callback) override;
 
   void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       gfx::NativeWindow parent_window,
       UninstallCompleteCallback callback) override;
 
   void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       gfx::NativeWindow parent_window,
       UninstallCompleteCallback callback,
       UninstallScheduledCallback scheduled_callback) override;
 
  private:
-  base::flat_map<AppId, size_t> app_id_to_num_windows_map_;
-  // Closures waiting to be called when all windows for a given `AppId` are
-  // closed.
-  base::flat_map<AppId, std::vector<base::OnceClosure>>
+  base::flat_map<webapps::AppId, size_t> app_id_to_num_windows_map_;
+  // Closures waiting to be called when all windows for a given `webapps::AppId`
+  // are closed.
+  base::flat_map<webapps::AppId, std::vector<base::OnceClosure>>
       windows_closed_requests_map_;
 
   // Callback that is triggered after `NotifyOnAllAppWindowsClosed` is called.
-  base::RepeatingCallback<void(AppId)>
+  base::RepeatingCallback<void(webapps::AppId)>
       notify_on_all_app_windows_closed_callback_ = base::DoNothing();
 
   int num_reparent_tab_calls_ = 0;
diff --git a/chrome/browser/web_applications/test/fake_web_contents_manager.cc b/chrome/browser/web_applications/test/fake_web_contents_manager.cc
index fb439ee..7c8d5585 100644
--- a/chrome/browser/web_applications/test/fake_web_contents_manager.cc
+++ b/chrome/browser/web_applications/test/fake_web_contents_manager.cc
@@ -380,7 +380,7 @@
   icon_state_.erase(icon_url);
 }
 
-AppId FakeWebContentsManager::CreateBasicInstallPageState(
+webapps::AppId FakeWebContentsManager::CreateBasicInstallPageState(
     const GURL& install_url,
     const GURL& manifest_url,
     const GURL& start_url,
diff --git a/chrome/browser/web_applications/test/fake_web_contents_manager.h b/chrome/browser/web_applications/test/fake_web_contents_manager.h
index 7ba69c76..2cddbf76 100644
--- a/chrome/browser/web_applications/test/fake_web_contents_manager.h
+++ b/chrome/browser/web_applications/test/fake_web_contents_manager.h
@@ -54,9 +54,9 @@
     FakePageState(FakePageState&&);
     FakePageState& operator=(FakePageState&&);
 
-    AppId PopulateWithBasicManifest(GURL install_url,
-                                    GURL manifest_url,
-                                    GURL start_url);
+    webapps::AppId PopulateWithBasicManifest(GURL install_url,
+                                             GURL manifest_url,
+                                             GURL start_url);
 
     // `WebAppUrlLoader::LoadUrl`:
     // If this is populated, then a redirection is always assumed. If the
@@ -116,7 +116,7 @@
   // Set the behavior for calls to `LoadUrl`, `GetWebAppInstallInfo`, and
   // `CheckInstallabilityAndRetrieveManifest` from wrappers returned by this
   // fake class.
-  AppId CreateBasicInstallPageState(
+  webapps::AppId CreateBasicInstallPageState(
       const GURL& install_url,
       const GURL& manifest_url,
       const GURL& start_url,
diff --git a/chrome/browser/web_applications/test/mock_os_integration_manager.h b/chrome/browser/web_applications/test/mock_os_integration_manager.h
index 607da15..ab0d66a 100644
--- a/chrome/browser/web_applications/test/mock_os_integration_manager.h
+++ b/chrome/browser/web_applications/test/mock_os_integration_manager.h
@@ -29,14 +29,14 @@
   // Installation:
   MOCK_METHOD(void,
               Synchronize,
-              (const AppId& app_id,
+              (const webapps::AppId& app_id,
                base::OnceClosure callback,
                absl::optional<SynchronizeOsOptions> options),
               (override));
 
   MOCK_METHOD(void,
               CreateShortcuts,
-              (const AppId& app_id,
+              (const webapps::AppId& app_id,
                bool add_to_desktop,
                ShortcutCreationReason reason,
                CreateShortcutsCallback callback),
@@ -44,20 +44,20 @@
 
   MOCK_METHOD(void,
               RegisterFileHandlers,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
 
   MOCK_METHOD(void,
               RegisterProtocolHandlers,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
   MOCK_METHOD(void,
               RegisterUrlHandlers,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
   MOCK_METHOD(void,
               RegisterShortcutsMenu,
-              (const AppId& app_id,
+              (const webapps::AppId& app_id,
                const std::vector<WebAppShortcutsMenuItemInfo>&
                    shortcuts_menu_item_infos,
                const ShortcutsMenuIconBitmaps& shortcuts_menu_icon_bitmaps,
@@ -66,64 +66,70 @@
 
   MOCK_METHOD(void,
               ReadAllShortcutsMenuIconsAndRegisterShortcutsMenu,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
 
   MOCK_METHOD(void,
               RegisterRunOnOsLogin,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
 
   MOCK_METHOD(void,
               MacAppShimOnAppInstalledForProfile,
-              (const AppId& app_id),
+              (const webapps::AppId& app_id),
               (override));
 
-  MOCK_METHOD(void, AddAppToQuickLaunchBar, (const AppId& app_id), (override));
+  MOCK_METHOD(void,
+              AddAppToQuickLaunchBar,
+              (const webapps::AppId& app_id),
+              (override));
 
   MOCK_METHOD(void,
               RegisterWebAppOsUninstallation,
-              (const AppId& app_id, const std::string& name),
+              (const webapps::AppId& app_id, const std::string& name),
               (override));
 
   // Uninstallation:
   MOCK_METHOD(void,
               UninstallAllOsHooks,
-              (const AppId& app_id, UninstallOsHooksCallback callback),
+              (const webapps::AppId& app_id, UninstallOsHooksCallback callback),
               (override));
   MOCK_METHOD(bool,
               UnregisterShortcutsMenu,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
   MOCK_METHOD(void,
               UnregisterRunOnOsLogin,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
   MOCK_METHOD(void,
               DeleteShortcuts,
-              (const AppId& app_id,
+              (const webapps::AppId& app_id,
                const base::FilePath& shortcuts_data_dir,
                std::unique_ptr<ShortcutInfo> shortcut_info,
                ResultCallback callback),
               (override));
   MOCK_METHOD(void,
               UnregisterFileHandlers,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
   MOCK_METHOD(void,
               UnregisterProtocolHandlers,
-              (const AppId& app_id, ResultCallback callback),
+              (const webapps::AppId& app_id, ResultCallback callback),
               (override));
-  MOCK_METHOD(void, UnregisterUrlHandlers, (const AppId& app_id), (override));
+  MOCK_METHOD(void,
+              UnregisterUrlHandlers,
+              (const webapps::AppId& app_id),
+              (override));
   MOCK_METHOD(void,
               UnregisterWebAppOsUninstallation,
-              (const AppId& app_id),
+              (const webapps::AppId& app_id),
               (override));
 
   // Update:
   MOCK_METHOD(void,
               UpdateShortcuts,
-              (const AppId& app_id,
+              (const webapps::AppId& app_id,
                base::StringPiece old_name,
                ResultCallback callback),
               (override));
@@ -131,7 +137,7 @@
   // Utility methods:
   MOCK_METHOD(std::unique_ptr<ShortcutInfo>,
               BuildShortcutInfo,
-              (const AppId& app_id),
+              (const webapps::AppId& app_id),
               (override));
 };
 
diff --git a/chrome/browser/web_applications/test/os_integration_test_override_impl.cc b/chrome/browser/web_applications/test/os_integration_test_override_impl.cc
index 2dd5745..69cec86 100644
--- a/chrome/browser/web_applications/test/os_integration_test_override_impl.cc
+++ b/chrome/browser/web_applications/test/os_integration_test_override_impl.cc
@@ -35,9 +35,9 @@
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -130,7 +130,7 @@
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
 // Performs a blocking read of app icons from the disk.
 SkColor IconManagerReadIconTopLeftColorForSize(WebAppIconManager& icon_manager,
-                                               const AppId& app_id,
+                                               const webapps::AppId& app_id,
                                                SquareSizePx size_px) {
   SkColor result = SK_ColorTRANSPARENT;
   if (!icon_manager.HasIcons(app_id, IconPurpose::ANY, {size_px})) {
@@ -208,7 +208,7 @@
 
 bool OsIntegrationTestOverrideImpl::SimulateDeleteShortcutsByUser(
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name) {
 #if BUILDFLAG(IS_WIN)
   base::FilePath desktop_shortcut_path =
@@ -276,7 +276,7 @@
 
 bool OsIntegrationTestOverrideImpl::IsRunOnOsLoginEnabled(
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name) {
 #if BUILDFLAG(IS_LINUX)
   std::string shortcut_filename =
@@ -299,7 +299,7 @@
 
 bool OsIntegrationTestOverrideImpl::IsFileExtensionHandled(
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     std::string app_name,
     std::string file_extension) {
   base::ScopedAllowBlockingForTesting allow_blocking;
@@ -368,7 +368,7 @@
 OsIntegrationTestOverrideImpl::GetShortcutIconTopLeftColor(
     Profile* profile,
     base::FilePath shortcut_dir,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     SquareSizePx size_px) {
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
@@ -394,7 +394,7 @@
 base::FilePath OsIntegrationTestOverrideImpl::GetShortcutPath(
     Profile* profile,
     base::FilePath shortcut_dir,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name) {
 #if BUILDFLAG(IS_WIN)
   base::FileEnumerator enumerator(shortcut_dir, false,
@@ -441,7 +441,7 @@
 
 bool OsIntegrationTestOverrideImpl::IsShortcutCreated(
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name) {
 #if BUILDFLAG(IS_WIN)
   base::FilePath desktop_shortcut_path =
@@ -495,7 +495,7 @@
 
 base::expected<bool, std::string>
 OsIntegrationTestOverrideImpl::IsUninstallRegisteredWithOs(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& app_name,
     Profile* profile) {
   constexpr wchar_t kUninstallRegistryKey[] =
@@ -656,7 +656,7 @@
 #endif  // BUILDFLAG(IS_LINUX)
 
 void OsIntegrationTestOverrideImpl::RegisterProtocolSchemes(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     std::vector<std::string> protocols) {
   protocol_scheme_registrations_.emplace_back(app_id, std::move(protocols));
 }
diff --git a/chrome/browser/web_applications/test/os_integration_test_override_impl.h b/chrome/browser/web_applications/test/os_integration_test_override_impl.h
index 12fdd734..fb0f6f8 100644
--- a/chrome/browser/web_applications/test/os_integration_test_override_impl.h
+++ b/chrome/browser/web_applications/test/os_integration_test_override_impl.h
@@ -22,6 +22,7 @@
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 
@@ -57,7 +58,7 @@
 class OsIntegrationTestOverrideImpl : public OsIntegrationTestOverride {
  public:
   using AppProtocolList =
-      std::vector<std::tuple<AppId, std::vector<std::string>>>;
+      std::vector<std::tuple<webapps::AppId, std::vector<std::string>>>;
 #if BUILDFLAG(IS_WIN)
   using JumpListEntryMap =
       base::flat_map<std::wstring, std::vector<scoped_refptr<ShellLinkItem>>>;
@@ -100,7 +101,7 @@
   // Delete shortcuts stored in the test override for a specific app. This
   // should only be run on Windows, Mac and Linux.
   bool SimulateDeleteShortcutsByUser(Profile* profile,
-                                     const AppId& app_id,
+                                     const webapps::AppId& app_id,
                                      const std::string& app_name);
 
 #if BUILDFLAG(IS_MAC)
@@ -124,7 +125,7 @@
   // login mode is enabled based on the location. This should only be run on
   // Windows, Mac and Linux.
   bool IsRunOnOsLoginEnabled(Profile* profile,
-                             const AppId& app_id,
+                             const webapps::AppId& app_id,
                              const std::string& app_name);
 
   // -------------------------------
@@ -132,7 +133,7 @@
   // -------------------------------
 
   bool IsFileExtensionHandled(Profile* profile,
-                              const AppId& app_id,
+                              const webapps::AppId& app_id,
                               std::string app_name,
                               std::string file_extension);
 
@@ -151,7 +152,7 @@
   absl::optional<SkColor> GetShortcutIconTopLeftColor(
       Profile* profile,
       base::FilePath shortcut_dir,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::string& app_name,
       SquareSizePx size_px = icon_size::k128);
 
@@ -159,14 +160,14 @@
   // app_name. This should only be run on Windows, Mac and Linux.
   base::FilePath GetShortcutPath(Profile* profile,
                                  base::FilePath shortcut_dir,
-                                 const AppId& app_id,
+                                 const webapps::AppId& app_id,
                                  const std::string& app_name);
 
   // Looks into the current shortcut paths to determine if a shortcut has
   // been created or not. This should only be run on Windows, Mac and Linux.
   // TODO(crbug.com/1425967): Add PList parsing logic for Mac shortcut checking.
   bool IsShortcutCreated(Profile* profile,
-                         const AppId& app_id,
+                         const webapps::AppId& app_id,
                          const std::string& app_name);
 
   // ---------------------------------
@@ -191,7 +192,7 @@
   // the uninstall menu, and false if it isn't. The unexpected value is a string
   // description of the error.
   base::expected<bool, std::string> IsUninstallRegisteredWithOs(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::string& app_name,
       Profile* profile);
 #endif  // BUILDFLAG(IS_WIN)
@@ -240,7 +241,7 @@
   // Creates a tuple of app_id to protocols and adds it to the vector
   // of registered protocols. There can be multiple entries for the same
   // app_id.
-  void RegisterProtocolSchemes(const AppId& app_id,
+  void RegisterProtocolSchemes(const webapps::AppId& app_id,
                                std::vector<std::string> protocols) override;
 
  private:
diff --git a/chrome/browser/web_applications/test/web_app_icon_test_utils.cc b/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
index b4cef4ff..6fea742d 100644
--- a/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
@@ -87,7 +87,8 @@
          abs_error_b <= threshold && abs_error_a <= threshold;
 }
 
-base::FilePath GetAppIconsAnyDir(Profile* profile, const AppId& app_id) {
+base::FilePath GetAppIconsAnyDir(Profile* profile,
+                                 const webapps::AppId& app_id) {
   base::FilePath web_apps_root_directory = GetWebAppsRootDirectory(profile);
   base::FilePath app_dir =
       GetManifestResourcesDirectoryForApp(web_apps_root_directory, app_id);
@@ -95,7 +96,8 @@
   return icons_dir;
 }
 
-base::FilePath GetAppIconsMaskableDir(Profile* profile, const AppId& app_id) {
+base::FilePath GetAppIconsMaskableDir(Profile* profile,
+                                      const webapps::AppId& app_id) {
   base::FilePath web_apps_root_directory = GetWebAppsRootDirectory(profile);
   base::FilePath app_dir =
       GetManifestResourcesDirectoryForApp(web_apps_root_directory, app_id);
@@ -103,7 +105,8 @@
   return icons_dir;
 }
 
-base::FilePath GetOtherIconsDir(Profile* profile, const AppId& app_id) {
+base::FilePath GetOtherIconsDir(Profile* profile,
+                                const webapps::AppId& app_id) {
   base::FilePath web_apps_root_directory = GetWebAppsRootDirectory(profile);
   base::FilePath app_dir =
       GetManifestResourcesDirectoryForApp(web_apps_root_directory, app_id);
@@ -245,7 +248,7 @@
 
 void IconManagerWriteGeneratedIcons(
     WebAppIconManager& icon_manager,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<GeneratedIconsInfo>& icons_info) {
   IconBitmaps icon_bitmaps;
 
@@ -271,7 +274,7 @@
 }
 
 SkColor IconManagerReadAppIconPixel(WebAppIconManager& icon_manager,
-                                    const AppId& app_id,
+                                    const webapps::AppId& app_id,
                                     SquareSizePx size_px,
                                     int x,
                                     int y) {
diff --git a/chrome/browser/web_applications/test/web_app_icon_test_utils.h b/chrome/browser/web_applications/test/web_app_icon_test_utils.h
index de983d3a..af4cfce 100644
--- a/chrome/browser/web_applications/test/web_app_icon_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_icon_test_utils.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -46,11 +47,13 @@
                     SkColor actual_color,
                     int threshold);
 
-base::FilePath GetAppIconsAnyDir(Profile* profile, const AppId& app_id);
+base::FilePath GetAppIconsAnyDir(Profile* profile,
+                                 const webapps::AppId& app_id);
 
-base::FilePath GetAppIconsMaskableDir(Profile* profile, const AppId& app_id);
+base::FilePath GetAppIconsMaskableDir(Profile* profile,
+                                      const webapps::AppId& app_id);
 
-base::FilePath GetOtherIconsDir(Profile* profile, const AppId& app_id);
+base::FilePath GetOtherIconsDir(Profile* profile, const webapps::AppId& app_id);
 
 // Performs blocking IO and decompression.
 bool ReadBitmap(FileUtilsWrapper* utils,
@@ -101,12 +104,12 @@
 
 void IconManagerWriteGeneratedIcons(
     WebAppIconManager& icon_manager,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<GeneratedIconsInfo>& icons_info);
 
 // Synchronous read of an app icon pixel.
 SkColor IconManagerReadAppIconPixel(WebAppIconManager& icon_manager,
-                                    const AppId& app_id,
+                                    const webapps::AppId& app_id,
                                     SquareSizePx size_px,
                                     int x = 0,
                                     int y = 0);
diff --git a/chrome/browser/web_applications/test/web_app_icon_waiter.cc b/chrome/browser/web_applications/test/web_app_icon_waiter.cc
index dbb4c22c..4d875a5 100644
--- a/chrome/browser/web_applications/test/web_app_icon_waiter.cc
+++ b/chrome/browser/web_applications/test/web_app_icon_waiter.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/web_applications/web_app_utils.h"
 
 WebAppIconWaiter::WebAppIconWaiter(Profile* profile,
-                                   const web_app::AppId& app_id)
+                                   const webapps::AppId& app_id)
     : app_id_(app_id) {
   web_app::WebAppProvider* web_app_provider =
       web_app::WebAppProvider::GetForTest(profile);
@@ -26,7 +26,7 @@
 void WebAppIconWaiter::Wait() {
   run_loop_.Run();
 }
-void WebAppIconWaiter::OnFaviconRead(const web_app::AppId& app_id) {
+void WebAppIconWaiter::OnFaviconRead(const webapps::AppId& app_id) {
   if (app_id == *app_id_) {
     run_loop_.Quit();
   }
diff --git a/chrome/browser/web_applications/test/web_app_icon_waiter.h b/chrome/browser/web_applications/test/web_app_icon_waiter.h
index f65a46c..fdb9d6ef 100644
--- a/chrome/browser/web_applications/test/web_app_icon_waiter.h
+++ b/chrome/browser/web_applications/test/web_app_icon_waiter.h
@@ -9,18 +9,19 @@
 #include "base/run_loop.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
 class WebAppIconWaiter {
  public:
-  explicit WebAppIconWaiter(Profile* profile, const web_app::AppId& app_id);
+  explicit WebAppIconWaiter(Profile* profile, const webapps::AppId& app_id);
 
   void Wait();
 
  private:
-  void OnFaviconRead(const web_app::AppId& app_id);
-  const raw_ref<const web_app::AppId> app_id_;
+  void OnFaviconRead(const webapps::AppId& app_id);
+  const raw_ref<const webapps::AppId> app_id_;
   base::RunLoop run_loop_;
 };
 
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.cc b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
index 5022c72..aa47286 100644
--- a/chrome/browser/web_applications/test/web_app_install_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
@@ -62,10 +62,11 @@
   WaitUntilWebAppProviderAndSubsystemsReady(provider);
 }
 
-AppId InstallDummyWebApp(Profile* profile,
-                         const std::string& app_name,
-                         const GURL& start_url,
-                         const webapps::WebappInstallSource install_source) {
+webapps::AppId InstallDummyWebApp(
+    Profile* profile,
+    const std::string& app_name,
+    const GURL& start_url,
+    const webapps::WebappInstallSource install_source) {
   auto web_app_info = std::make_unique<WebAppInstallInfo>();
 
   web_app_info->start_url = start_url;
@@ -80,15 +81,15 @@
                        install_source);
 }
 
-AppId InstallWebApp(Profile* profile,
-                    std::unique_ptr<WebAppInstallInfo> web_app_info,
-                    bool overwrite_existing_manifest_fields,
-                    webapps::WebappInstallSource install_source) {
+webapps::AppId InstallWebApp(Profile* profile,
+                             std::unique_ptr<WebAppInstallInfo> web_app_info,
+                             bool overwrite_existing_manifest_fields,
+                             webapps::WebappInstallSource install_source) {
   // The sync system requires that sync entity name is never empty.
   if (web_app_info->title.empty())
     web_app_info->title = u"WebAppInstallInfo App Name";
 
-  AppId app_id;
+  webapps::AppId app_id;
   base::RunLoop run_loop;
   auto* provider = WebAppProvider::GetForTest(profile);
   DCHECK(provider);
@@ -99,12 +100,12 @@
   provider->scheduler().InstallFromInfo(
       std::move(web_app_info), overwrite_existing_manifest_fields,
       install_source,
-      base::BindLambdaForTesting(
-          [&](const AppId& installed_app_id, webapps::InstallResultCode code) {
-            EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
-            app_id = installed_app_id;
-            run_loop.Quit();
-          }));
+      base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id,
+                                     webapps::InstallResultCode code) {
+        EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
+        app_id = installed_app_id;
+        run_loop.Quit();
+      }));
 
   run_loop.Run();
   // Allow updates to be published to App Service listeners.
@@ -112,7 +113,7 @@
   return app_id;
 }
 
-void UninstallWebApp(Profile* profile, const AppId& app_id) {
+void UninstallWebApp(Profile* profile, const webapps::AppId& app_id) {
   WebAppProvider* const provider = WebAppProvider::GetForTest(profile);
   base::test::TestFuture<webapps::UninstallResultCode> future;
   DCHECK(provider->registrar_unsafe().CanUserUninstallWebApp(app_id));
@@ -129,7 +130,8 @@
   auto* provider = WebAppProvider::GetForTest(profile);
   if (!provider)
     return false;
-  std::vector<AppId> app_ids = provider->registrar_unsafe().GetAppIds();
+  std::vector<webapps::AppId> app_ids =
+      provider->registrar_unsafe().GetAppIds();
   for (auto& app_id : app_ids) {
     const WebApp* app = provider->registrar_unsafe().GetAppById(app_id);
     WebAppManagementTypes sources = app->GetSources();
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.h b/chrome/browser/web_applications/test/web_app_install_test_utils.h
index 6f5452a..62d1f32 100644
--- a/chrome/browser/web_applications/test/web_app_install_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_install_test_utils.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/common/buildflags.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 #include "components/services/app_service/public/cpp/url_handler_info.h"
@@ -41,7 +42,7 @@
 // is complete.
 void WaitUntilWebAppProviderAndSubsystemsReady(WebAppProvider* provider);
 
-AppId InstallDummyWebApp(
+webapps::AppId InstallDummyWebApp(
     Profile* profile,
     const std::string& app_name,
     const GURL& app_url,
@@ -50,15 +51,16 @@
 
 // Synchronous version of WebAppInstallManager::InstallWebAppFromInfo. May be
 // used in unit tests and browser tests.
-AppId InstallWebApp(Profile* profile,
-                    std::unique_ptr<WebAppInstallInfo> web_app_info,
-                    bool overwrite_existing_manifest_fields = false,
-                    webapps::WebappInstallSource install_source =
-                        webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
+webapps::AppId InstallWebApp(
+    Profile* profile,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
+    bool overwrite_existing_manifest_fields = false,
+    webapps::WebappInstallSource install_source =
+        webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
 
 // Synchronously uninstall a web app. May be used in unit tests and browser
 // tests.
-void UninstallWebApp(Profile* profile, const AppId& app_id);
+void UninstallWebApp(Profile* profile, const webapps::AppId& app_id);
 
 // Synchronously uninstall all web apps for the given profile. May be used in
 // unit tests and browser tests. Returns `false` if there was a failure.
diff --git a/chrome/browser/web_applications/test/web_app_sync_test_utils.cc b/chrome/browser/web_applications/test/web_app_sync_test_utils.cc
index 34aa0a3..bdd16244 100644
--- a/chrome/browser/web_applications/test/web_app_sync_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_sync_test_utils.cc
@@ -58,12 +58,12 @@
 }
 
 void DeleteApps(WebAppSyncBridge& sync_bridge,
-                const std::vector<AppId>& app_ids_to_delete) {
+                const std::vector<webapps::AppId>& app_ids_to_delete) {
   std::unique_ptr<syncer::MetadataChangeList> metadata_change_list =
       sync_bridge.CreateMetadataChangeList();
   syncer::EntityChangeList entity_changes;
 
-  for (const AppId& app_id : app_ids_to_delete) {
+  for (const webapps::AppId& app_id : app_ids_to_delete) {
     auto entity_change = syncer::EntityChange::CreateDelete(app_id);
     entity_changes.push_back(std::move(entity_change));
   }
diff --git a/chrome/browser/web_applications/test/web_app_sync_test_utils.h b/chrome/browser/web_applications/test/web_app_sync_test_utils.h
index 184cf6b..5a66b6b 100644
--- a/chrome/browser/web_applications/test/web_app_sync_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_sync_test_utils.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -24,7 +25,7 @@
                 const std::vector<std::unique_ptr<WebApp>>& apps_server_state);
 
 void DeleteApps(WebAppSyncBridge& sync_bridge,
-                const std::vector<AppId>& app_ids_to_delete);
+                const std::vector<webapps::AppId>& app_ids_to_delete);
 
 }  // namespace sync_bridge_test_utils
 
diff --git a/chrome/browser/web_applications/test/web_app_test_observers.cc b/chrome/browser/web_applications/test/web_app_test_observers.cc
index 76508b9a..7d6052ce 100644
--- a/chrome/browser/web_applications/test/web_app_test_observers.cc
+++ b/chrome/browser/web_applications/test/web_app_test_observers.cc
@@ -16,8 +16,8 @@
 namespace {
 
 #if DCHECK_IS_ON()
-bool IsAnyIdEmpty(const std::set<AppId>& app_ids) {
-  for (const AppId& id : app_ids) {
+bool IsAnyIdEmpty(const std::set<webapps::AppId>& app_ids) {
+  for (const webapps::AppId& id : app_ids) {
     if (id.empty())
       return true;
   }
@@ -71,31 +71,31 @@
 }
 
 void WebAppInstallManagerObserverAdapter::OnWebAppInstalled(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (app_installed_delegate_)
     app_installed_delegate_.Run(app_id);
 }
 
 void WebAppInstallManagerObserverAdapter::OnWebAppInstalledWithOsHooks(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (app_installed_with_os_hooks_delegate_)
     app_installed_with_os_hooks_delegate_.Run(app_id);
 }
 
 void WebAppInstallManagerObserverAdapter::OnWebAppManifestUpdated(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (app_manifest_updated_delegate_)
     app_manifest_updated_delegate_.Run(app_id);
 }
 
 void WebAppInstallManagerObserverAdapter::OnWebAppWillBeUninstalled(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (app_will_be_uninstalled_delegate_)
     app_will_be_uninstalled_delegate_.Run(app_id);
 }
 
 void WebAppInstallManagerObserverAdapter::OnWebAppUninstalled(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   if (app_uninstalled_delegate_)
     app_uninstalled_delegate_.Run(app_id);
@@ -106,14 +106,14 @@
 }
 
 void WebAppInstallManagerObserverAdapter::OnWebAppSourceRemoved(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (app_source_removed_delegate_) {
     app_source_removed_delegate_.Run(app_id);
   }
 }
 
 void WebAppInstallManagerObserverAdapter::SignalRunLoopAndStoreAppId(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (!is_listening_)
     return;
   optional_app_ids_.erase(app_id);
@@ -166,13 +166,13 @@
 }
 
 void WebAppTestRegistryObserverAdapter::OnWebAppProfileWillBeDeleted(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (app_profile_will_be_deleted_delegate_)
     app_profile_will_be_deleted_delegate_.Run(app_id);
 }
 
 void WebAppTestRegistryObserverAdapter::OnWebAppLastBadgingTimeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::Time& time) {
   if (app_last_badging_time_changed_delegate_)
     app_last_badging_time_changed_delegate_.Run(app_id, time);
@@ -188,7 +188,7 @@
 }
 
 void WebAppTestRegistryObserverAdapter::SignalRunLoopAndStoreAppId(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   if (!is_listening_)
     return;
   optional_app_ids_.erase(app_id);
@@ -205,7 +205,7 @@
 WebAppTestInstallObserver::~WebAppTestInstallObserver() = default;
 
 void WebAppTestInstallObserver::BeginListening(
-    const std::set<AppId>& optional_app_ids) {
+    const std::set<webapps::AppId>& optional_app_ids) {
   optional_app_ids_ = optional_app_ids;
 #if DCHECK_IS_ON()
   DCHECK(!IsAnyIdEmpty(optional_app_ids_)) << "Cannot listen for empty ids.";
@@ -216,15 +216,15 @@
       weak_factory_.GetWeakPtr());
 }
 
-AppId WebAppTestInstallObserver::Wait() {
+webapps::AppId WebAppTestInstallObserver::Wait() {
   wait_loop_.Run();
   return last_app_id_;
 }
 
-AppId WebAppTestInstallObserver::BeginListeningAndWait(
-    const std::set<AppId>& optional_app_ids) {
+webapps::AppId WebAppTestInstallObserver::BeginListeningAndWait(
+    const std::set<webapps::AppId>& optional_app_ids) {
   BeginListening(optional_app_ids);
-  AppId id = Wait();
+  webapps::AppId id = Wait();
   return id;
 }
 
@@ -235,7 +235,7 @@
     default;
 
 void WebAppTestInstallWithOsHooksObserver::BeginListening(
-    const std::set<AppId>& optional_app_ids) {
+    const std::set<webapps::AppId>& optional_app_ids) {
   optional_app_ids_ = optional_app_ids;
 #if DCHECK_IS_ON()
   DCHECK(!IsAnyIdEmpty(optional_app_ids_)) << "Cannot listen for empty ids.";
@@ -246,15 +246,15 @@
       weak_factory_.GetWeakPtr());
 }
 
-AppId WebAppTestInstallWithOsHooksObserver::Wait() {
+webapps::AppId WebAppTestInstallWithOsHooksObserver::Wait() {
   wait_loop_.Run();
   return last_app_id_;
 }
 
-AppId WebAppTestInstallWithOsHooksObserver::BeginListeningAndWait(
-    const std::set<AppId>& optional_app_ids) {
+webapps::AppId WebAppTestInstallWithOsHooksObserver::BeginListeningAndWait(
+    const std::set<webapps::AppId>& optional_app_ids) {
   BeginListening(optional_app_ids);
-  AppId id = Wait();
+  webapps::AppId id = Wait();
   return id;
 }
 
@@ -265,7 +265,7 @@
     default;
 
 void WebAppTestManifestUpdatedObserver::BeginListening(
-    const std::set<AppId>& optional_app_ids) {
+    const std::set<webapps::AppId>& optional_app_ids) {
   optional_app_ids_ = optional_app_ids;
 #if DCHECK_IS_ON()
   DCHECK(!IsAnyIdEmpty(optional_app_ids_)) << "Cannot listen for empty ids.";
@@ -276,15 +276,15 @@
       weak_factory_.GetWeakPtr());
 }
 
-AppId WebAppTestManifestUpdatedObserver::Wait() {
+webapps::AppId WebAppTestManifestUpdatedObserver::Wait() {
   wait_loop_.Run();
   return last_app_id_;
 }
 
-AppId WebAppTestManifestUpdatedObserver::BeginListeningAndWait(
-    const std::set<AppId>& optional_app_ids) {
+webapps::AppId WebAppTestManifestUpdatedObserver::BeginListeningAndWait(
+    const std::set<webapps::AppId>& optional_app_ids) {
   BeginListening(optional_app_ids);
-  AppId id = Wait();
+  webapps::AppId id = Wait();
   return id;
 }
 
@@ -294,7 +294,7 @@
 WebAppTestUninstallObserver::~WebAppTestUninstallObserver() = default;
 
 void WebAppTestUninstallObserver::BeginListening(
-    const std::set<AppId>& optional_app_ids) {
+    const std::set<webapps::AppId>& optional_app_ids) {
   optional_app_ids_ = optional_app_ids;
 #if DCHECK_IS_ON()
   DCHECK(!IsAnyIdEmpty(optional_app_ids_)) << "Cannot listen for empty ids.";
@@ -305,15 +305,15 @@
       weak_factory_.GetWeakPtr());
 }
 
-AppId WebAppTestUninstallObserver::Wait() {
+webapps::AppId WebAppTestUninstallObserver::Wait() {
   wait_loop_.Run();
   return last_app_id_;
 }
 
-AppId WebAppTestUninstallObserver::BeginListeningAndWait(
-    const std::set<AppId>& optional_app_ids) {
+webapps::AppId WebAppTestUninstallObserver::BeginListeningAndWait(
+    const std::set<webapps::AppId>& optional_app_ids) {
   BeginListening(optional_app_ids);
-  AppId id = Wait();
+  webapps::AppId id = Wait();
   return id;
 }
 
diff --git a/chrome/browser/web_applications/test/web_app_test_observers.h b/chrome/browser/web_applications/test/web_app_test_observers.h
index fe4dd1c..4ac3984 100644
--- a/chrome/browser/web_applications/test/web_app_test_observers.h
+++ b/chrome/browser/web_applications/test/web_app_test_observers.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registrar_observer.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -31,51 +32,51 @@
   ~WebAppInstallManagerObserverAdapter() override;
 
   using WebAppInstalledDelegate =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   void SetWebAppInstalledDelegate(WebAppInstalledDelegate delegate);
 
   using WebAppInstalledWithOsHooksDelegate =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   void SetWebAppInstalledWithOsHooksDelegate(
       WebAppInstalledWithOsHooksDelegate delegate);
 
   using WebAppWillBeUninstalledDelegate =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   void SetWebAppWillBeUninstalledDelegate(
       WebAppWillBeUninstalledDelegate delegate);
 
   using WebAppUninstalledDelegate =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   void SetWebAppUninstalledDelegate(WebAppUninstalledDelegate delegate);
 
   using WebAppManifestUpdateDelegate =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   void SetWebAppManifestUpdateDelegate(WebAppManifestUpdateDelegate delegate);
 
   using WebAppSourceRemovedDelegate =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   void SetWebAppSourceRemovedDelegate(WebAppSourceRemovedDelegate delegate);
 
-  void OnWebAppInstalled(const AppId& app_id) override;
-  void OnWebAppInstalledWithOsHooks(const AppId& app_id) override;
-  void OnWebAppManifestUpdated(const AppId& app_id) override;
-  void OnWebAppWillBeUninstalled(const AppId& app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& app_id) override;
+  void OnWebAppInstalledWithOsHooks(const webapps::AppId& app_id) override;
+  void OnWebAppManifestUpdated(const webapps::AppId& app_id) override;
+  void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) override;
   void OnWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
   void OnWebAppInstallManagerDestroyed() override;
-  void OnWebAppSourceRemoved(const AppId& app_id) override;
+  void OnWebAppSourceRemoved(const webapps::AppId& app_id) override;
 
  protected:
   // Helper method for subclasses to allow easy waiting on `wait_loop_`.
   // Expects that the users set `is_listening_` to `true` and
   // optionally set `optional_app_ids_`.
-  void SignalRunLoopAndStoreAppId(const AppId& app_id);
+  void SignalRunLoopAndStoreAppId(const webapps::AppId& app_id);
 
   bool is_listening_ = false;
-  std::set<AppId> optional_app_ids_;
+  std::set<webapps::AppId> optional_app_ids_;
   base::RunLoop wait_loop_;
-  AppId last_app_id_;
+  webapps::AppId last_app_id_;
 
   WebAppInstalledDelegate app_installed_delegate_;
   WebAppInstalledWithOsHooksDelegate app_installed_with_os_hooks_delegate_;
@@ -109,7 +110,7 @@
   ~WebAppTestRegistryObserverAdapter() override;
 
   using WebAppProfileWillBeDeletedDelegate =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   void SetWebAppProfileWillBeDeletedDelegate(
       WebAppProfileWillBeDeletedDelegate delegate);
 
@@ -119,11 +120,11 @@
       WebAppWillBeUpdatedFromSyncDelegate delegate);
 
   using WebAppManifestUpdateDelegate =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   void SetWebAppManifestUpdateDelegate(WebAppManifestUpdateDelegate delegate);
 
   using WebAppLastBadgingTimeChangedDelegate =
-      base::RepeatingCallback<void(const AppId& app_id,
+      base::RepeatingCallback<void(const webapps::AppId& app_id,
                                    const base::Time& time)>;
   void SetWebAppLastBadgingTimeChangedDelegate(
       WebAppLastBadgingTimeChangedDelegate delegate);
@@ -135,8 +136,8 @@
   // WebAppRegistrarObserver:
   void OnWebAppsWillBeUpdatedFromSync(
       const std::vector<const WebApp*>& new_apps_state) override;
-  void OnWebAppProfileWillBeDeleted(const AppId& app_id) override;
-  void OnWebAppLastBadgingTimeChanged(const AppId& app_id,
+  void OnWebAppProfileWillBeDeleted(const webapps::AppId& app_id) override;
+  void OnWebAppLastBadgingTimeChanged(const webapps::AppId& app_id,
                                       const base::Time& time) override;
   void OnWebAppProtocolSettingsChanged() override;
   void OnAppRegistrarDestroyed() override;
@@ -145,12 +146,12 @@
   // Helper method for subclasses to allow easy waiting on `wait_loop_`.
   // Expects that the users set `is_listening_` to `true` and
   // optionally set `optional_app_ids_`.
-  void SignalRunLoopAndStoreAppId(const AppId& app_id);
+  void SignalRunLoopAndStoreAppId(const webapps::AppId& app_id);
 
   bool is_listening_ = false;
-  std::set<AppId> optional_app_ids_;
+  std::set<webapps::AppId> optional_app_ids_;
   base::RunLoop wait_loop_;
-  AppId last_app_id_;
+  webapps::AppId last_app_id_;
 
  private:
   WebAppWillBeUpdatedFromSyncDelegate app_will_be_updated_from_sync_delegate_;
@@ -175,13 +176,14 @@
   // |optional_app_ids|. Settings these means that the
   // WebAppInstalledDelegate doesn't get called until all of the ids in
   // |optional_app_ids| are installed.
-  void BeginListening(const std::set<AppId>& optional_app_ids = {});
+  void BeginListening(const std::set<webapps::AppId>& optional_app_ids = {});
 
   // Wait for the next observation (or, until all optional_app_ids are
   // observed).
-  AppId Wait();
+  webapps::AppId Wait();
 
-  AppId BeginListeningAndWait(const std::set<AppId>& optional_app_ids = {});
+  webapps::AppId BeginListeningAndWait(
+      const std::set<webapps::AppId>& optional_app_ids = {});
 };
 
 class WebAppTestInstallWithOsHooksObserver final
@@ -194,13 +196,14 @@
   // |optional_app_ids|. Settings these means that the
   // WebAppInstalledWithOsHooksDelegate doesn't get called until all of the ids
   // in |optional_app_ids| are installed.
-  void BeginListening(const std::set<AppId>& optional_app_ids = {});
+  void BeginListening(const std::set<webapps::AppId>& optional_app_ids = {});
 
   // Wait for the next observation (or, until all optional_app_ids are
   // observed).
-  AppId Wait();
+  webapps::AppId Wait();
 
-  AppId BeginListeningAndWait(const std::set<AppId>& app_ids = {});
+  webapps::AppId BeginListeningAndWait(
+      const std::set<webapps::AppId>& app_ids = {});
 };
 
 class WebAppTestManifestUpdatedObserver final
@@ -214,13 +217,14 @@
   // |optional_app_ids|. Settings these means that the
   // WebAppManifestUpdateDelegate doesn't get called until all of the ids in
   // |optional_app_ids| are installed.
-  void BeginListening(const std::set<AppId>& optional_app_ids = {});
+  void BeginListening(const std::set<webapps::AppId>& optional_app_ids = {});
 
   // Wait for the next observation (or, until all optional_app_ids are
   // observed).
-  AppId Wait();
+  webapps::AppId Wait();
 
-  AppId BeginListeningAndWait(const std::set<AppId>& app_ids = {});
+  webapps::AppId BeginListeningAndWait(
+      const std::set<webapps::AppId>& app_ids = {});
 };
 
 class WebAppTestUninstallObserver final
@@ -233,11 +237,12 @@
   // |optional_app_ids|. Settings these means that the
   // WebAppUninstalledDelegate doesn't get called until all of the ids in
   // |optional_app_ids| are installed.
-  void BeginListening(const std::set<AppId>& optional_app_ids = {});
+  void BeginListening(const std::set<webapps::AppId>& optional_app_ids = {});
 
-  AppId Wait();
+  webapps::AppId Wait();
 
-  AppId BeginListeningAndWait(const std::set<AppId>& app_ids = {});
+  webapps::AppId BeginListeningAndWait(
+      const std::set<webapps::AppId>& app_ids = {});
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.cc b/chrome/browser/web_applications/test/web_app_test_utils.cc
index c248e281..e4c7e30 100644
--- a/chrome/browser/web_applications/test/web_app_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_test_utils.cc
@@ -535,7 +535,8 @@
 
 std::unique_ptr<WebApp> CreateWebApp(const GURL& start_url,
                                      WebAppManagement::Type source_type) {
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  const webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
 
   auto web_app = std::make_unique<WebApp>(app_id);
   web_app->SetStartUrl(start_url);
@@ -564,7 +565,7 @@
   }
   const GURL scope = params.base_url.Resolve("scope" + seed_str + "/");
   const GURL start_url = scope.Resolve("start" + seed_str);
-  const AppId app_id = GenerateAppId(relative_manifest_id, start_url);
+  const webapps::AppId app_id = GenerateAppId(relative_manifest_id, start_url);
 
   const std::string name = "Name" + seed_str;
   const std::string description = "Description" + seed_str;
@@ -955,14 +956,14 @@
                                 false /*accept*/, std::move(web_app_info)));
 }
 
-AppId InstallPwaForCurrentUrl(Browser* browser) {
+webapps::AppId InstallPwaForCurrentUrl(Browser* browser) {
   // Depending on the installability criteria, different dialogs can be used.
   chrome::SetAutoAcceptWebAppDialogForTesting(true, true);
   chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true);
   WebAppTestInstallWithOsHooksObserver observer(browser->profile());
   observer.BeginListening();
   CHECK(chrome::ExecuteCommand(browser, IDC_INSTALL_PWA));
-  AppId app_id = observer.Wait();
+  webapps::AppId app_id = observer.Wait();
   chrome::SetAutoAcceptPWAInstallConfirmationForTesting(false);
   chrome::SetAutoAcceptWebAppDialogForTesting(false, false);
   return app_id;
@@ -994,7 +995,7 @@
 
 void AddInstallUrlData(PrefService* pref_service,
                        WebAppSyncBridge* sync_bridge,
-                       const AppId& app_id,
+                       const webapps::AppId& app_id,
                        const GURL& url,
                        const ExternalInstallSource& source) {
   ScopedRegistryUpdate update = sync_bridge->BeginUpdate();
@@ -1008,7 +1009,7 @@
 
 void AddInstallUrlAndPlaceholderData(PrefService* pref_service,
                                      WebAppSyncBridge* sync_bridge,
-                                     const AppId& app_id,
+                                     const webapps::AppId& app_id,
                                      const GURL& url,
                                      const ExternalInstallSource& source,
                                      bool is_placeholder) {
@@ -1022,7 +1023,7 @@
 }
 
 void SynchronizeOsIntegration(Profile* profile,
-                              const AppId& app_id,
+                              const webapps::AppId& app_id,
                               absl::optional<SynchronizeOsOptions> options) {
   base::test::TestFuture<void> sync_future;
   WebAppProvider::GetForTest(profile)->scheduler().SynchronizeOsIntegration(
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.h b/chrome/browser/web_applications/test/web_app_test_utils.h
index c4f2847..1cc6a7a 100644
--- a/chrome/browser/web_applications/test/web_app_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_test_utils.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_install_params.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "components/prefs/pref_service.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/service_worker_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -73,7 +74,7 @@
     std::unique_ptr<WebAppInstallInfo> web_app_info,
     WebAppInstallationAcceptanceCallback acceptance_callback);
 
-AppId InstallPwaForCurrentUrl(Browser* browser);
+webapps::AppId InstallPwaForCurrentUrl(Browser* browser);
 
 void CheckServiceWorkerStatus(const GURL& url,
                               content::StoragePartition* storage_partition,
@@ -83,20 +84,20 @@
 
 void AddInstallUrlData(PrefService* pref_service,
                        WebAppSyncBridge* sync_bridge,
-                       const AppId& app_id,
+                       const webapps::AppId& app_id,
                        const GURL& url,
                        const ExternalInstallSource& source);
 
 void AddInstallUrlAndPlaceholderData(PrefService* pref_service,
                                      WebAppSyncBridge* sync_bridge,
-                                     const AppId& app_id,
+                                     const webapps::AppId& app_id,
                                      const GURL& url,
                                      const ExternalInstallSource& source,
                                      bool is_placeholder);
 
 void SynchronizeOsIntegration(
     Profile* profile,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     absl::optional<SynchronizeOsOptions> options = absl::nullopt);
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.cc b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.cc
index a7283cb..6fa6845 100644
--- a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.cc
+++ b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.cc
@@ -33,7 +33,7 @@
 }
 
 void UserUninstalledPreinstalledWebAppPrefs::Add(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::flat_set<GURL> install_urls) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   base::Value::List url_list;
@@ -53,7 +53,7 @@
   update->Set(app_id, std::move(url_list));
 }
 
-absl::optional<AppId>
+absl::optional<webapps::AppId>
 UserUninstalledPreinstalledWebAppPrefs::LookUpAppIdByInstallUrl(
     const GURL& url) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -78,7 +78,7 @@
 }
 
 bool UserUninstalledPreinstalledWebAppPrefs::DoesAppIdExist(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const base::Value::Dict& ids_to_urls =
       pref_service_->GetDict(prefs::kUserUninstalledPreinstalledWebAppPref);
@@ -87,7 +87,7 @@
 }
 
 void UserUninstalledPreinstalledWebAppPrefs::AppendExistingInstallUrlsPerAppId(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::flat_set<GURL>& urls) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const base::Value::Dict& ids_to_urls =
@@ -117,7 +117,7 @@
 }
 
 bool UserUninstalledPreinstalledWebAppPrefs::RemoveByInstallUrl(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& install_url) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const base::Value::Dict& ids_to_urls =
@@ -156,7 +156,7 @@
 }
 
 bool UserUninstalledPreinstalledWebAppPrefs::RemoveByAppId(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const base::Value::Dict& ids_to_urls =
       pref_service_->GetDict(prefs::kUserUninstalledPreinstalledWebAppPref);
@@ -170,7 +170,7 @@
 }
 
 bool UserUninstalledPreinstalledWebAppPrefs::AppIdContainsAllUrls(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::flat_map<WebAppManagement::Type,
                          WebApp::ExternalManagementConfig>& url_map,
     const bool only_default) {
diff --git a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h
index 1324fac..eed14ad 100644
--- a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h
+++ b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h
@@ -14,6 +14,7 @@
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
+#include "components/webapps/common/web_app_id.h"
 #include "url/gurl.h"
 
 class GURL;
@@ -36,7 +37,7 @@
 // thereby maintaining its synchronization.
 //
 // The prefs are stored in prefs::kUserUninstalledPreinstalledWebAppPref and
-// they are stored as map<AppId, Set<Install URLs>>, e.g.
+// they are stored as map<webapps::AppId, Set<Install URLs>>, e.g.
 // {"app_id": {"https://install_url1.com", "https://install_url2.com"}}
 //
 // They can be seen on chrome://web-app-internals under the
@@ -51,16 +52,18 @@
       const UserUninstalledPreinstalledWebAppPrefs&) = delete;
 
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-  void Add(const AppId& app_id, base::flat_set<GURL> install_urls);
-  absl::optional<AppId> LookUpAppIdByInstallUrl(const GURL& install_url);
-  bool DoesAppIdExist(const AppId& app_id);
-  void AppendExistingInstallUrlsPerAppId(const AppId& app_id,
+  void Add(const webapps::AppId& app_id, base::flat_set<GURL> install_urls);
+  absl::optional<webapps::AppId> LookUpAppIdByInstallUrl(
+      const GURL& install_url);
+  bool DoesAppIdExist(const webapps::AppId& app_id);
+  void AppendExistingInstallUrlsPerAppId(const webapps::AppId& app_id,
                                          base::flat_set<GURL>& urls);
   int Size();
-  bool RemoveByInstallUrl(const AppId& app_id, const GURL& install_url);
-  bool RemoveByAppId(const AppId& app_id);
+  bool RemoveByInstallUrl(const webapps::AppId& app_id,
+                          const GURL& install_url);
+  bool RemoveByAppId(const webapps::AppId& app_id);
   bool AppIdContainsAllUrls(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const base::flat_map<WebAppManagement::Type,
                            WebApp::ExternalManagementConfig>& url_map,
       const bool only_default);
diff --git a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs_browsertest.cc b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs_browsertest.cc
index 453cca2..fc7f861b 100644
--- a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs_browsertest.cc
+++ b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs_browsertest.cc
@@ -15,9 +15,9 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "url/gurl.h"
 
@@ -45,8 +45,8 @@
   GURL url1("https://foo.com");
   GURL url2("https://bar1.com");
   GURL url3("https://bar2.com");
-  AppId app_id1 = "foo";
-  AppId app_id2 = "bar";
+  webapps::AppId app_id1 = "foo";
+  webapps::AppId app_id2 = "bar";
   UserUninstalledPreinstalledWebAppPrefs preinstalled_prefs(
       profile()->GetPrefs());
 
@@ -87,9 +87,9 @@
   GURL url1("https://foo.com");
   GURL url2("https://bar1.com");
   GURL url3("https://bar2.com");
-  AppId app_id1 = "foo";
-  AppId app_id2 = "bar";
-  AppId app_id3 = "baz";
+  webapps::AppId app_id1 = "foo";
+  webapps::AppId app_id2 = "bar";
+  webapps::AppId app_id3 = "baz";
 
   UserUninstalledPreinstalledWebAppPrefs preinstalled_prefs(
       profile()->GetPrefs());
@@ -126,11 +126,11 @@
   app_info2->start_url = GURL("https://example_url2.com/");
   app_info2->title = u"Example App2";
   app_info2->install_url = GURL("https://example_url2.com/install");
-  AppId app_id1 =
+  webapps::AppId app_id1 =
       test::InstallWebApp(profile(), std::move(app_info1),
                           /*overwrite_existing_manifest_fields=*/false,
                           webapps::WebappInstallSource::EXTERNAL_DEFAULT);
-  AppId app_id2 =
+  webapps::AppId app_id2 =
       test::InstallWebApp(profile(), std::move(app_info2),
                           /*overwrite_existing_manifest_fields=*/false,
                           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index 698f80121..046f488 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -302,7 +302,7 @@
 
 }  // namespace
 
-WebApp::WebApp(const AppId& app_id)
+WebApp::WebApp(const webapps::AppId& app_id)
     : app_id_(app_id),
       chromeos_data_(IsChromeOsDataMandatory()
                          ? absl::make_optional<WebAppChromeOsData>()
@@ -325,7 +325,7 @@
   }
 }
 
-ManifestId WebApp::manifest_id() const {
+webapps::ManifestId WebApp::manifest_id() const {
   // Almost all production use-cases should have the manifest_id set, but in
   // some test it is not. If the manifest id is not set, then fall back to the
   // start_url, as per the algorithm in
@@ -625,7 +625,7 @@
   manifest_url_ = manifest_url;
 }
 
-void WebApp::SetManifestId(const ManifestId& manifest_id) {
+void WebApp::SetManifestId(const webapps::ManifestId& manifest_id) {
   CHECK(manifest_id.is_valid());
   CHECK(start_url_.is_empty() ||
         url::Origin::Create(start_url_)
@@ -642,7 +642,8 @@
   launch_handler_ = std::move(launch_handler);
 }
 
-void WebApp::SetParentAppId(const absl::optional<AppId>& parent_app_id) {
+void WebApp::SetParentAppId(
+    const absl::optional<webapps::AppId>& parent_app_id) {
   parent_app_id_ = parent_app_id;
 }
 
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index fd2652d..4cc1f609 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -31,6 +31,7 @@
 #include "components/services/app_service/public/cpp/share_target.h"
 #include "components/services/app_service/public/cpp/url_handler_info.h"
 #include "components/sync/model/string_ordinal.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
 #include "third_party/blink/public/common/permissions_policy/permissions_policy_declaration.h"
@@ -51,7 +52,7 @@
 
 class WebApp {
  public:
-  explicit WebApp(const AppId& app_id);
+  explicit WebApp(const webapps::AppId& app_id);
   ~WebApp();
 
   // Copyable and move-assignable to support Copy-on-Write with Commit.
@@ -62,7 +63,7 @@
   WebApp(WebApp&&) = delete;
   WebApp& operator=(const WebApp&) = delete;
 
-  const AppId& app_id() const { return app_id_; }
+  const webapps::AppId& app_id() const { return app_id_; }
 
   // UTF8 encoded application name. This name is not translated, use
   // WebAppRegistrar.GetAppShortName to get the translated name.
@@ -265,13 +266,15 @@
 
   const GURL& manifest_url() const { return manifest_url_; }
 
-  ManifestId manifest_id() const;
+  webapps::ManifestId manifest_id() const;
 
   const absl::optional<LaunchHandler>& launch_handler() const {
     return launch_handler_;
   }
 
-  const absl::optional<AppId>& parent_app_id() const { return parent_app_id_; }
+  const absl::optional<webapps::AppId>& parent_app_id() const {
+    return parent_app_id_;
+  }
 
   const blink::ParsedPermissionsPolicy& permissions_policy() const {
     return permissions_policy_;
@@ -487,10 +490,10 @@
   void SetSyncFallbackData(SyncFallbackData sync_fallback_data);
   void SetCaptureLinks(blink::mojom::CaptureLinks capture_links);
   void SetManifestUrl(const GURL& manifest_url);
-  void SetManifestId(const ManifestId& manifest_id);
+  void SetManifestId(const webapps::ManifestId& manifest_id);
   void SetWindowControlsOverlayEnabled(bool enabled);
   void SetLaunchHandler(absl::optional<LaunchHandler> launch_handler);
-  void SetParentAppId(const absl::optional<AppId>& parent_app_id);
+  void SetParentAppId(const absl::optional<webapps::AppId>& parent_app_id);
   void SetPermissionsPolicy(blink::ParsedPermissionsPolicy permissions_policy);
   void SetLatestInstallSource(
       absl::optional<webapps::WebappInstallSource> latest_install_source);
@@ -547,7 +550,7 @@
   friend class WebAppDatabase;
   friend std::ostream& operator<<(std::ostream&, const WebApp&);
 
-  AppId app_id_;
+  webapps::AppId app_id_;
 
   // This set always contains at least one source.
   WebAppManagementTypes sources_{};
@@ -608,7 +611,7 @@
       blink::mojom::CaptureLinks::kUndefined;
   ClientData client_data_;
   GURL manifest_url_;
-  ManifestId manifest_id_;
+  webapps::ManifestId manifest_id_;
   // The state of the user's approval of the app's use of the File Handler API.
   ApiApprovalState file_handler_approval_state_ =
       ApiApprovalState::kRequiresPrompt;
@@ -619,7 +622,7 @@
       OsIntegrationState::kDisabled;
   bool window_controls_overlay_enabled_ = false;
   absl::optional<LaunchHandler> launch_handler_;
-  absl::optional<AppId> parent_app_id_;
+  absl::optional<webapps::AppId> parent_app_id_;
   blink::ParsedPermissionsPolicy permissions_policy_;
   // The source of the latest install. WebAppRegistrar provides range
   // validation. Optional only to support legacy installations, since this used
diff --git a/chrome/browser/web_applications/web_app_audio_focus_browsertest.cc b/chrome/browser/web_applications/web_app_audio_focus_browsertest.cc
index a8496d6af..8c39b51d 100644
--- a/chrome/browser/web_applications/web_app_audio_focus_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_audio_focus_browsertest.cc
@@ -82,7 +82,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL app_url = embedded_test_server()->GetURL(kAudioFocusTestPageURL);
 
-  AppId app_id = InstallPWA(app_url);
+  webapps::AppId app_id = InstallPWA(app_url);
 
   // Launch browser with media page.
   content::WebContents* tab1 = AddTestPageTabAtIndex(0);
@@ -166,7 +166,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL app_url = embedded_test_server()->GetURL(kAudioFocusTestPageURL);
 
-  AppId app_id = InstallPWA(app_url);
+  webapps::AppId app_id = InstallPWA(app_url);
 
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), app_url));
   content::WebContents* web_contents =
diff --git a/chrome/browser/web_applications/web_app_audio_focus_id_map.cc b/chrome/browser/web_applications/web_app_audio_focus_id_map.cc
index 833b636..08079cf5 100644
--- a/chrome/browser/web_applications/web_app_audio_focus_id_map.cc
+++ b/chrome/browser/web_applications/web_app_audio_focus_id_map.cc
@@ -13,7 +13,7 @@
 WebAppAudioFocusIdMap::~WebAppAudioFocusIdMap() = default;
 
 const base::UnguessableToken& WebAppAudioFocusIdMap::CreateOrGetIdForApp(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   auto it = ids_.find(app_id);
 
   if (it == ids_.end())
diff --git a/chrome/browser/web_applications/web_app_audio_focus_id_map.h b/chrome/browser/web_applications/web_app_audio_focus_id_map.h
index a3260a7..ae778621 100644
--- a/chrome/browser/web_applications/web_app_audio_focus_id_map.h
+++ b/chrome/browser/web_applications/web_app_audio_focus_id_map.h
@@ -8,6 +8,7 @@
 #include <map>
 
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace base {
 class UnguessableToken;
@@ -28,10 +29,11 @@
  protected:
   friend class WebAppTabHelper;
 
-  const base::UnguessableToken& CreateOrGetIdForApp(const AppId& app_id);
+  const base::UnguessableToken& CreateOrGetIdForApp(
+      const webapps::AppId& app_id);
 
  private:
-  std::map<AppId, base::UnguessableToken> ids_;
+  std::map<webapps::AppId, base::UnguessableToken> ids_;
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_command_manager.h b/chrome/browser/web_applications/web_app_command_manager.h
index 116b930..4752506 100644
--- a/chrome/browser/web_applications/web_app_command_manager.h
+++ b/chrome/browser/web_applications/web_app_command_manager.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/locks/web_app_lock_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
diff --git a/chrome/browser/web_applications/web_app_command_manager_unittest.cc b/chrome/browser/web_applications/web_app_command_manager_unittest.cc
index d85e52bb..1b95e47e 100644
--- a/chrome/browser/web_applications/web_app_command_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_command_manager_unittest.cc
@@ -445,10 +445,11 @@
         loop.Quit();
       }));
   for (auto* app_id : {kTestAppId, kTestAppId2}) {
-    base::OnceCallback<void(AppLock&)> callback = base::BindOnce(
-        [](AppId app_id, base::RepeatingCallback<void(std::string)> barrier,
-           AppLock&) { barrier.Run(app_id); },
-        app_id, barrier);
+    base::OnceCallback<void(AppLock&)> callback =
+        base::BindOnce([](webapps::AppId app_id,
+                          base::RepeatingCallback<void(std::string)> barrier,
+                          AppLock&) { barrier.Run(app_id); },
+                       app_id, barrier);
     manager().ScheduleCommand(std::make_unique<CallbackCommand<AppLock>>(
         "", std::make_unique<AppLockDescription>(app_id), std::move(callback)));
   }
@@ -458,7 +459,7 @@
 TEST_F(WebAppCommandManagerTest, AppWithSharedWebContents) {
   auto command1 = std::make_unique<MockCommand<SharedWebContentsWithAppLock>>(
       std::make_unique<SharedWebContentsWithAppLockDescription,
-                       base::flat_set<AppId>>({kTestAppId}));
+                       base::flat_set<webapps::AppId>>({kTestAppId}));
   auto command2 = std::make_unique<MockCommand<AppLock>>(
       std::make_unique<AppLockDescription>(kTestAppId));
   auto command3 = std::make_unique<MockCommand<SharedWebContentsLock>>(
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.cc b/chrome/browser/web_applications/web_app_command_scheduler.cc
index 099f3c9..7becc0b 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.cc
+++ b/chrome/browser/web_applications/web_app_command_scheduler.cc
@@ -111,7 +111,7 @@
     const base::Location& location) {
   if (IsShuttingDown()) {
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback), AppId(),
+        FROM_HERE, base::BindOnce(std::move(callback), webapps::AppId(),
                                   webapps::InstallResultCode::
                                       kCancelledOnWebAppProviderShuttingDown));
     return;
@@ -126,7 +126,7 @@
 }
 
 void WebAppCommandScheduler::FetchInstallInfoFromInstallUrl(
-    ManifestId manifest_id,
+    webapps::ManifestId manifest_id,
     GURL install_url,
     base::OnceCallback<void(std::unique_ptr<WebAppInstallInfo>)> callback) {
   if (IsShuttingDown()) {
@@ -148,7 +148,7 @@
     const base::Location& location) {
   if (IsShuttingDown()) {
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(install_callback), AppId(),
+        FROM_HERE, base::BindOnce(std::move(install_callback), webapps::AppId(),
                                   webapps::InstallResultCode::
                                       kCancelledOnWebAppProviderShuttingDown));
     return;
@@ -171,7 +171,7 @@
     const base::Location& location) {
   if (IsShuttingDown()) {
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(install_callback), AppId(),
+        FROM_HERE, base::BindOnce(std::move(install_callback), webapps::AppId(),
                                   webapps::InstallResultCode::
                                       kCancelledOnWebAppProviderShuttingDown));
     return;
@@ -189,17 +189,17 @@
     std::unique_ptr<WebAppInstallInfo> install_info,
     bool overwrite_existing_manifest_fields,
     webapps::WebappInstallSource install_surface,
-    base::OnceCallback<void(const AppId& app_id,
+    base::OnceCallback<void(const webapps::AppId& app_id,
                             webapps::InstallResultCode code,
                             bool did_uninstall_and_replace)> install_callback,
     const WebAppInstallParams& install_params,
-    const std::vector<AppId>& apps_to_uninstall,
+    const std::vector<webapps::AppId>& apps_to_uninstall,
     const base::Location& location) {
   if (IsShuttingDown()) {
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
         FROM_HERE,
         base::BindOnce(
-            std::move(install_callback), AppId(),
+            std::move(install_callback), webapps::AppId(),
             webapps::InstallResultCode::kCancelledOnWebAppProviderShuttingDown,
             /*did_uninstall_and_replace=*/false));
     return;
@@ -215,7 +215,7 @@
 
 void WebAppCommandScheduler::InstallExternallyManagedApp(
     const ExternalInstallOptions& external_install_options,
-    absl::optional<AppId> installed_placeholder_app_id,
+    absl::optional<webapps::AppId> installed_placeholder_app_id,
     ExternalAppResolutionCommand::InstalledCallback installed_callback,
     const base::Location& location) {
   if (IsShuttingDown()) {
@@ -225,7 +225,7 @@
                        web_app::ExternallyManagedAppManager::InstallResult(
                            webapps::InstallResultCode::
                                kCancelledOnWebAppProviderShuttingDown,
-                           AppId(),
+                           webapps::AppId(),
                            /*did_uninstall_and_replace=*/false)));
     return;
   }
@@ -239,7 +239,7 @@
 }
 
 void WebAppCommandScheduler::PersistFileHandlersUserChoice(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool allowed,
     base::OnceClosure callback,
     const base::Location& location) {
@@ -257,7 +257,7 @@
 
 void WebAppCommandScheduler::ScheduleManifestUpdateCheck(
     const GURL& url,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::Time check_time,
     base::WeakPtr<content::WebContents> contents,
     ManifestUpdateCheckCommand::CompletedCallback callback,
@@ -280,7 +280,7 @@
 
 void WebAppCommandScheduler::ScheduleManifestUpdateFinalize(
     const GURL& url,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     WebAppInstallInfo install_info,
     std::unique_ptr<ScopedKeepAlive> optional_keep_alive,
     std::unique_ptr<ScopedProfileKeepAlive> optional_profile_keep_alive,
@@ -290,7 +290,7 @@
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback),
                                   /*url=*/GURL(),
-                                  /*app_id=*/AppId(),
+                                  /*app_id=*/webapps::AppId(),
                                   ManifestUpdateResult::kWebContentsDestroyed));
     return;
   }
@@ -491,7 +491,7 @@
 }
 
 void WebAppCommandScheduler::RemoveInstallUrl(
-    absl::optional<AppId> app_id,
+    absl::optional<webapps::AppId> app_id,
     WebAppManagement::Type install_source,
     const GURL& install_url,
     webapps::WebappUninstallSource uninstall_source,
@@ -513,7 +513,7 @@
 }
 
 void WebAppCommandScheduler::RemoveInstallSource(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     WebAppManagement::Type install_source,
     webapps::WebappUninstallSource uninstall_source,
     UninstallJob::Callback callback,
@@ -533,7 +533,7 @@
 }
 
 void WebAppCommandScheduler::UninstallWebApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
     UninstallJob::Callback callback,
     const base::Location& location) {
@@ -570,7 +570,7 @@
 }
 
 void WebAppCommandScheduler::SetRunOnOsLoginMode(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     RunOnOsLoginMode login_mode,
     base::OnceClosure callback,
     const base::Location& location) {
@@ -587,7 +587,7 @@
 }
 
 void WebAppCommandScheduler::SyncRunOnOsLoginMode(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure callback,
     const base::Location& location) {
   if (IsShuttingDown()) {
@@ -602,7 +602,7 @@
 }
 
 void WebAppCommandScheduler::UpdateProtocolHandlerUserApproval(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& protocol_scheme,
     ApiApprovalState approval_state,
     base::OnceClosure callback,
@@ -637,7 +637,7 @@
       location);
 }
 
-void WebAppCommandScheduler::SetAppIsDisabled(const AppId& app_id,
+void WebAppCommandScheduler::SetAppIsDisabled(const webapps::AppId& app_id,
                                               bool is_disabled,
                                               base::OnceClosure callback,
                                               const base::Location& location) {
@@ -650,9 +650,9 @@
   provider_->scheduler().ScheduleCallbackWithLock<web_app::AppLock>(
       "SetAppIsDisabled",
       std::make_unique<web_app::AppLockDescription,
-                       base::flat_set<web_app::AppId>>({app_id}),
+                       base::flat_set<webapps::AppId>>({app_id}),
       base::BindOnce(
-          [](const web_app::AppId& app_id, bool is_disabled,
+          [](const webapps::AppId& app_id, bool is_disabled,
              web_app::AppLock& lock) {
             lock.sync_bridge().SetAppIsDisabled(lock, app_id, is_disabled);
           },
@@ -661,7 +661,7 @@
 }
 
 void WebAppCommandScheduler::ComputeAppSize(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceCallback<void(absl::optional<ComputeAppSizeCommand::Size>)>
         callback) {
   if (IsShuttingDown()) {
@@ -708,7 +708,7 @@
 }
 
 void WebAppCommandScheduler::LaunchApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::CommandLine& command_line,
     const base::FilePath& current_directory,
     const absl::optional<GURL>& url_handler_launch_url,
@@ -724,7 +724,7 @@
             std::move(callback), location);
 }
 
-void WebAppCommandScheduler::LaunchUrlInApp(const AppId& app_id,
+void WebAppCommandScheduler::LaunchUrlInApp(const webapps::AppId& app_id,
                                             const GURL& url,
                                             LaunchWebAppCallback callback,
                                             const base::Location& location) {
@@ -751,7 +751,7 @@
             std::move(callback), location);
 }
 
-void WebAppCommandScheduler::InstallAppLocally(const AppId& app_id,
+void WebAppCommandScheduler::InstallAppLocally(const webapps::AppId& app_id,
                                                base::OnceClosure callback,
                                                const base::Location& location) {
   if (IsShuttingDown()) {
@@ -766,7 +766,7 @@
 }
 
 void WebAppCommandScheduler::SynchronizeOsIntegration(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceClosure synchronize_callback,
     absl::optional<SynchronizeOsOptions> synchronize_options,
     const base::Location& location) {
@@ -857,7 +857,7 @@
   // (via the WebAppCommandManager), which is a Profile KeyedService. It is
   // destructed when the profile is shutting down as well. So it is impossible
   // for this callback to be run with the WebAppUiManager being destructed.
-  AppId app_id = params.app_id;
+  webapps::AppId app_id = params.app_id;
   ScheduleCallbackWithLock(
       "LaunchApp", std::make_unique<AppLockDescription>(app_id),
       base::BindOnce(&WebAppUiManager::LaunchWebApp,
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.h b/chrome/browser/web_applications/web_app_command_scheduler.h
index 45d8e7ab..a51ce9b 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.h
+++ b/chrome/browser/web_applications/web_app_command_scheduler.h
@@ -91,7 +91,7 @@
                                const base::Location& location = FROM_HERE);
 
   void FetchInstallInfoFromInstallUrl(
-      ManifestId manifest_id,
+      webapps::ManifestId manifest_id,
       GURL install_url,
       base::OnceCallback<void(std::unique_ptr<WebAppInstallInfo>)> callback);
 
@@ -117,22 +117,22 @@
       std::unique_ptr<WebAppInstallInfo> install_info,
       bool overwrite_existing_manifest_fields,
       webapps::WebappInstallSource install_surface,
-      base::OnceCallback<void(const AppId& app_id,
+      base::OnceCallback<void(const webapps::AppId& app_id,
                               webapps::InstallResultCode code,
                               bool did_uninstall_and_replace)> install_callback,
       const WebAppInstallParams& install_params,
-      const std::vector<AppId>& apps_to_uninstall,
+      const std::vector<webapps::AppId>& apps_to_uninstall,
       const base::Location& location = FROM_HERE);
 
   // Install web apps managed by `ExternallyInstalledAppManager`.
   void InstallExternallyManagedApp(
       const ExternalInstallOptions& external_install_options,
-      absl::optional<AppId> installed_placeholder_app_id,
+      absl::optional<webapps::AppId> installed_placeholder_app_id,
       ExternalAppResolutionCommand::InstalledCallback installed_callback,
       const base::Location& location = FROM_HERE);
 
   void PersistFileHandlersUserChoice(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       bool allowed,
       base::OnceClosure callback,
       const base::Location& location = FROM_HERE);
@@ -141,7 +141,7 @@
   // for a manifest update.
   void ScheduleManifestUpdateCheck(
       const GURL& url,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::Time check_time,
       base::WeakPtr<content::WebContents> contents,
       ManifestUpdateCheckCommand::CompletedCallback callback,
@@ -151,7 +151,7 @@
   // completion of the manifest update.
   void ScheduleManifestUpdateFinalize(
       const GURL& url,
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppInstallInfo install_info,
       std::unique_ptr<ScopedKeepAlive> keep_alive,
       std::unique_ptr<ScopedProfileKeepAlive> profile_keep_alive,
@@ -245,7 +245,7 @@
   // TODO(crbug.com/1434692): There could potentially be multiple app matches
   // for `install_source` and `install_url` when `app_id` is not provided,
   // handle this case better than "first matching".
-  virtual void RemoveInstallUrl(absl::optional<AppId> app_id,
+  virtual void RemoveInstallUrl(absl::optional<webapps::AppId> app_id,
                                 WebAppManagement::Type install_source,
                                 const GURL& install_url,
                                 webapps::WebappUninstallSource uninstall_source,
@@ -258,7 +258,7 @@
   // case.
   // Virtual for testing.
   virtual void RemoveInstallSource(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppManagement::Type install_source,
       webapps::WebappUninstallSource uninstall_source,
       UninstallJob::Callback callback,
@@ -269,7 +269,7 @@
   // uninstalls them too if they have no other install sources. Adds the
   // uninstall web app to `UserUninstalledPreinstalledWebAppPrefs` if it was
   // default installed.
-  void UninstallWebApp(const AppId& app_id,
+  void UninstallWebApp(const webapps::AppId& app_id,
                        webapps::WebappUninstallSource uninstall_source,
                        UninstallJob::Callback callback,
                        const base::Location& location = FROM_HERE);
@@ -282,21 +282,21 @@
 
   // Schedules a command that updates run on os login to provided `login_mode`
   // for a web app.
-  void SetRunOnOsLoginMode(const AppId& app_id,
+  void SetRunOnOsLoginMode(const webapps::AppId& app_id,
                            RunOnOsLoginMode login_mode,
                            base::OnceClosure callback,
                            const base::Location& location = FROM_HERE);
 
   // Schedules a command that syncs the run on os login mode from web app DB to
   // OS.
-  void SyncRunOnOsLoginMode(const AppId& app_id,
+  void SyncRunOnOsLoginMode(const webapps::AppId& app_id,
                             base::OnceClosure callback,
                             const base::Location& location = FROM_HERE);
 
   // Updates the approved or disallowed protocol list for the given app. If
   // necessary, it also updates the protocol registration with the OS.
   void UpdateProtocolHandlerUserApproval(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::string& protocol_scheme,
       ApiApprovalState approval_state,
       base::OnceClosure callback,
@@ -304,14 +304,14 @@
 
   // Set app to disabled, This is Chrome OS specific and no-op on other
   // platforms.
-  void SetAppIsDisabled(const AppId& app_id,
+  void SetAppIsDisabled(const webapps::AppId& app_id,
                         bool is_disabled,
                         base::OnceClosure callback,
                         const base::Location& location = FROM_HERE);
 
   // Schedules a command that calculates the app and data size of a web app.
   void ComputeAppSize(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceCallback<void(absl::optional<ComputeAppSizeCommand::Size>)>
           callback);
 
@@ -347,7 +347,7 @@
 
   // Launches the given app. This call also uses keep-alives to guarantee that
   // the browser and profile will not destruct before the launch is complete.
-  void LaunchApp(const AppId& app_id,
+  void LaunchApp(const webapps::AppId& app_id,
                  const base::CommandLine& command_line,
                  const base::FilePath& current_directory,
                  const absl::optional<GURL>& url_handler_launch_url,
@@ -359,7 +359,7 @@
 
   // Launches the given app to the given url, using keep-alives to guarantee the
   // browser and profile stay alive. Will CHECK-fail if `url` is not valid.
-  void LaunchUrlInApp(const AppId& app_id,
+  void LaunchUrlInApp(const webapps::AppId& app_id,
                       const GURL& url,
                       LaunchWebAppCallback callback,
                       const base::Location& location = FROM_HERE);
@@ -372,14 +372,14 @@
 
   // Used to locally install an app from the chrome://apps page, triggered
   // by the AppLauncherHandler.
-  void InstallAppLocally(const AppId& app_id,
+  void InstallAppLocally(const webapps::AppId& app_id,
                          base::OnceClosure callback,
                          const base::Location& location = FROM_HERE);
 
   // Used to schedule a synchronization of a web app's OS states with the
   // current DB states.
   void SynchronizeOsIntegration(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceClosure synchronize_callback,
       absl::optional<SynchronizeOsOptions> synchronize_options = absl::nullopt,
       const base::Location& location = FROM_HERE);
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc
index 89a5ad7..4b8f6061 100644
--- a/chrome/browser/web_applications/web_app_database.cc
+++ b/chrome/browser/web_applications/web_app_database.cc
@@ -438,8 +438,9 @@
     write_batch->WriteData(web_app->app_id(), proto->SerializeAsString());
   }
 
-  for (const AppId& app_id : update_data.apps_to_delete)
+  for (const webapps::AppId& app_id : update_data.apps_to_delete) {
     write_batch->DeleteData(app_id);
+  }
 
   store_->CommitWriteBatch(
       std::move(write_batch),
@@ -910,7 +911,7 @@
 
   const sync_pb::WebAppSpecifics& sync_data = local_data.sync_data();
 
-  // AppId is a hash of start_url. Read start_url first:
+  // webapps::AppId is a hash of start_url. Read start_url first:
   GURL start_url(sync_data.start_url());
   if (start_url.is_empty() || !start_url.is_valid()) {
     DLOG(ERROR) << "WebApp proto start_url parse error: "
@@ -918,7 +919,7 @@
     return nullptr;
   }
 
-  ManifestId manifest_id;
+  webapps::ManifestId manifest_id;
   if (sync_data.has_relative_manifest_id()) {
     manifest_id =
         GenerateManifestId(sync_data.relative_manifest_id(), start_url);
@@ -926,7 +927,7 @@
     manifest_id = GenerateManifestIdFromStartUrlOnly(start_url);
   }
 
-  AppId app_id = GenerateAppIdFromManifestId(manifest_id);
+  webapps::AppId app_id = GenerateAppIdFromManifestId(manifest_id);
 
   auto web_app = std::make_unique<WebApp>(app_id);
   web_app->SetStartUrl(start_url);
@@ -1709,7 +1710,7 @@
 
   Registry registry;
   for (const syncer::ModelTypeStore::Record& record : *data_records) {
-    const AppId app_id = record.id;
+    const webapps::AppId app_id = record.id;
     std::unique_ptr<WebApp> web_app = ParseWebApp(app_id, record.value);
     if (web_app)
       registry.emplace(app_id, std::move(web_app));
@@ -1734,8 +1735,9 @@
 }
 
 // static
-std::unique_ptr<WebApp> WebAppDatabase::ParseWebApp(const AppId& app_id,
-                                                    const std::string& value) {
+std::unique_ptr<WebApp> WebAppDatabase::ParseWebApp(
+    const webapps::AppId& app_id,
+    const std::string& value) {
   WebAppProto proto;
   const bool parsed = proto.ParseFromString(value);
   if (!parsed) {
diff --git a/chrome/browser/web_applications/web_app_database.h b/chrome/browser/web_applications/web_app_database.h
index 9f574bc..18b9fcaa 100644
--- a/chrome/browser/web_applications/web_app_database.h
+++ b/chrome/browser/web_applications/web_app_database.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/sync/model/model_type_store.h"
 #include "components/sync/protocol/web_app_specifics.pb.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace syncer {
@@ -58,7 +59,7 @@
   // Exposed for testing.
   static std::unique_ptr<WebAppProto> CreateWebAppProto(const WebApp& web_app);
   // Exposed for testing.
-  static std::unique_ptr<WebApp> ParseWebApp(const AppId& app_id,
+  static std::unique_ptr<WebApp> ParseWebApp(const webapps::AppId& app_id,
                                              const std::string& value);
   // Exposed for testing.
   static std::unique_ptr<WebApp> CreateWebApp(const WebAppProto& local_data);
diff --git a/chrome/browser/web_applications/web_app_database_unittest.cc b/chrome/browser/web_applications/web_app_database_unittest.cc
index 8609d7d..6046621d 100644
--- a/chrome/browser/web_applications/web_app_database_unittest.cc
+++ b/chrome/browser/web_applications/web_app_database_unittest.cc
@@ -113,7 +113,7 @@
       std::unique_ptr<WebApp> app = test::CreateRandomWebApp({.seed = i});
       std::unique_ptr<WebAppProto> proto =
           WebAppDatabase::CreateWebAppProto(*app);
-      const AppId app_id = app->app_id();
+      const webapps::AppId app_id = app->app_id();
 
       write_batch->WriteData(app_id, proto->SerializeAsString());
 
@@ -147,15 +147,16 @@
     update->CreateApp(std::move(web_app));
   }
 
-  void UnregisterApp(const AppId& app_id) {
+  void UnregisterApp(const webapps::AppId& app_id) {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
     update->DeleteApp(app_id);
   }
 
   void UnregisterAll() {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
-    for (const AppId& app_id : registrar().GetAppIds())
+    for (const webapps::AppId& app_id : registrar().GetAppIds()) {
       update->DeleteApp(app_id);
+    }
   }
 
  private:
@@ -174,7 +175,7 @@
   const uint32_t num_apps = 100;
 
   std::unique_ptr<WebApp> app = test::CreateRandomWebApp({.seed = 0});
-  AppId app_id = app->app_id();
+  webapps::AppId app_id = app->app_id();
   RegisterApp(std::move(app));
   EXPECT_TRUE(IsDatabaseRegistryEqualToRegistrar());
 
@@ -198,7 +199,7 @@
   const uint32_t num_apps = 100;
 
   RegistryUpdateData::Apps apps_to_create;
-  std::vector<AppId> apps_to_delete;
+  std::vector<webapps::AppId> apps_to_delete;
   Registry expected_registry;
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -238,7 +239,7 @@
     {
       ScopedRegistryUpdate update =
           sync_bridge().BeginUpdate(future.GetCallback());
-      for (const AppId& app_id : apps_to_delete) {
+      for (const webapps::AppId& app_id : apps_to_delete) {
         update->DeleteApp(app_id);
       }
     }
@@ -258,7 +259,8 @@
 
 TEST_F(WebAppDatabaseTest, BackwardCompatibility_WebAppWithOnlyRequiredFields) {
   const GURL start_url{"https://example.com/"};
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  const webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   const std::string name = "App Name";
   const bool is_locally_installed = true;
 
@@ -321,7 +323,7 @@
   InitSyncBridge();
 
   const auto start_url = GURL("https://example.com/");
-  const AppId app_id =
+  const webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, GURL(start_url));
   const std::string name = "Name";
 
@@ -463,7 +465,7 @@
 
   std::unique_ptr<WebApp> app =
       test::CreateRandomWebApp({.base_url = base_url});
-  AppId app_id = app->app_id();
+  webapps::AppId app_id = app->app_id();
 
   std::vector<apps::IconInfo> icons;
 
@@ -611,7 +613,8 @@
  public:
   std::unique_ptr<WebApp> CreateMinimalWebApp() {
     GURL start_url{"https://example.com/"};
-    AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+    webapps::AppId app_id =
+        GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
     auto web_app = std::make_unique<WebApp>(app_id);
     web_app->SetStartUrl(start_url);
     web_app->SetUserDisplayMode(mojom::UserDisplayMode::kBrowser);
diff --git a/chrome/browser/web_applications/web_app_helpers.cc b/chrome/browser/web_applications/web_app_helpers.cc
index 87afa283d..f778b0c 100644
--- a/chrome/browser/web_applications/web_app_helpers.cc
+++ b/chrome/browser/web_applications/web_app_helpers.cc
@@ -39,20 +39,21 @@
   return base::StrCat({url.host_piece(), "_", url.path_piece()});
 }
 
-std::string GenerateApplicationNameFromAppId(const AppId& app_id) {
+std::string GenerateApplicationNameFromAppId(const webapps::AppId& app_id) {
   std::string t(kCrxAppPrefix);
   t.append(app_id);
   return t;
 }
 
-AppId GetAppIdFromApplicationName(const std::string& app_name) {
+webapps::AppId GetAppIdFromApplicationName(const std::string& app_name) {
   std::string prefix(kCrxAppPrefix);
   if (app_name.substr(0, prefix.length()) != prefix)
     return std::string();
   return app_name.substr(prefix.length());
 }
 
-AppId GenerateAppIdFromManifestId(const ManifestId& manifest_id) {
+webapps::AppId GenerateAppIdFromManifestId(
+    const webapps::ManifestId& manifest_id) {
   // The app ID is hashed twice: here and in GenerateId.
   // The double-hashing is for historical reasons and it needs to stay
   // this way for backwards compatibility. (Back then, a web app's input to the
@@ -61,8 +62,9 @@
       crypto::SHA256HashString(manifest_id.spec()));
 }
 
-AppId GenerateAppId(const absl::optional<std::string>& manifest_id_path,
-                    const GURL& start_url) {
+webapps::AppId GenerateAppId(
+    const absl::optional<std::string>& manifest_id_path,
+    const GURL& start_url) {
   if (!manifest_id_path) {
     return GenerateAppIdFromManifestId(
         GenerateManifestIdFromStartUrlOnly(start_url));
@@ -71,8 +73,8 @@
       GenerateManifestId(manifest_id_path.value(), start_url));
 }
 
-ManifestId GenerateManifestId(const std::string& manifest_id_path,
-                              const GURL& start_url) {
+webapps::ManifestId GenerateManifestId(const std::string& manifest_id_path,
+                                       const GURL& start_url) {
   // When manifest_id is specified, the app id is generated from
   // <start_url_origin>/<manifest_id_path>.
   // Note: start_url.DeprecatedGetOriginAsURL().spec() returns the origin ending
@@ -83,12 +85,13 @@
   return app_id.GetWithoutRef();
 }
 
-AppId GenerateAppIdFromManifest(const blink::mojom::Manifest& manifest) {
+webapps::AppId GenerateAppIdFromManifest(
+    const blink::mojom::Manifest& manifest) {
   CHECK(manifest.id.is_valid());
   return GenerateAppIdFromManifestId(manifest.id);
 }
 
-ManifestId GenerateManifestIdFromStartUrlOnly(const GURL& start_url) {
+webapps::ManifestId GenerateManifestIdFromStartUrlOnly(const GURL& start_url) {
   CHECK(start_url.is_valid()) << start_url.spec();
   return start_url.GetWithoutRef();
 }
@@ -105,9 +108,10 @@
           (app_url.host() == password_manager::kChromeUIPasswordManagerHost));
 }
 
-absl::optional<AppId> FindInstalledAppWithUrlInScope(Profile* profile,
-                                                     const GURL& url,
-                                                     bool window_only) {
+absl::optional<webapps::AppId> FindInstalledAppWithUrlInScope(
+    Profile* profile,
+    const GURL& url,
+    bool window_only) {
   auto* provider = WebAppProvider::GetForLocalAppsUnchecked(profile);
   return provider ? provider->registrar_unsafe().FindInstalledAppWithUrlInScope(
                         url, window_only)
diff --git a/chrome/browser/web_applications/web_app_helpers.h b/chrome/browser/web_applications/web_app_helpers.h
index b82c823..986b3d4 100644
--- a/chrome/browser/web_applications/web_app_helpers.h
+++ b/chrome/browser/web_applications/web_app_helpers.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 
@@ -26,24 +27,25 @@
 std::string GenerateApplicationNameFromURL(const GURL& url);
 
 // Compute a deterministic name based on an apps's id.
-std::string GenerateApplicationNameFromAppId(const AppId& app_id);
+std::string GenerateApplicationNameFromAppId(const webapps::AppId& app_id);
 
 // Extracts the application id from the app name.
-AppId GetAppIdFromApplicationName(const std::string& app_name);
+webapps::AppId GetAppIdFromApplicationName(const std::string& app_name);
 
-// Compute the AppId using the given start_url and optional manifest
+// Compute the webapps::AppId using the given start_url and optional manifest
 // id path, which is the path component of the manifest id defined by the spec.
 // This mimics what is given to the spec algorithm as the json manifest_id in
 // https://www.w3.org/TR/appmanifest/#id-member. The `manifest_id_path` can
 // include query arguments and/or fragments, although the fragment will be
-// removed. See the `AppId` type for more information.
+// removed. See the `webapps::AppId` type for more information.
 //
 // This should only be used if a `Manifest` object is not available.
 //
 // TODO(b/281881755): Change the optional parameter to required, and refactor
 // calls with absl::nullopt to `GenerateManifestIdFromStartUrlOnly`.
-AppId GenerateAppId(const absl::optional<std::string>& manifest_id_path,
-                    const GURL& start_url);
+webapps::AppId GenerateAppId(
+    const absl::optional<std::string>& manifest_id_path,
+    const GURL& start_url);
 
 // Returns a resolved manifest id given the relative `manifest_id_path`,
 // as per the spec algorithm at https://www.w3.org/TR/appmanifest/#id-member.
@@ -52,17 +54,19 @@
 // GenerateManifestIdFromStartUrlOnly can be used.
 //
 // This should only be used if a `Manifest` object is not available.
-ManifestId GenerateManifestId(const std::string& manifest_id_path,
-                              const GURL& start_url);
+webapps::ManifestId GenerateManifestId(const std::string& manifest_id_path,
+                                       const GURL& start_url);
 
-// Generates the chrome-specific `AppId` from the spec-defined manifest id. See
-// the `AppId` type for more information.
-AppId GenerateAppIdFromManifestId(const ManifestId& manifest_id);
+// Generates the chrome-specific `webapps::AppId` from the spec-defined manifest
+// id. See the `webapps::AppId` type for more information.
+webapps::AppId GenerateAppIdFromManifestId(
+    const webapps::ManifestId& manifest_id);
 
-// Generates the chrome-specific `AppId` from the spec-defined manifest. See the
-// `AppId` type for more information. This will CHECK-fail if the `id` field is
-// not present on the manifest.
-AppId GenerateAppIdFromManifest(const blink::mojom::Manifest& manifest);
+// Generates the chrome-specific `webapps::AppId` from the spec-defined
+// manifest. See the `webapps::AppId` type for more information. This will
+// CHECK-fail if the `id` field is not present on the manifest.
+webapps::AppId GenerateAppIdFromManifest(
+    const blink::mojom::Manifest& manifest);
 
 // Generates a manifest id by only the start_url, which matches the spec
 // algorithm in https://www.w3.org/TR/appmanifest/#id-member where the `id` json
@@ -70,7 +74,7 @@
 // please use `GenerateManifestId`.
 //
 // This should only be used if a `Manifest` object is not available.
-ManifestId GenerateManifestIdFromStartUrlOnly(const GURL& start_url);
+webapps::ManifestId GenerateManifestIdFromStartUrlOnly(const GURL& start_url);
 
 // Returns whether the given |app_url| is a valid web app url.
 bool IsValidWebAppUrl(const GURL& app_url);
@@ -78,9 +82,10 @@
 // Searches for the first locally installed app id in the registry for which
 // the |url| is in scope. If |window_only| is specified, only apps that
 // open in app windows will be considered.
-absl::optional<AppId> FindInstalledAppWithUrlInScope(Profile* profile,
-                                                     const GURL& url,
-                                                     bool window_only = false);
+absl::optional<webapps::AppId> FindInstalledAppWithUrlInScope(
+    Profile* profile,
+    const GURL& url,
+    bool window_only = false);
 
 // Searches for the first app id in the registry which is not locally installed
 // and for which the |url| is in scope.
diff --git a/chrome/browser/web_applications/web_app_icon_manager.cc b/chrome/browser/web_applications/web_app_icon_manager.cc
index 461815d8..f3df7d5 100644
--- a/chrome/browser/web_applications/web_app_icon_manager.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager.cc
@@ -102,11 +102,11 @@
 }
 
 struct IconId {
-  IconId(AppId app_id, IconPurpose purpose, SquareSizePx size)
+  IconId(webapps::AppId app_id, IconPurpose purpose, SquareSizePx size)
       : app_id(std::move(app_id)), purpose(purpose), size(size) {}
   ~IconId() = default;
 
-  AppId app_id;
+  webapps::AppId app_id;
   IconPurpose purpose;
   SquareSizePx size;
 };
@@ -184,7 +184,7 @@
 // Returns true if no errors occurred.
 bool DeleteDataBlocking(scoped_refptr<FileUtilsWrapper> utils,
                         const base::FilePath& web_apps_directory,
-                        const AppId& app_id) {
+                        const webapps::AppId& app_id) {
   base::FilePath app_dir =
       GetManifestResourcesDirectoryForApp(web_apps_directory, app_id);
 
@@ -206,7 +206,7 @@
 // stored for the relevant profile.
 base::FilePath GetManifestResourcesShortcutsMenuIconFileName(
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     IconPurpose purpose,
     int index,
     int icon_size_px) {
@@ -225,7 +225,7 @@
 // stored for the relevant profile.
 base::FilePath GetManifestResourcesOtherIconsFileName(
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& url,
     int icon_size_px) {
   return GetManifestResourcesDirectoryForApp(web_apps_directory, app_id)
@@ -283,7 +283,7 @@
 TypedResult<SkBitmap> ReadShortcutsMenuIconBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     IconPurpose purpose,
     int index,
     int icon_size_px) {
@@ -314,7 +314,7 @@
 TypedResult<SkBitmap> ReadHomeTabIconFromFileAndResizeBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const GURL& url,
     int icon_size_px,
     const SquareSizePx target_icon_size_px) {
@@ -380,7 +380,7 @@
 TypedResult<std::map<SquareSizePx, SkBitmap>> ReadIconsBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     IconPurpose purpose,
     const std::vector<SquareSizePx>& icon_sizes) {
   TRACE_EVENT0("ui", "web_app_icon_manager::ReadIconsBlocking");
@@ -402,7 +402,7 @@
 TypedResult<base::flat_map<SquareSizePx, base::Time>>
 ReadIconsLastUpdateTimeBlocking(scoped_refptr<FileUtilsWrapper> utils,
                                 const base::FilePath& web_apps_directory,
-                                const AppId& app_id,
+                                const webapps::AppId& app_id,
                                 IconPurpose purpose,
                                 const std::vector<SquareSizePx>& icon_sizes) {
   TRACE_EVENT0("ui", "web_app_icon_manager::ReadIconsLastUpdateTimeBlocking");
@@ -424,7 +424,7 @@
 TypedResult<IconBitmaps> ReadAllIconsBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::map<IconPurpose, std::vector<SquareSizePx>>&
         icon_purposes_to_sizes) {
   TRACE_EVENT0("ui", "web_app_icon_manager::ReadAllIconsBlocking");
@@ -446,7 +446,7 @@
 TypedResult<ShortcutsMenuIconBitmaps> ReadShortcutsMenuIconsBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_item_infos) {
   TRACE_EVENT0("ui", "web_app_icon_manager::ReadShortcutsMenuIconsBlocking");
   TypedResult<ShortcutsMenuIconBitmaps> results;
@@ -531,7 +531,7 @@
 TypedResult<SkBitmap> ReadHomeTabIconBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<blink::Manifest::ImageResource>& icons,
     const SquareSizePx min_home_tab_icon_size_px) {
   TRACE_EVENT0("ui", "web_app_icon_manager::ReadHomeTabIconBlocking");
@@ -555,7 +555,7 @@
 ReadShortcutMenuIconsWithTimestampBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<WebAppShortcutsMenuItemInfo>& shortcuts_menu_icon_infos) {
   TRACE_EVENT0(
       "ui", "web_app_icon_manager::ReadShortcutMenuIconsWithTimestampBlocking");
@@ -612,7 +612,7 @@
 WebAppIconManager::IconFilesCheck CheckForEmptyOrMissingIconFilesBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::flat_map<IconPurpose, SortedSizesPx> purpose_to_sizes) {
   TRACE_EVENT0("ui",
                "web_app_icon_manager::CheckForEmptyOrMissingIconFilesBlocking");
@@ -676,7 +676,7 @@
   static TypedResult<bool> WriteIconsBlocking(
       scoped_refptr<FileUtilsWrapper> utils,
       base::FilePath&& web_apps_directory,
-      AppId&& app_id,
+      webapps::AppId&& app_id,
       IconBitmaps&& icon_bitmaps,
       ShortcutsMenuIconBitmaps&& shortcuts_menu_icon_bitmaps,
       IconsMap&& other_icons) {
@@ -695,7 +695,7 @@
  private:
   WriteIconsJob(scoped_refptr<FileUtilsWrapper> utils,
                 base::FilePath&& web_apps_directory,
-                AppId&& app_id,
+                webapps::AppId&& app_id,
                 IconBitmaps&& icon_bitmaps,
                 ShortcutsMenuIconBitmaps&& shortcuts_menu_icon_bitmaps,
                 IconsMap&& other_icons)
@@ -938,7 +938,7 @@
 
   scoped_refptr<FileUtilsWrapper> utils_;
   base::FilePath web_apps_directory_;
-  AppId app_id_;
+  webapps::AppId app_id_;
   IconBitmaps icon_bitmaps_;
   ShortcutsMenuIconBitmaps shortcuts_menu_icon_bitmaps_;
   SkBitmap home_tab_icon_bitmap_;
@@ -971,7 +971,7 @@
 WebAppIconManager::~WebAppIconManager() = default;
 
 void WebAppIconManager::WriteData(
-    AppId app_id,
+    webapps::AppId app_id,
     IconBitmaps icon_bitmaps,
     ShortcutsMenuIconBitmaps shortcuts_menu_icon_bitmaps,
     IconsMap other_icons_map,
@@ -989,7 +989,8 @@
                      std::move(callback)));
 }
 
-void WebAppIconManager::DeleteData(AppId app_id, WriteDataCallback callback) {
+void WebAppIconManager::DeleteData(webapps::AppId app_id,
+                                   WriteDataCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   icon_task_runner_->PostTaskAndReplyWithResult(
@@ -1006,7 +1007,8 @@
 
 void WebAppIconManager::Start() {
   TRACE_EVENT0("ui", "WebAppIconManager::Start");
-  for (const AppId& app_id : provider_->registrar_unsafe().GetAppIds()) {
+  for (const webapps::AppId& app_id :
+       provider_->registrar_unsafe().GetAppIds()) {
     ReadFavicon(app_id);
 
 #if BUILDFLAG(IS_CHROMEOS)
@@ -1019,7 +1021,7 @@
 
 void WebAppIconManager::Shutdown() {}
 
-bool WebAppIconManager::HasIcons(const AppId& app_id,
+bool WebAppIconManager::HasIcons(const webapps::AppId& app_id,
                                  IconPurpose purpose,
                                  const SortedSizesPx& icon_sizes) const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -1032,7 +1034,7 @@
 }
 
 absl::optional<WebAppIconManager::IconSizeAndPurpose>
-WebAppIconManager::FindIconMatchBigger(const AppId& app_id,
+WebAppIconManager::FindIconMatchBigger(const webapps::AppId& app_id,
                                        const std::vector<IconPurpose>& purposes,
                                        SquareSizePx min_size) const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -1054,13 +1056,13 @@
 }
 
 bool WebAppIconManager::HasSmallestIcon(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<IconPurpose>& purposes,
     SquareSizePx min_size) const {
   return FindIconMatchBigger(app_id, purposes, min_size).has_value();
 }
 
-void WebAppIconManager::ReadIcons(const AppId& app_id,
+void WebAppIconManager::ReadIcons(const webapps::AppId& app_id,
                                   IconPurpose purpose,
                                   const SortedSizesPx& icon_sizes,
                                   ReadIconsCallback callback) {
@@ -1084,7 +1086,7 @@
 }
 
 void WebAppIconManager::ReadAllShortcutMenuIconsWithTimestamp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ShortcutIconDataCallback callback) {
   TRACE_EVENT0("ui",
                "WebAppIconManager::ReadAllShortcutMenuIconsWithTimestamp");
@@ -1104,7 +1106,7 @@
 }
 
 void WebAppIconManager::ReadIconsLastUpdateTime(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ReadIconsUpdateTimeCallback callback) {
   TRACE_EVENT0("ui", "WebAppIconManager::ReadIconsLastUpdateTime");
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -1127,7 +1129,7 @@
           GetWeakPtr(), std::move(callback)));
 }
 
-void WebAppIconManager::ReadAllIcons(const AppId& app_id,
+void WebAppIconManager::ReadAllIcons(const webapps::AppId& app_id,
                                      ReadIconBitmapsCallback callback) {
   TRACE_EVENT0("ui", "WebAppIconManager::ReadAllIcons");
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -1155,7 +1157,7 @@
 }
 
 void WebAppIconManager::ReadAllShortcutsMenuIcons(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ReadShortcutsMenuIconsCallback callback) {
   TRACE_EVENT0("ui", "WebAppIconManager::ReadAllShortcutsMenuIcons");
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -1175,7 +1177,7 @@
 }
 
 void WebAppIconManager::ReadBestHomeTabIcon(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<blink::Manifest::ImageResource>& icons,
     const SquareSizePx min_home_tab_icon_size_px,
     ReadHomeTabIconsCallback callback) {
@@ -1196,7 +1198,7 @@
 }
 
 void WebAppIconManager::GetIconsSizeForApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     WebAppIconManager::GetIconsSizeCallback callback) const {
   std::vector<base::FilePath> icon_paths;
 
@@ -1217,7 +1219,7 @@
 }
 
 void WebAppIconManager::ReadSmallestIcon(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<IconPurpose>& purposes,
     SquareSizePx min_size_in_px,
     ReadIconWithPurposeCallback callback) {
@@ -1240,7 +1242,7 @@
 }
 
 void WebAppIconManager::ReadSmallestCompressedIcon(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<IconPurpose>& purposes,
     SquareSizePx min_size_in_px,
     ReadCompressedIconWithPurposeCallback callback) {
@@ -1262,7 +1264,7 @@
                      std::move(wrapped)));
 }
 
-SkBitmap WebAppIconManager::GetFavicon(const AppId& app_id) const {
+SkBitmap WebAppIconManager::GetFavicon(const webapps::AppId& app_id) const {
   auto iter = favicon_cache_.find(app_id);
   if (iter == favicon_cache_.end())
     return SkBitmap();
@@ -1275,19 +1277,19 @@
 }
 
 gfx::ImageSkia WebAppIconManager::GetFaviconImageSkia(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto iter = favicon_cache_.find(app_id);
   return iter != favicon_cache_.end() ? iter->second : gfx::ImageSkia();
 }
 
 gfx::ImageSkia WebAppIconManager::GetMonochromeFavicon(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto iter = favicon_monochrome_cache_.find(app_id);
   return iter != favicon_monochrome_cache_.end() ? iter->second
                                                  : gfx::ImageSkia();
 }
 
-void WebAppIconManager::OnWebAppInstalled(const AppId& app_id) {
+void WebAppIconManager::OnWebAppInstalled(const webapps::AppId& app_id) {
   TRACE_EVENT0("ui", "WebAppIconManager::OnWebAppInstalled");
   ReadFavicon(app_id);
   // Monochrome icons are used in tabbed apps and for ChromeOS notifications.
@@ -1298,7 +1300,7 @@
   install_manager_observation_.Reset();
 }
 
-void WebAppIconManager::ReadIconAndResize(const AppId& app_id,
+void WebAppIconManager::ReadIconAndResize(const webapps::AppId& app_id,
                                           IconPurpose purpose,
                                           SquareSizePx desired_icon_size,
                                           ReadIconsCallback callback) {
@@ -1325,7 +1327,7 @@
 }
 
 void WebAppIconManager::ReadUiScaleFactorsIcons(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     IconPurpose purpose,
     SquareSizeDip size_in_dip,
     ReadImageSkiaCallback callback) {
@@ -1362,7 +1364,7 @@
 }
 
 void WebAppIconManager::CheckForEmptyOrMissingIconFiles(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::OnceCallback<void(IconFilesCheck)> callback) const {
   TRACE_EVENT0("ui", "WebAppIconManager::CheckForEmptyOrMissingIconFiles");
   const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
@@ -1393,9 +1395,10 @@
   favicon_monochrome_read_callback_ = std::move(callback);
 }
 
-base::FilePath WebAppIconManager::GetIconFilePathForTesting(const AppId& app_id,
-                                                            IconPurpose purpose,
-                                                            SquareSizePx size) {
+base::FilePath WebAppIconManager::GetIconFilePathForTesting(
+    const webapps::AppId& app_id,
+    IconPurpose purpose,
+    SquareSizePx size) {
   return GetIconFileName(web_apps_directory_, IconId(app_id, purpose, size));
 }
 
@@ -1409,7 +1412,7 @@
 
 absl::optional<WebAppIconManager::IconSizeAndPurpose>
 WebAppIconManager::FindIconMatchSmaller(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::vector<IconPurpose>& purposes,
     SquareSizePx max_size) const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -1430,14 +1433,14 @@
   return absl::nullopt;
 }
 
-void WebAppIconManager::ReadFavicon(const AppId& app_id) {
+void WebAppIconManager::ReadFavicon(const webapps::AppId& app_id) {
   TRACE_EVENT0("ui", "WebAppIconManager::ReadFavicon");
   ReadUiScaleFactorsIcons(
       app_id, IconPurpose::ANY, gfx::kFaviconSize,
       base::BindOnce(&WebAppIconManager::OnReadFavicon, GetWeakPtr(), app_id));
 }
 
-void WebAppIconManager::OnReadFavicon(const AppId& app_id,
+void WebAppIconManager::OnReadFavicon(const webapps::AppId& app_id,
                                       gfx::ImageSkia image_skia) {
   TRACE_EVENT0("ui", "WebAppIconManager::OnReadFavicon");
   if (!image_skia.isNull())
@@ -1447,7 +1450,7 @@
     favicon_read_callback_.Run(app_id);
 }
 
-void WebAppIconManager::ReadMonochromeFavicon(const AppId& app_id) {
+void WebAppIconManager::ReadMonochromeFavicon(const webapps::AppId& app_id) {
   TRACE_EVENT0("ui", "WebAppIconManager::ReadMonochromeFavicon");
   ReadUiScaleFactorsIcons(
       app_id, IconPurpose::MONOCHROME, gfx::kFaviconSize,
@@ -1456,7 +1459,7 @@
 }
 
 void WebAppIconManager::OnReadMonochromeFavicon(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     gfx::ImageSkia manifest_monochrome_image) {
   TRACE_EVENT0("ui", "WebAppIconManager::OnReadMonochromeFavicon");
   const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
@@ -1482,7 +1485,7 @@
 }
 
 void WebAppIconManager::OnMonochromeIconConverted(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     gfx::ImageSkia converted_image) {
   TRACE_EVENT0("ui", "WebAppIconManager::OnMonochromeIconConverted");
   if (!converted_image.isNull())
diff --git a/chrome/browser/web_applications/web_app_icon_manager.h b/chrome/browser/web_applications/web_app_icon_manager.h
index 96548808..de3864b 100644
--- a/chrome/browser/web_applications/web_app_icon_manager.h
+++ b/chrome/browser/web_applications/web_app_icon_manager.h
@@ -22,6 +22,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/image/image_skia.h"
@@ -46,7 +47,7 @@
 class WebAppIconManager : public WebAppInstallManagerObserver {
  public:
   using FaviconReadCallback =
-      base::RepeatingCallback<void(const AppId& app_id)>;
+      base::RepeatingCallback<void(const webapps::AppId& app_id)>;
   using ReadImageSkiaCallback =
       base::OnceCallback<void(gfx::ImageSkia image_skia)>;
 
@@ -58,12 +59,12 @@
   using WriteDataCallback = base::OnceCallback<void(bool success)>;
 
   // Writes all data (icons) for an app.
-  void WriteData(AppId app_id,
+  void WriteData(webapps::AppId app_id,
                  IconBitmaps icon_bitmaps,
                  ShortcutsMenuIconBitmaps shortcuts_menu_icons,
                  IconsMap other_icons_map,
                  WriteDataCallback callback);
-  void DeleteData(AppId app_id, WriteDataCallback callback);
+  void DeleteData(webapps::AppId app_id, WriteDataCallback callback);
 
   void SetProvider(base::PassKey<WebAppProvider>, WebAppProvider& provider);
   void Start();
@@ -71,7 +72,7 @@
 
   // Returns false if any icon in |icon_sizes_in_px| is missing from downloaded
   // icons for a given app and |purpose|.
-  bool HasIcons(const AppId& app_id,
+  bool HasIcons(const webapps::AppId& app_id,
                 IconPurpose purpose,
                 const SortedSizesPx& icon_sizes) const;
   struct IconSizeAndPurpose {
@@ -82,12 +83,12 @@
   // For each of |purposes|, in the given order, looks for an icon with size at
   // least |min_icon_size|. Returns information on the first icon found.
   absl::optional<IconSizeAndPurpose> FindIconMatchBigger(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<IconPurpose>& purposes,
       SquareSizePx min_size) const;
   // Returns whether there is a downloaded icon of at least |min_size| for any
   // of the given |purposes|.
-  bool HasSmallestIcon(const AppId& app_id,
+  bool HasSmallestIcon(const webapps::AppId& app_id,
                        const std::vector<IconPurpose>& purposes,
                        SquareSizePx min_size) const;
 
@@ -95,7 +96,7 @@
       base::OnceCallback<void(std::map<SquareSizePx, SkBitmap> icon_bitmaps)>;
   // Reads specified icon bitmaps for an app and |purpose|. Returns empty map in
   // |callback| if IO error.
-  void ReadIcons(const AppId& app_id,
+  void ReadIcons(const webapps::AppId& app_id,
                  IconPurpose purpose,
                  const SortedSizesPx& icon_sizes,
                  ReadIconsCallback callback);
@@ -108,14 +109,14 @@
   using ShortcutIconDataCallback =
       base::OnceCallback<void(ShortcutIconDataVector)>;
 
-  void ReadAllShortcutMenuIconsWithTimestamp(const AppId& app_id,
+  void ReadAllShortcutMenuIconsWithTimestamp(const webapps::AppId& app_id,
                                              ShortcutIconDataCallback callback);
 
   using ReadIconsUpdateTimeCallback = base::OnceCallback<void(
       base::flat_map<SquareSizePx, base::Time> time_map)>;
   // Reads all the last updated time for all icons in the app. Returns empty map
   // in |callback| if IO error.
-  void ReadIconsLastUpdateTime(const AppId& app_id,
+  void ReadIconsLastUpdateTime(const webapps::AppId& app_id,
                                ReadIconsUpdateTimeCallback callback);
 
   // TODO (crbug.com/1102701): Callback with const ref instead of value.
@@ -123,7 +124,8 @@
       base::OnceCallback<void(IconBitmaps icon_bitmaps)>;
   // Reads all icon bitmaps for an app. Returns empty |icon_bitmaps| in
   // |callback| if IO error.
-  void ReadAllIcons(const AppId& app_id, ReadIconBitmapsCallback callback);
+  void ReadAllIcons(const webapps::AppId& app_id,
+                    ReadIconBitmapsCallback callback);
 
   using ReadShortcutsMenuIconsCallback = base::OnceCallback<void(
       ShortcutsMenuIconBitmaps shortcuts_menu_icon_bitmaps)>;
@@ -131,7 +133,7 @@
   // map<SquareSizePx, SkBitmap>. The index of a map in the vector is the same
   // as that of its corresponding shortcut in the manifest's shortcuts vector.
   // Returns empty vector in |callback| if we hit any error.
-  void ReadAllShortcutsMenuIcons(const AppId& app_id,
+  void ReadAllShortcutsMenuIcons(const webapps::AppId& app_id,
                                  ReadShortcutsMenuIconsCallback callback);
 
   using ReadHomeTabIconsCallback =
@@ -141,7 +143,7 @@
   // in |callback| if the icon exists. Otherwise, if it doesn't
   // exist, the SkBitmap is empty.
   void ReadBestHomeTabIcon(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<blink::Manifest::ImageResource>& icons,
       const SquareSizePx min_home_tab_icon_size_px,
       ReadHomeTabIconsCallback callback);
@@ -151,7 +153,7 @@
   // For each of |purposes|, in the given order, looks for an icon with size at
   // least |min_icon_size|. Returns the first icon found, as a bitmap. Returns
   // an empty SkBitmap in |callback| if IO error.
-  void ReadSmallestIcon(const AppId& app_id,
+  void ReadSmallestIcon(const webapps::AppId& app_id,
                         const std::vector<IconPurpose>& purposes,
                         SquareSizePx min_size_in_px,
                         ReadIconWithPurposeCallback callback);
@@ -162,34 +164,34 @@
   // least |min_icon_size|. Returns the first icon found, compressed as PNG.
   // Returns empty |data| in |callback| if IO error.
   void ReadSmallestCompressedIcon(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<IconPurpose>& purposes,
       SquareSizePx min_size_in_px,
       ReadCompressedIconWithPurposeCallback callback);
 
   using ReadCompressedIconsSizeCallback =
-      base::OnceCallback<void(const AppId& app_id, uint64_t size)>;
+      base::OnceCallback<void(const webapps::AppId& app_id, uint64_t size)>;
 
   using GetIconsSizeCallback = base::OnceCallback<void(uint64_t)>;
-  void GetIconsSizeForApp(const AppId& app_id,
+  void GetIconsSizeForApp(const webapps::AppId& app_id,
                           GetIconsSizeCallback callback) const;
 
   // Returns a square icon of gfx::kFaviconSize px, or an empty bitmap if not
   // found.
-  SkBitmap GetFavicon(const AppId& app_id) const;
+  SkBitmap GetFavicon(const webapps::AppId& app_id) const;
 
-  gfx::ImageSkia GetFaviconImageSkia(const AppId& app_id) const;
-  gfx::ImageSkia GetMonochromeFavicon(const AppId& app_id) const;
+  gfx::ImageSkia GetFaviconImageSkia(const webapps::AppId& app_id) const;
+  gfx::ImageSkia GetMonochromeFavicon(const webapps::AppId& app_id) const;
 
   // WebAppInstallManagerObserver:
-  void OnWebAppInstalled(const AppId& app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
 
   // Calls back with an icon of the |desired_icon_size| and |purpose|, resizing
   // an icon of a different size if necessary. If no icons were available, calls
   // back with an empty map. Prefers resizing a large icon smaller over resizing
   // a small icon larger.
-  void ReadIconAndResize(const AppId& app_id,
+  void ReadIconAndResize(const webapps::AppId& app_id,
                          IconPurpose purpose,
                          SquareSizePx desired_icon_size,
                          ReadIconsCallback callback);
@@ -198,7 +200,7 @@
   // See ui/base/resource/resource_scale_factor.h. Returns null image in
   // `callback` if no icons found for all supported UI scale factors (matches
   // only bigger icons, no upscaling).
-  void ReadUiScaleFactorsIcons(const AppId& app_id,
+  void ReadUiScaleFactorsIcons(const webapps::AppId& app_id,
                                IconPurpose purpose,
                                SquareSizeDip size_in_dip,
                                ReadImageSkiaCallback callback);
@@ -208,13 +210,13 @@
     size_t missing = 0;
   };
   void CheckForEmptyOrMissingIconFiles(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       base::OnceCallback<void(IconFilesCheck)> callback) const;
 
   void SetFaviconReadCallbackForTesting(FaviconReadCallback callback);
   void SetFaviconMonochromeReadCallbackForTesting(FaviconReadCallback callback);
 
-  base::FilePath GetIconFilePathForTesting(const AppId& app_id,
+  base::FilePath GetIconFilePathForTesting(const webapps::AppId& app_id,
                                            IconPurpose purpose,
                                            SquareSizePx size);
 
@@ -228,7 +230,7 @@
   base::WeakPtr<WebAppIconManager> GetWeakPtr();
 
   absl::optional<IconSizeAndPurpose> FindIconMatchSmaller(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<IconPurpose>& purposes,
       SquareSizePx max_size) const;
 
@@ -236,13 +238,13 @@
                                  ReadImageSkiaCallback callback,
                                  std::map<SquareSizePx, SkBitmap> icon_bitmaps);
 
-  void ReadFavicon(const AppId& app_id);
-  void OnReadFavicon(const AppId& app_id, gfx::ImageSkia image_skia);
+  void ReadFavicon(const webapps::AppId& app_id);
+  void OnReadFavicon(const webapps::AppId& app_id, gfx::ImageSkia image_skia);
 
-  void ReadMonochromeFavicon(const AppId& app_id);
-  void OnReadMonochromeFavicon(const AppId& app_id,
+  void ReadMonochromeFavicon(const webapps::AppId& app_id);
+  void OnReadMonochromeFavicon(const webapps::AppId& app_id,
                                gfx::ImageSkia manifest_monochrome_image);
-  void OnMonochromeIconConverted(const AppId& app_id,
+  void OnMonochromeIconConverted(const webapps::AppId& app_id,
                                  gfx::ImageSkia converted_image);
 
   raw_ptr<WebAppProvider> provider_ = nullptr;
@@ -254,8 +256,8 @@
       install_manager_observation_{this};
 
   // We cache different densities for high-DPI displays per each app.
-  std::map<AppId, gfx::ImageSkia> favicon_cache_;
-  std::map<AppId, gfx::ImageSkia> favicon_monochrome_cache_;
+  std::map<webapps::AppId, gfx::ImageSkia> favicon_cache_;
+  std::map<webapps::AppId, gfx::ImageSkia> favicon_monochrome_cache_;
 
   FaviconReadCallback favicon_read_callback_;
   FaviconReadCallback favicon_monochrome_read_callback_;
diff --git a/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc b/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc
index f3f61d15b..b889161 100644
--- a/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc
@@ -72,7 +72,7 @@
   const GURL start_url =
       https_server()->GetURL("/banners/manifest_test_page.html");
 
-  AppId app_id;
+  webapps::AppId app_id;
   {
     std::unique_ptr<WebAppInstallInfo> install_info =
         std::make_unique<WebAppInstallInfo>();
@@ -96,7 +96,7 @@
         /*overwrite_existing_manifest_fields=*/false,
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
         base::BindLambdaForTesting(
-            [&app_id, &run_loop](const AppId& installed_app_id,
+            [&app_id, &run_loop](const webapps::AppId& installed_app_id,
                                  webapps::InstallResultCode code) {
               EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
               app_id = installed_app_id;
diff --git a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
index 14c4e09..1c1a0ed 100644
--- a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
@@ -77,7 +77,7 @@
 
  protected:
   void WriteGeneratedShortcutsMenuIcons(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<GeneratedIconsInfo>& icons_info,
       int num_menu_items) {
     ShortcutsMenuIconBitmaps shortcuts_menu_icons;
@@ -111,7 +111,8 @@
     run_loop.Run();
   }
 
-  ShortcutsMenuIconBitmaps ReadAllShortcutsMenuIcons(const AppId& app_id) {
+  ShortcutsMenuIconBitmaps ReadAllShortcutsMenuIcons(
+      const webapps::AppId& app_id) {
     ShortcutsMenuIconBitmaps result;
     base::RunLoop run_loop;
     icon_manager().ReadAllShortcutsMenuIcons(
@@ -128,7 +129,7 @@
     IconPurpose purpose;
     SkBitmap bitmap;
   };
-  PurposeAndBitmap ReadSmallestIcon(const AppId& app_id,
+  PurposeAndBitmap ReadSmallestIcon(const webapps::AppId& app_id,
                                     const std::vector<IconPurpose>& purposes,
                                     SquareSizePx min_icon_size) {
     PurposeAndBitmap result;
@@ -149,7 +150,7 @@
     std::vector<uint8_t> data;
   };
   PurposeAndData ReadSmallestCompressedIcon(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const std::vector<IconPurpose>& purposes,
       int min_size_in_px) {
     EXPECT_TRUE(
@@ -171,7 +172,7 @@
     return result;
   }
 
-  SkColor ReadIconAndResize(const AppId& app_id,
+  SkColor ReadIconAndResize(const webapps::AppId& app_id,
                             IconPurpose purpose,
                             int desired_icon_size) {
     base::RunLoop run_loop;
@@ -195,7 +196,8 @@
     return icon_color;
   }
 
-  SkColor ReadIconAndResize(const AppId& app_id, int desired_icon_size) {
+  SkColor ReadIconAndResize(const webapps::AppId& app_id,
+                            int desired_icon_size) {
     return ReadIconAndResize(app_id, IconPurpose::ANY, desired_icon_size);
   }
 
@@ -207,10 +209,10 @@
   // Read favicons on web_app installation and await
   // WebAppIconManager::favicon_read_callback_ synchronously.
   void AwaitReadFaviconOnAddingWebApp(std::unique_ptr<WebApp> web_app) {
-    const AppId& app_id = web_app->app_id();
+    const webapps::AppId& app_id = web_app->app_id();
     base::RunLoop run_loop;
     icon_manager().SetFaviconReadCallbackForTesting(
-        base::BindLambdaForTesting([&](const AppId& cached_app_id) {
+        base::BindLambdaForTesting([&](const webapps::AppId& cached_app_id) {
           EXPECT_EQ(cached_app_id, app_id);
           run_loop.Quit();
         }));
@@ -224,10 +226,10 @@
   // WebAppIconManager::favicon_monochrome_read_callback_ synchronously.
   void AwaitReadFaviconMonochromeOnAddingWebApp(
       std::unique_ptr<WebApp> web_app) {
-    const AppId& app_id = web_app->app_id();
+    const webapps::AppId& app_id = web_app->app_id();
     base::RunLoop run_loop;
     icon_manager().SetFaviconMonochromeReadCallbackForTesting(
-        base::BindLambdaForTesting([&](const AppId& cached_app_id) {
+        base::BindLambdaForTesting([&](const webapps::AppId& cached_app_id) {
           EXPECT_EQ(cached_app_id, app_id);
           run_loop.Quit();
         }));
@@ -252,7 +254,7 @@
 
 TEST_F(WebAppIconManagerTest, WriteAndReadIcons_AnyOnly) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k256, icon_size::k512};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW};
@@ -292,7 +294,7 @@
 
 TEST_F(WebAppIconManagerTest, WriteAndReadIcons_MaskableOnly) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k256, icon_size::k512};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW};
@@ -331,7 +333,7 @@
 
 TEST_F(WebAppIconManagerTest, WriteAndReadIcons_MonochromeOnly) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k128, icon_size::k256};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorTRANSPARENT};
@@ -373,7 +375,7 @@
 
 TEST_F(WebAppIconManagerTest, WriteAndReadIcons_AnyAndMaskable) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k256, icon_size::k512};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW};
@@ -436,7 +438,7 @@
 
 TEST_F(WebAppIconManagerTest, WriteAndReadIcons_AnyAndMonochrome) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px_any{icon_size::k256, icon_size::k512};
   const std::vector<SkColor> colors_any{SK_ColorGREEN, SK_ColorYELLOW};
@@ -507,7 +509,7 @@
 
 TEST_F(WebAppIconManagerTest, OverwriteIcons) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // Write initial red icons to be overwritten.
   {
@@ -604,7 +606,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadAllIcons_AnyOnly) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k256, icon_size::k512};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW};
@@ -633,7 +635,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadAllIconsLastUpdateTime) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k256, icon_size::k512};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW};
@@ -656,7 +658,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadAllShortcutMenuIconsWithTimestamp) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const int num_menu_items = 2;
 
@@ -714,7 +716,7 @@
 
 TEST_F(WebAppIconManagerTest, NoHomeTabIcons) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   const std::vector<blink::Manifest::ImageResource>& icons{};
   SkBitmap result;
 
@@ -736,7 +738,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadAllIcons_AnyAndMaskable) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k256, icon_size::k512};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW};
@@ -769,7 +771,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadShortcutsMenuIconsFailed) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<SquareSizePx> sizes_px_any{icon_size::k96, icon_size::k256};
   const int num_menu_items = 10;
@@ -794,7 +796,7 @@
 
 TEST_F(WebAppIconManagerTest, WriteAndReadAllShortcutsMenuIcons) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const int num_menu_items = 3;
 
@@ -875,7 +877,7 @@
 
 TEST_F(WebAppIconManagerTest, WriteNonProductIconsEmptyMaps) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   web_app->SetShortcutsMenuInfo({});
 
@@ -901,7 +903,7 @@
 
 TEST_F(WebAppIconManagerTest, WriteOtherIconsToDisk) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   AddAppToRegistry(std::move(web_app));
 
@@ -925,7 +927,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadIconsFailed) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<SquareSizePx> icon_sizes_px{icon_size::k256};
 
@@ -957,7 +959,7 @@
 
 TEST_F(WebAppIconManagerTest, FindExact) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{10, 60, 50, 20, 30};
   const std::vector<SkColor> colors{SK_ColorRED, SK_ColorYELLOW, SK_ColorGREEN,
@@ -998,7 +1000,7 @@
 
 TEST_F(WebAppIconManagerTest, FindSmallest) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{10, 60, 50, 20, 30};
   const std::vector<SkColor> colors{SK_ColorRED, SK_ColorYELLOW, SK_ColorGREEN,
@@ -1083,10 +1085,10 @@
 }
 
 TEST_F(WebAppIconManagerTest, DeleteData_Success) {
-  const AppId app1_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
-                                      GURL("https://example.com/"));
-  const AppId app2_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
-                                      GURL("https://example.org/"));
+  const webapps::AppId app1_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
+                                               GURL("https://example.com/"));
+  const webapps::AppId app2_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
+                                               GURL("https://example.org/"));
 
   const std::vector<int> sizes_px{icon_size::k128};
   const std::vector<SkColor> colors{SK_ColorMAGENTA};
@@ -1129,8 +1131,8 @@
 }
 
 TEST_F(WebAppIconManagerTest, DeleteData_Failure) {
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
-                                     GURL("https://example.com/"));
+  const webapps::AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt,
+                                              GURL("https://example.com/"));
 
   file_utils().SetNextDeleteFileRecursivelyResult(false);
 
@@ -1145,7 +1147,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadSmallestCompressedIcon_Success_AnyOnly) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k128};
   const std::vector<SkColor> colors{SK_ColorGREEN};
@@ -1178,7 +1180,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadSmallestCompressedIcon_Success) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k64, icon_size::k128};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorGREEN};
@@ -1246,7 +1248,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadSmallestCompressedIcon_Failure) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k64};
   web_app->SetDownloadedIconSizes(IconPurpose::ANY, sizes_px);
@@ -1278,7 +1280,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadIconAndResize_Success_AnyOnly) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k32, icon_size::k64,
                                   icon_size::k256, icon_size::k512};
@@ -1316,7 +1318,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadIconAndResize_Success_AnyAndMaskable) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{icon_size::k32, icon_size::k64,
                                   icon_size::k256, icon_size::k512};
@@ -1358,7 +1360,7 @@
 
 TEST_F(WebAppIconManagerTest, ReadIconAndResize_Failure) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   web_app->SetDownloadedIconSizes(IconPurpose::ANY,
                                   {icon_size::k32, icon_size::k64});
@@ -1393,7 +1395,7 @@
 
 TEST_F(WebAppIconManagerTest, CacheExistingAppFavicon) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{gfx::kFaviconSize, icon_size::k48};
   const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorRED};
@@ -1413,7 +1415,7 @@
 
 TEST_F(WebAppIconManagerTest, CacheAppFaviconWithResize) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // App does not declare an icon of gfx::kFaviconSize, forcing a resize.
   const std::vector<int> sizes_px{8, icon_size::k48, icon_size::k64};
@@ -1436,7 +1438,7 @@
 
 TEST_F(WebAppIconManagerTest, CacheNewAppFavicon) {
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   const std::vector<int> sizes_px{gfx::kFaviconSize, icon_size::k48};
   const std::vector<SkColor> colors{SK_ColorBLUE, SK_ColorRED};
@@ -1459,7 +1461,7 @@
       {ui::k100Percent, ui::k200Percent, ui::k300Percent});
 
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // App declares icons precisely matching suspported UI scale factors.
   const std::vector<int> sizes_px{icon_size::k16, icon_size::k32,
@@ -1501,7 +1503,7 @@
       {ui::k100Percent, ui::k200Percent});
 
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // App declares only bigger icons, forcing a downsize to suspported UI scale
   // factors.
@@ -1538,7 +1540,7 @@
       {ui::k100Percent, ui::k200Percent});
 
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   AwaitReadFaviconOnAddingWebApp(std::move(web_app));
 
@@ -1551,7 +1553,7 @@
       {ui::k200Percent, ui::k300Percent});
 
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // App declares only smaller icon and implementations ignore it: no upsizing.
   const std::vector<int> sizes_px{icon_size::k16};
@@ -1572,7 +1574,7 @@
       {ui::k100Percent, ui::k200Percent});
 
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // App declares only one jumbo icon.
   const std::vector<int> sizes_px{icon_size::k512};
@@ -1606,7 +1608,7 @@
       {ui::k100Percent, ui::k300Percent});
 
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // App declares the icon which is ok for 100P but small for 300P.
   const std::vector<int> sizes_px{icon_size::k32};
@@ -1642,7 +1644,7 @@
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
   web_app->SetThemeColor(absl::make_optional(SK_ColorBLUE));
 
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // App declares icons precisely matching suspported UI scale factors.
   const std::vector<int> sizes_px{icon_size::k16, icon_size::k32,
@@ -1688,7 +1690,7 @@
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
   web_app->SetThemeColor(absl::make_optional(SK_ColorGREEN));
 
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // App declares only one jumbo icon.
   const std::vector<int> sizes_px{icon_size::k512};
@@ -1724,7 +1726,7 @@
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
   web_app->SetThemeColor(absl::nullopt);
 
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // Provides only k200Percent icon.
   const std::vector<int> sizes_px{icon_size::k32};
@@ -1755,7 +1757,7 @@
       {ui::k100Percent, ui::k200Percent});
 
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   AwaitReadFaviconMonochromeOnAddingWebApp(std::move(web_app));
 
   gfx::ImageSkia monochrome_image = icon_manager().GetMonochromeFavicon(app_id);
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 4600d04..26553f9 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -38,7 +38,6 @@
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
@@ -54,6 +53,7 @@
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_thread.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "url/origin.h"
@@ -133,13 +133,13 @@
   // WebAppInstallManager and replace this runtime error in
   // WebAppInstallFinalizer with DCHECK(started_).
   if (!started_) {
-    std::move(callback).Run(AppId(),
+    std::move(callback).Run(webapps::AppId(),
                             webapps::InstallResultCode::kWebAppProviderNotReady,
                             OsHooksErrors());
     return;
   }
 
-  ManifestId manifest_id = web_app_info.manifest_id;
+  webapps::ManifestId manifest_id = web_app_info.manifest_id;
   if (manifest_id.is_valid()) {
     CHECK(url::Origin::Create(manifest_id)
               .IsSameOriginWith(url::Origin::Create(web_app_info.start_url)));
@@ -149,7 +149,7 @@
     manifest_id = GenerateManifestIdFromStartUrlOnly(web_app_info.start_url);
   }
 
-  AppId app_id = GenerateAppIdFromManifestId(manifest_id);
+  webapps::AppId app_id = GenerateAppIdFromManifestId(manifest_id);
   OnDidGetWebAppOriginAssociations origin_association_validated_callback =
       base::BindOnce(&WebAppInstallFinalizer::OnOriginAssociationValidated,
                      weak_ptr_factory_.GetWeakPtr(), web_app_info.Clone(),
@@ -171,7 +171,7 @@
     WebAppInstallInfo web_app_info,
     FinalizeOptions options,
     InstallFinalizedCallback callback,
-    AppId app_id,
+    webapps::AppId app_id,
     ScopeExtensions validated_scope_extensions) {
   const WebApp* existing_web_app =
       provider_->registrar_unsafe().GetAppById(app_id);
@@ -286,7 +286,7 @@
   }
 }
 
-bool WebAppInstallFinalizer::CanReparentTab(const AppId& app_id,
+bool WebAppInstallFinalizer::CanReparentTab(const webapps::AppId& app_id,
                                             bool shortcut_created) const {
   // Reparent the web contents into its own window only if that is the
   // app's launch type.
@@ -300,7 +300,7 @@
                                                            shortcut_created);
 }
 
-void WebAppInstallFinalizer::ReparentTab(const AppId& app_id,
+void WebAppInstallFinalizer::ReparentTab(const webapps::AppId& app_id,
                                          bool shortcut_created,
                                          content::WebContents* web_contents) {
   DCHECK(web_contents);
@@ -313,7 +313,7 @@
     InstallFinalizedCallback callback) {
   CHECK(started_);
   CHECK(web_app_info.start_url.is_valid());
-  ManifestId manifest_id = web_app_info.manifest_id;
+  webapps::ManifestId manifest_id = web_app_info.manifest_id;
   if (manifest_id.is_valid()) {
     CHECK(url::Origin::Create(manifest_id)
               .IsSameOriginWith(url::Origin::Create(web_app_info.start_url)));
@@ -325,7 +325,7 @@
   }
   CHECK(manifest_id.is_valid());
 
-  const AppId app_id = GenerateAppIdFromManifestId(manifest_id);
+  const webapps::AppId app_id = GenerateAppIdFromManifestId(manifest_id);
   const WebApp* existing_web_app =
       provider_->registrar_unsafe().GetAppById(app_id);
 
@@ -333,7 +333,7 @@
       existing_web_app->is_from_sync_and_pending_installation() ||
       app_id != existing_web_app->app_id()) {
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback), AppId(),
+        FROM_HERE, base::BindOnce(std::move(callback), webapps::AppId(),
                                   webapps::InstallResultCode::kWebAppDisabled,
                                   OsHooksErrors()));
     return;
@@ -410,7 +410,7 @@
   SetWebAppManifestFields(web_app_info, *web_app,
                           skip_icon_writes_on_download_failure);
 
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   auto write_translations_callback = base::BindOnce(
       &WebAppInstallFinalizer::WriteTranslations,
       weak_ptr_factory_.GetWeakPtr(), app_id, web_app_info.translations);
@@ -441,7 +441,7 @@
 }
 
 void WebAppInstallFinalizer::WriteTranslations(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::flat_map<std::string, blink::Manifest::TranslationItem>&
         translations,
     CommitCallback commit_callback,
@@ -464,7 +464,7 @@
     return;
   }
 
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
 
   ScopedRegistryUpdate update =
       provider_->sync_bridge_unsafe().BeginUpdate(std::move(commit_callback));
@@ -479,13 +479,14 @@
 
 void WebAppInstallFinalizer::OnDatabaseCommitCompletedForInstall(
     InstallFinalizedCallback callback,
-    AppId app_id,
+    webapps::AppId app_id,
     FinalizeOptions finalize_options,
     bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success) {
-    std::move(callback).Run(
-        AppId(), webapps::InstallResultCode::kWriteDataFailed, OsHooksErrors());
+    std::move(callback).Run(webapps::AppId(),
+                            webapps::InstallResultCode::kWriteDataFailed,
+                            OsHooksErrors());
     return;
   }
 
@@ -496,7 +497,8 @@
   // isolation work is done. https://crbug.com/1298130
   if (!web_app) {
     std::move(callback).Run(
-        AppId(), webapps::InstallResultCode::kAppNotInRegistrarAfterCommit,
+        webapps::AppId(),
+        webapps::InstallResultCode::kAppNotInRegistrarAfterCommit,
         OsHooksErrors());
     return;
   }
@@ -588,7 +590,7 @@
 
 void WebAppInstallFinalizer::OnInstallHooksFinished(
     InstallFinalizedCallback callback,
-    AppId app_id,
+    webapps::AppId app_id,
     OsHooksErrors os_hooks_errors) {
   auto joined = std::move(callback).Then(
       base::BindOnce(&WebAppInstallFinalizer::NotifyWebAppInstalledWithOsHooks,
@@ -598,11 +600,12 @@
                         os_hooks_errors);
 }
 
-void WebAppInstallFinalizer::NotifyWebAppInstalledWithOsHooks(AppId app_id) {
+void WebAppInstallFinalizer::NotifyWebAppInstalledWithOsHooks(
+    webapps::AppId app_id) {
   provider_->install_manager().NotifyWebAppInstalledWithOsHooks(app_id);
 }
 
-bool WebAppInstallFinalizer::ShouldUpdateOsHooks(const AppId& app_id) {
+bool WebAppInstallFinalizer::ShouldUpdateOsHooks(const webapps::AppId& app_id) {
 #if BUILDFLAG(IS_CHROMEOS)
   // OS integration should always be enabled on ChromeOS.
   return true;
@@ -615,15 +618,16 @@
 
 void WebAppInstallFinalizer::OnDatabaseCommitCompletedForUpdate(
     InstallFinalizedCallback callback,
-    AppId app_id,
+    webapps::AppId app_id,
     std::string old_name,
     FileHandlerUpdateAction file_handlers_need_os_update,
     const WebAppInstallInfo& web_app_info,
     bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success) {
-    std::move(callback).Run(
-        AppId(), webapps::InstallResultCode::kWriteDataFailed, OsHooksErrors());
+    std::move(callback).Run(webapps::AppId(),
+                            webapps::InstallResultCode::kWriteDataFailed,
+                            OsHooksErrors());
     return;
   }
 
@@ -651,7 +655,7 @@
 
 void WebAppInstallFinalizer::OnUpdateHooksFinished(
     InstallFinalizedCallback callback,
-    AppId app_id,
+    webapps::AppId app_id,
     OsHooksErrors os_hooks_errors) {
   provider_->install_manager().NotifyWebAppManifestUpdated(app_id);
   std::move(callback).Run(
@@ -684,7 +688,7 @@
 }
 
 FileHandlerUpdateAction WebAppInstallFinalizer::GetFileHandlerUpdateAction(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const WebAppInstallInfo& new_web_app_info) {
   if (provider_->registrar_unsafe().GetAppFileHandlerApprovalState(app_id) ==
       ApiApprovalState::kDisallowed) {
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h
index 55e2cc76..d99fa31 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.h
+++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -23,6 +23,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/webapps/browser/install_result_code.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -47,13 +48,13 @@
 class WebAppInstallFinalizer {
  public:
   using InstallFinalizedCallback =
-      base::OnceCallback<void(const AppId& app_id,
+      base::OnceCallback<void(const webapps::AppId& app_id,
                               webapps::InstallResultCode code,
                               OsHooksErrors os_hooks_errors)>;
   using UninstallWebAppCallback =
       base::OnceCallback<void(webapps::UninstallResultCode code)>;
   using RepeatingUninstallCallback =
-      base::RepeatingCallback<void(const AppId& app_id,
+      base::RepeatingCallback<void(const webapps::AppId& app_id,
                                    webapps::UninstallResultCode code)>;
 
   struct FinalizeOptions {
@@ -111,8 +112,9 @@
   virtual void FinalizeUpdate(const WebAppInstallInfo& web_app_info,
                               InstallFinalizedCallback callback);
 
-  bool CanReparentTab(const AppId& app_id, bool shortcut_created) const;
-  void ReparentTab(const AppId& app_id,
+  bool CanReparentTab(const webapps::AppId& app_id,
+                      bool shortcut_created) const;
+  void ReparentTab(const webapps::AppId& app_id,
                    bool shortcut_created,
                    content::WebContents* web_contents);
 
@@ -133,7 +135,7 @@
  private:
   using CommitCallback = base::OnceCallback<void(bool success)>;
 
-  void OnMaybeRegisterOsUninstall(const AppId& app_id,
+  void OnMaybeRegisterOsUninstall(const webapps::AppId& app_id,
                                   WebAppManagement::Type source,
                                   UninstallWebAppCallback callback,
                                   OsHooksErrors os_hooks_errors);
@@ -150,7 +152,7 @@
       bool skip_icon_writes_on_download_failure);
 
   void WriteTranslations(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const base::flat_map<std::string, blink::Manifest::TranslationItem>&
           translations,
       CommitCallback commit_callback,
@@ -163,31 +165,31 @@
   void OnOriginAssociationValidated(WebAppInstallInfo web_app_info,
                                     FinalizeOptions options,
                                     InstallFinalizedCallback callback,
-                                    AppId app_id,
+                                    webapps::AppId app_id,
                                     ScopeExtensions validated_scope_extensions);
 
   void OnDatabaseCommitCompletedForInstall(InstallFinalizedCallback callback,
-                                           AppId app_id,
+                                           webapps::AppId app_id,
                                            FinalizeOptions finalize_options,
                                            bool success);
 
   void OnInstallHooksFinished(InstallFinalizedCallback callback,
-                              AppId app_id,
+                              webapps::AppId app_id,
                               OsHooksErrors os_hooks_errors);
-  void NotifyWebAppInstalledWithOsHooks(AppId app_id);
+  void NotifyWebAppInstalledWithOsHooks(webapps::AppId app_id);
 
-  bool ShouldUpdateOsHooks(const AppId& app_id);
+  bool ShouldUpdateOsHooks(const webapps::AppId& app_id);
 
   void OnDatabaseCommitCompletedForUpdate(
       InstallFinalizedCallback callback,
-      AppId app_id,
+      webapps::AppId app_id,
       std::string old_name,
       FileHandlerUpdateAction file_handlers_need_os_update,
       const WebAppInstallInfo& web_app_info,
       bool success);
 
   void OnUpdateHooksFinished(InstallFinalizedCallback callback,
-                             AppId app_id,
+                             webapps::AppId app_id,
                              OsHooksErrors os_hooks_errors);
 
   // Returns a value indicating whether the file handlers registered with the OS
@@ -195,7 +197,7 @@
   // does this optimization exist when other OS hooks don't have similar
   // optimizations?
   FileHandlerUpdateAction GetFileHandlerUpdateAction(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const WebAppInstallInfo& new_web_app_info);
 
   const raw_ptr<Profile> profile_;
diff --git a/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc b/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
index 2e085ef..d8b7ea5 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
@@ -51,7 +51,7 @@
 namespace {
 
 struct FinalizeInstallResult {
-  AppId installed_app_id;
+  webapps::AppId installed_app_id;
   webapps::InstallResultCode code;
   OsHooksErrors os_hooks_errors;
 };
@@ -64,7 +64,7 @@
     install_manager_observation_.Observe(install_manager);
   }
 
-  void OnWebAppManifestUpdated(const AppId& app_id) override {
+  void OnWebAppManifestUpdated(const webapps::AppId& app_id) override {
     web_app_manifest_updated_called_ = true;
   }
 
@@ -127,7 +127,7 @@
     base::RunLoop run_loop;
     finalizer().FinalizeInstall(
         info, options,
-        base::BindLambdaForTesting([&](const AppId& installed_app_id,
+        base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id,
                                        webapps::InstallResultCode code,
                                        OsHooksErrors os_hooks_errors) {
           result.installed_app_id = installed_app_id;
@@ -201,7 +201,7 @@
   {
     finalizer().FinalizeInstall(
         *info1, options,
-        base::BindLambdaForTesting([&](const AppId& installed_app_id,
+        base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id,
                                        webapps::InstallResultCode code,
                                        OsHooksErrors os_hooks_errors) {
           EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
@@ -219,7 +219,7 @@
   {
     finalizer().FinalizeInstall(
         *info2, options,
-        base::BindLambdaForTesting([&](const AppId& installed_app_id,
+        base::BindLambdaForTesting([&](const webapps::AppId& installed_app_id,
                                        webapps::InstallResultCode code,
                                        OsHooksErrors os_hooks_errors) {
           EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall, code);
@@ -260,7 +260,7 @@
       webapps::WebappInstallSource::EXTERNAL_POLICY);
 
   FinalizeInstallResult result = AwaitFinalizeInstall(*info, options);
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode,
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode,
                          OsHooksErrors>
       update_future;
   finalizer().FinalizeUpdate(*info, update_future.GetCallback());
@@ -484,7 +484,7 @@
   info->file_handlers =
       CreateFileHandlersFromManifest(file_handlers, info->start_url);
 
-  base::test::TestFuture<const AppId&, webapps::InstallResultCode,
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode,
                          OsHooksErrors>
       update_future;
   finalizer().FinalizeUpdate(*info, update_future.GetCallback());
diff --git a/chrome/browser/web_applications/web_app_install_info.cc b/chrome/browser/web_applications/web_app_install_info.cc
index 659e31d..95a3ed8 100644
--- a/chrome/browser/web_applications/web_app_install_info.cc
+++ b/chrome/browser/web_applications/web_app_install_info.cc
@@ -288,12 +288,12 @@
 
 WebAppInstallInfo::WebAppInstallInfo() = default;
 
-WebAppInstallInfo::WebAppInstallInfo(const web_app::ManifestId& manifest_id)
+WebAppInstallInfo::WebAppInstallInfo(const webapps::ManifestId& manifest_id)
     : manifest_id(manifest_id) {
   CHECK(manifest_id.is_valid());
 }
 
-WebAppInstallInfo::WebAppInstallInfo(const web_app::ManifestId& manifest_id,
+WebAppInstallInfo::WebAppInstallInfo(const webapps::ManifestId& manifest_id,
                                      const GURL& start_url)
     : manifest_id(manifest_id), start_url(start_url) {
   CHECK(manifest_id.is_valid());
diff --git a/chrome/browser/web_applications/web_app_install_info.h b/chrome/browser/web_applications/web_app_install_info.h
index 74294ef..61e6d39 100644
--- a/chrome/browser/web_applications/web_app_install_info.h
+++ b/chrome/browser/web_applications/web_app_install_info.h
@@ -23,6 +23,7 @@
 #include "components/services/app_service/public/cpp/protocol_handler_info.h"
 #include "components/services/app_service/public/cpp/share_target.h"
 #include "components/services/app_service/public/cpp/url_handler_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
@@ -205,11 +206,11 @@
   // TODO(b/280862254): Remove this constructor to force users to use specify
   // both the manifest_id and start_url (or call
   // `CreateWithStartUrlForTesting`).
-  explicit WebAppInstallInfo(const web_app::ManifestId& manifest_id);
+  explicit WebAppInstallInfo(const webapps::ManifestId& manifest_id);
 
   // The `manifest_id` and the `start_url` MUST be valid. The `manifest_id` MUST
   // be created properly, and cannot contain refs (e.g. '#refs').
-  WebAppInstallInfo(const web_app::ManifestId& manifest_id,
+  WebAppInstallInfo(const webapps::ManifestId& manifest_id,
                     const GURL& start_url);
 
   // Deleted to prevent accidental copying. Use Clone() to deep copy explicitly.
@@ -226,7 +227,7 @@
   // TODO(b/280862254): After the manifest id constructor is required, this can
   // be guaranteed to be valid & non-empty.
   // https://www.w3.org/TR/appmanifest/#id-member
-  web_app::ManifestId manifest_id;
+  webapps::ManifestId manifest_id;
 
   // Title of the application.
   std::u16string title;
@@ -380,7 +381,7 @@
   // Id of the app that called the SUB_APP API to install this app. This field
   // is only used when the app is installed as a sub app through the SUB_APP
   // API.
-  absl::optional<web_app::AppId> parent_app_id;
+  absl::optional<webapps::AppId> parent_app_id;
 
   // A list of additional terms to use when matching this app against
   // identifiers in admin policies (for shelf pinning, default file handlers,
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc
index 63ae0505..2147bfb6 100644
--- a/chrome/browser/web_applications/web_app_install_manager.cc
+++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -113,7 +113,7 @@
   observers_.RemoveObserver(observer);
 }
 
-void WebAppInstallManager::NotifyWebAppInstalled(const AppId& app_id) {
+void WebAppInstallManager::NotifyWebAppInstalled(const webapps::AppId& app_id) {
   for (WebAppInstallManagerObserver& observer : observers_) {
     observer.OnWebAppInstalled(app_id);
   }
@@ -122,33 +122,36 @@
 }
 
 void WebAppInstallManager::NotifyWebAppInstalledWithOsHooks(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   for (WebAppInstallManagerObserver& obs : observers_) {
     obs.OnWebAppInstalledWithOsHooks(app_id);
   }
 }
 
-void WebAppInstallManager::NotifyWebAppSourceRemoved(const AppId& app_id) {
+void WebAppInstallManager::NotifyWebAppSourceRemoved(
+    const webapps::AppId& app_id) {
   for (WebAppInstallManagerObserver& observer : observers_) {
     observer.OnWebAppSourceRemoved(app_id);
   }
 }
 
 void WebAppInstallManager::NotifyWebAppUninstalled(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     webapps::WebappUninstallSource uninstall_source) {
   for (WebAppInstallManagerObserver& observer : observers_) {
     observer.OnWebAppUninstalled(app_id, uninstall_source);
   }
 }
 
-void WebAppInstallManager::NotifyWebAppManifestUpdated(const AppId& app_id) {
+void WebAppInstallManager::NotifyWebAppManifestUpdated(
+    const webapps::AppId& app_id) {
   for (WebAppInstallManagerObserver& observer : observers_) {
     observer.OnWebAppManifestUpdated(app_id);
   }
 }
 
-void WebAppInstallManager::NotifyWebAppWillBeUninstalled(const AppId& app_id) {
+void WebAppInstallManager::NotifyWebAppWillBeUninstalled(
+    const webapps::AppId& app_id) {
   for (WebAppInstallManagerObserver& observer : observers_) {
     observer.OnWebAppWillBeUninstalled(app_id);
   }
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h
index cb69989..23c9b29 100644
--- a/chrome/browser/web_applications/web_app_install_manager.h
+++ b/chrome/browser/web_applications/web_app_install_manager.h
@@ -15,6 +15,7 @@
 #include "base/values.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 class Profile;
 
@@ -36,14 +37,14 @@
   virtual void AddObserver(WebAppInstallManagerObserver* observer);
   virtual void RemoveObserver(WebAppInstallManagerObserver* observer);
 
-  virtual void NotifyWebAppInstalled(const AppId& app_id);
-  virtual void NotifyWebAppInstalledWithOsHooks(const AppId& app_id);
-  virtual void NotifyWebAppSourceRemoved(const AppId& app_id);
+  virtual void NotifyWebAppInstalled(const webapps::AppId& app_id);
+  virtual void NotifyWebAppInstalledWithOsHooks(const webapps::AppId& app_id);
+  virtual void NotifyWebAppSourceRemoved(const webapps::AppId& app_id);
   virtual void NotifyWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source);
-  virtual void NotifyWebAppManifestUpdated(const AppId& app_id);
-  virtual void NotifyWebAppWillBeUninstalled(const AppId& app_id);
+  virtual void NotifyWebAppManifestUpdated(const webapps::AppId& app_id);
+  virtual void NotifyWebAppWillBeUninstalled(const webapps::AppId& app_id);
   virtual void NotifyWebAppInstallManagerDestroyed();
 
   // Collects icon read/write errors (unbounded) if the |kRecordWebAppDebugInfo|
diff --git a/chrome/browser/web_applications/web_app_install_manager_observer.h b/chrome/browser/web_applications/web_app_install_manager_observer.h
index 473ba47..35683a4 100644
--- a/chrome/browser/web_applications/web_app_install_manager_observer.h
+++ b/chrome/browser/web_applications/web_app_install_manager_observer.h
@@ -8,38 +8,39 @@
 #include "base/observer_list_types.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
 class WebAppInstallManagerObserver : public base::CheckedObserver {
  public:
   // Called after a web app is installed.
-  virtual void OnWebAppInstalled(const AppId& app_id) {}
+  virtual void OnWebAppInstalled(const webapps::AppId& app_id) {}
 
   // Called when OS hooks installation is finished during web app installation.
-  virtual void OnWebAppInstalledWithOsHooks(const AppId& app_id) {}
+  virtual void OnWebAppInstalledWithOsHooks(const webapps::AppId& app_id) {}
 
   // Called before a web app is uninstalled, before the uninstallation process
   // begins. |app_id| is still registered in the WebAppRegistrar, and OS hooks
   // have not yet been uninstalled.
-  virtual void OnWebAppWillBeUninstalled(const AppId& app_id) {}
+  virtual void OnWebAppWillBeUninstalled(const webapps::AppId& app_id) {}
 
   // Called after a web app is uninstalled. |app_id| is no longer registered in
   // the WebAppRegistrar, all OS hooks are uninstalled, and icons have been
   // deleted.
   virtual void OnWebAppUninstalled(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) {}
 
   // Called when any field of a web app's local manifest is updated.
-  virtual void OnWebAppManifestUpdated(const AppId& app_id) {}
+  virtual void OnWebAppManifestUpdated(const webapps::AppId& app_id) {}
 
   // Called when the WebAppInstallManager is about to be destroyed.
   virtual void OnWebAppInstallManagerDestroyed() {}
 
   // Called after web app's install source is removed, currently only used by
   // tests.
-  virtual void OnWebAppSourceRemoved(const AppId& app_id) {}
+  virtual void OnWebAppSourceRemoved(const webapps::AppId& app_id) {}
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_params.h b/chrome/browser/web_applications/web_app_install_params.h
index 983a6c3..05d4cd1 100644
--- a/chrome/browser/web_applications/web_app_install_params.h
+++ b/chrome/browser/web_applications/web_app_install_params.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
@@ -31,10 +32,10 @@
 
 // |app_id| may be empty on failure.
 using OnceInstallCallback =
-    base::OnceCallback<void(const AppId& app_id,
+    base::OnceCallback<void(const webapps::AppId& app_id,
                             webapps::InstallResultCode code)>;
 using OnceUninstallCallback =
-    base::OnceCallback<void(const AppId& app_id, bool uninstalled)>;
+    base::OnceCallback<void(const webapps::AppId& app_id, bool uninstalled)>;
 
 // Callback used to indicate whether a user has accepted the installation of a
 // web app.
diff --git a/chrome/browser/web_applications/web_app_install_utils.cc b/chrome/browser/web_applications/web_app_install_utils.cc
index 3a45025..b3313a5 100644
--- a/chrome/browser/web_applications/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/web_app_install_utils.cc
@@ -1255,7 +1255,7 @@
 }
 
 void MaybeDisableOsIntegration(const WebAppRegistrar* app_registrar,
-                               const AppId& app_id,
+                               const webapps::AppId& app_id,
                                InstallOsHooksOptions* options) {
 #if !BUILDFLAG(IS_CHROMEOS)  // Deeper OS integration is expected on ChromeOS.
   DCHECK(app_registrar);
diff --git a/chrome/browser/web_applications/web_app_install_utils.h b/chrome/browser/web_applications/web_app_install_utils.h
index 70ce4aab26..b6eba366 100644
--- a/chrome/browser/web_applications/web_app_install_utils.h
+++ b/chrome/browser/web_applications/web_app_install_utils.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 
 class GURL;
@@ -137,7 +138,7 @@
 // Possibly updates |options| to disable OS-integrations based on the
 // configuration of the given app.
 void MaybeDisableOsIntegration(const WebAppRegistrar* app_registrar,
-                               const AppId& app_id,
+                               const webapps::AppId& app_id,
                                InstallOsHooksOptions* options);
 
 // Update |web_app_info| using |install_params|.
diff --git a/chrome/browser/web_applications/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/web_app_install_utils_unittest.cc
index 952ec73..70ec16a4e 100644
--- a/chrome/browser/web_applications/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_utils_unittest.cc
@@ -1687,7 +1687,7 @@
   // removed source: kPolicy
   // check web_app.CanUserUninstallWebApp is false
   // check RegisterWebAppOsUninstallation is called
-  const AppId app_id = "test";
+  const webapps::AppId app_id = "test";
   testing::StrictMock<MockOsIntegrationManager> manager;
   // InstallOsHooks from MaybeRegisterOsUninstall
   // sets only kUninstallationViaOsSettings that will async call from
@@ -1726,7 +1726,7 @@
   // removed source: kSync
   // check web_app.CanUserUninstallWebApp is true
   // check RegisterWebAppOsUninstallation is not called
-  const AppId app_id = "test";
+  const webapps::AppId app_id = "test";
   testing::StrictMock<MockOsIntegrationManager> manager;
   // InstallOsHooks from MaybeRegisterOsUninstall
   // sets only kUninstallationViaOsSettings that will async call from
@@ -1766,7 +1766,7 @@
   // added source: kPolicy
   // check web_app.CanUserUninstallWebApp is false
   // check UnregisterWebAppOsUninstallation is called
-  const AppId app_id = "test";
+  const webapps::AppId app_id = "test";
   testing::StrictMock<MockOsIntegrationManager> manager;
   // InstallOsHooks from MaybeRegisterOsUninstall
   // sets only kUninstallationViaOsSettings that will async call from
@@ -1795,7 +1795,7 @@
   // added source: kSync
   // check web_app.CanUserUninstallWebApp is true
   // check UnregisterWebAppOsUninstallation is not called
-  const AppId app_id = "test";
+  const webapps::AppId app_id = "test";
   testing::StrictMock<MockOsIntegrationManager> manager;
   // InstallOsHooks from MaybeRegisterOsUninstall
   // sets only kUninstallationViaOsSettings that will async call from
@@ -1830,7 +1830,7 @@
   web_app_info.background_color = SK_ColorMAGENTA;
   web_app_info.dark_mode_background_color = SK_ColorBLACK;
 
-  const AppId app_id =
+  const webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, web_app_info.start_url);
   auto web_app = std::make_unique<WebApp>(app_id);
   SetWebAppManifestFields(web_app_info, *web_app);
@@ -1864,7 +1864,7 @@
   web_app_info.scope = web_app_info.start_url.GetWithoutFilename();
   web_app_info.title = u"App Name";
 
-  const AppId app_id =
+  const webapps::AppId app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, web_app_info.start_url);
   auto web_app = std::make_unique<WebApp>(app_id);
 
diff --git a/chrome/browser/web_applications/web_app_internals_browsertest.cc b/chrome/browser/web_applications/web_app_internals_browsertest.cc
index 88bcc81..6a0748d1 100644
--- a/chrome/browser/web_applications/web_app_internals_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_internals_browsertest.cc
@@ -86,22 +86,22 @@
     WebAppControllerBrowserTest::SetUpOnMainThread();
   }
 
-  AppId InstallWebApp(const GURL& app_url) {
+  webapps::AppId InstallWebApp(const GURL& app_url) {
     EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), app_url));
 
-    AppId app_id;
+    webapps::AppId app_id;
     base::RunLoop run_loop;
     GetProvider().scheduler().FetchManifestAndInstall(
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
         browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
         /*bypass_service_worker_check=*/false,
         base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting(
-            [&](const AppId& new_app_id, webapps::InstallResultCode code) {
-              EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
-              app_id = new_app_id;
-              run_loop.Quit();
-            }),
+        base::BindLambdaForTesting([&](const webapps::AppId& new_app_id,
+                                       webapps::InstallResultCode code) {
+          EXPECT_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
+          app_id = new_app_id;
+          run_loop.Quit();
+        }),
         /*use_fallback=*/true);
 
     run_loop.Run();
@@ -145,7 +145,7 @@
   OverrideHttpRequest(embedded_test_server()->GetURL("/banners/bad_icon.png"),
                       net::HTTP_NOT_FOUND);
 
-  AppId app_id = InstallWebApp(embedded_test_server()->GetURL(
+  webapps::AppId app_id = InstallWebApp(embedded_test_server()->GetURL(
       "/banners/manifest_test_page.html?manifest=manifest_bad_icon.json"));
 
   const WebApp* web_app = GetProvider().registrar_unsafe().GetAppById(app_id);
diff --git a/chrome/browser/web_applications/web_app_launch_params.h b/chrome/browser/web_applications/web_app_launch_params.h
index b9794ae..41212d4 100644
--- a/chrome/browser/web_applications/web_app_launch_params.h
+++ b/chrome/browser/web_applications/web_app_launch_params.h
@@ -9,6 +9,7 @@
 
 #include "base/files/file_path.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "url/gurl.h"
 
 namespace web_app {
@@ -30,7 +31,7 @@
   bool started_new_navigation = true;
 
   // The app being launched, used for scope validation.
-  AppId app_id;
+  webapps::AppId app_id;
 
   // The URL the web app was launched with. Note that redirects may cause us to
   // enqueue in a different URL, we still report the original launch target URL
diff --git a/chrome/browser/web_applications/web_app_launch_queue.cc b/chrome/browser/web_applications/web_app_launch_queue.cc
index ab058efa..4589453 100644
--- a/chrome/browser/web_applications/web_app_launch_queue.cc
+++ b/chrome/browser/web_applications/web_app_launch_queue.cc
@@ -152,7 +152,7 @@
   last_sent_queued_launch_params_.reset();
 }
 
-const AppId* WebAppLaunchQueue::GetPendingLaunchAppId() const {
+const webapps::AppId* WebAppLaunchQueue::GetPendingLaunchAppId() const {
   if (queue_.empty())
     return nullptr;
   return &(queue_.front().app_id);
diff --git a/chrome/browser/web_applications/web_app_launch_queue.h b/chrome/browser/web_applications/web_app_launch_queue.h
index bec924b..a17e0013 100644
--- a/chrome/browser/web_applications/web_app_launch_queue.h
+++ b/chrome/browser/web_applications/web_app_launch_queue.h
@@ -10,6 +10,7 @@
 #include "base/memory/raw_ref.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_launch_params.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents_observer.h"
 
 class GURL;
@@ -51,7 +52,7 @@
 
   void Enqueue(WebAppLaunchParams launch_params);
 
-  const AppId* GetPendingLaunchAppId() const;
+  const webapps::AppId* GetPendingLaunchAppId() const;
 
  private:
   bool IsInScope(const WebAppLaunchParams& launch_params,
diff --git a/chrome/browser/web_applications/web_app_logging.cc b/chrome/browser/web_applications/web_app_logging.cc
index 6c4c732..712d299 100644
--- a/chrome/browser/web_applications/web_app_logging.cc
+++ b/chrome/browser/web_applications/web_app_logging.cc
@@ -7,12 +7,12 @@
 #include <string>
 
 #include "base/feature_list.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
 #include "chrome/common/chrome_features.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 #include "net/http/http_status_code.h"
 
 namespace web_app {
@@ -70,10 +70,11 @@
   LogErrorObject(stage, url, std::move(url_loader_error));
 }
 
-void InstallErrorLogEntry::LogExpectedAppIdError(const char* stage,
-                                                 const std::string& url,
-                                                 const AppId& app_id,
-                                                 const AppId& expected_app_id) {
+void InstallErrorLogEntry::LogExpectedAppIdError(
+    const char* stage,
+    const std::string& url,
+    const webapps::AppId& app_id,
+    const webapps::AppId& expected_app_id) {
   if (!error_dict_)
     return;
 
diff --git a/chrome/browser/web_applications/web_app_logging.h b/chrome/browser/web_applications/web_app_logging.h
index 15a1d61..3ae5a47 100644
--- a/chrome/browser/web_applications/web_app_logging.h
+++ b/chrome/browser/web_applications/web_app_logging.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -41,8 +42,8 @@
                          WebAppUrlLoader::Result result);
   void LogExpectedAppIdError(const char* stage,
                              const std::string& url,
-                             const AppId& app_id,
-                             const AppId& expected_app_id);
+                             const webapps::AppId& app_id,
+                             const webapps::AppId& expected_app_id);
   void LogDownloadedIconsErrors(
       const WebAppInstallInfo& web_app_info,
       IconsDownloadedResult icons_downloaded_result,
diff --git a/chrome/browser/web_applications/web_app_notifications_interactive_uitest.cc b/chrome/browser/web_applications/web_app_notifications_interactive_uitest.cc
index b257114..c7a81c3 100644
--- a/chrome/browser/web_applications/web_app_notifications_interactive_uitest.cc
+++ b/chrome/browser/web_applications/web_app_notifications_interactive_uitest.cc
@@ -43,7 +43,7 @@
     return *display_service_tester_;
   }
 
-  void SetAppBrowserForAppId(const AppId& app_id) {
+  void SetAppBrowserForAppId(const webapps::AppId& app_id) {
     Browser* app_browser = FindWebAppBrowser(profile(), app_id);
     ASSERT_TRUE(app_browser);
     app_browser_ = app_browser;
@@ -110,7 +110,7 @@
   const GURL app_url =
       https_server()->GetURL("/web_app_notifications/index.html");
 
-  const AppId app_id = InstallWebAppFromPage(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromPage(browser(), app_url);
   // The installation opens a new Browser window: |user_display_mode| is
   // kStandalone.
   SetAppBrowserForAppId(app_id);
@@ -191,7 +191,7 @@
   const GURL app_url =
       https_server()->GetURL("/web_app_notifications/index.html");
 
-  const AppId app_id = InstallWebAppFromPage(browser(), app_url);
+  const webapps::AppId app_id = InstallWebAppFromPage(browser(), app_url);
   // The installation opens a new Browser window: |user_display_mode| is
   // kStandalone.
   SetAppBrowserForAppId(app_id);
diff --git a/chrome/browser/web_applications/web_app_pref_migration_browsertest.cc b/chrome/browser/web_applications/web_app_pref_migration_browsertest.cc
index 98df66fa..6401a779d 100644
--- a/chrome/browser/web_applications/web_app_pref_migration_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_pref_migration_browsertest.cc
@@ -11,13 +11,13 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_prefs_utils.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/test/browser_test.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
@@ -44,9 +44,9 @@
 };
 
 IN_PROC_BROWSER_TEST_F(WebAppPrefMigrationBrowserTest, PRE_Migration) {
-  AppId app_id = test::InstallDummyWebApp(browser()->profile(), "Test app 1",
-                                          GURL("https://example.com/app_1"),
-                                          webapps::WebappInstallSource::ARC);
+  webapps::AppId app_id = test::InstallDummyWebApp(
+      browser()->profile(), "Test app 1", GURL("https://example.com/app_1"),
+      webapps::WebappInstallSource::ARC);
   // New installs should no longer write into prefs.
   EXPECT_FALSE(GetWebAppInstallSourceDeprecated(
       browser()->profile()->GetPrefs(), app_id));
@@ -74,7 +74,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppPrefMigrationBrowserTest, Migration) {
-  AppId app_id = registrar().GetAppIds()[0];
+  webapps::AppId app_id = registrar().GetAppIds()[0];
   absl::optional<int> install_source = GetWebAppInstallSourceDeprecated(
       browser()->profile()->GetPrefs(), app_id);
   ASSERT_FALSE(install_source);
diff --git a/chrome/browser/web_applications/web_app_prefs_utils.cc b/chrome/browser/web_applications/web_app_prefs_utils.cc
index 7e072e21..9a9ac23 100644
--- a/chrome/browser/web_applications/web_app_prefs_utils.cc
+++ b/chrome/browser/web_applications/web_app_prefs_utils.cc
@@ -26,7 +26,7 @@
 const char kLatestWebAppInstallSource[] = "latest_web_app_install_source";
 
 const base::Value::Dict* GetWebAppDictionary(const PrefService* pref_service,
-                                             const AppId& app_id) {
+                                             const webapps::AppId& app_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const base::Value::Dict& web_apps_prefs =
       pref_service->GetDict(prefs::kWebAppsPreferences);
@@ -36,7 +36,7 @@
 
 base::Value::Dict& UpdateWebAppDictionary(
     ScopedDictPrefUpdate& web_apps_prefs_update,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   return *web_apps_prefs_update->EnsureDict(app_id);
 }
@@ -62,14 +62,15 @@
 void RemoveEmptyWebAppPrefs(PrefService* pref_service) {
   ScopedDictPrefUpdate update(pref_service, prefs::kWebAppsPreferences);
 
-  std::vector<AppId> apps_to_remove;
+  std::vector<webapps::AppId> apps_to_remove;
   for (const auto [app_id, dict] : *update) {
     if (dict.is_dict() && dict.GetDict().empty())
       apps_to_remove.push_back(app_id);
   }
 
-  for (const AppId& app_id : apps_to_remove)
+  for (const webapps::AppId& app_id : apps_to_remove) {
     update->Remove(app_id);
+  }
 }
 
 }  // namespace
@@ -131,7 +132,7 @@
 }
 
 absl::optional<int> GetIntWebAppPref(const PrefService* pref_service,
-                                     const AppId& app_id,
+                                     const webapps::AppId& app_id,
                                      base::StringPiece path) {
   const base::Value::Dict* web_app_prefs =
       GetWebAppDictionary(pref_service, app_id);
@@ -141,7 +142,7 @@
 }
 
 void UpdateIntWebAppPref(PrefService* pref_service,
-                         const AppId& app_id,
+                         const webapps::AppId& app_id,
                          base::StringPiece path,
                          int value) {
   ScopedDictPrefUpdate update(pref_service, prefs::kWebAppsPreferences);
@@ -151,7 +152,7 @@
 }
 
 absl::optional<base::Time> GetTimeWebAppPref(const PrefService* pref_service,
-                                             const AppId& app_id,
+                                             const webapps::AppId& app_id,
                                              base::StringPiece path) {
   if (const auto* web_app_prefs = GetWebAppDictionary(pref_service, app_id)) {
     if (auto* value = web_app_prefs->FindByDottedPath(path))
@@ -162,7 +163,7 @@
 }
 
 void UpdateTimeWebAppPref(PrefService* pref_service,
-                          const AppId& app_id,
+                          const webapps::AppId& app_id,
                           base::StringPiece path,
                           base::Time value) {
   ScopedDictPrefUpdate update(pref_service, prefs::kWebAppsPreferences);
@@ -172,7 +173,7 @@
 }
 
 void RemoveWebAppPref(PrefService* pref_service,
-                      const AppId& app_id,
+                      const webapps::AppId& app_id,
                       base::StringPiece path) {
   ScopedDictPrefUpdate update(pref_service, prefs::kWebAppsPreferences);
 
@@ -180,23 +181,25 @@
   web_app_prefs.RemoveByDottedPath(path);
 }
 
-absl::optional<int> GetWebAppInstallSourceDeprecated(PrefService* prefs,
-                                                     const AppId& app_id) {
+absl::optional<int> GetWebAppInstallSourceDeprecated(
+    PrefService* prefs,
+    const webapps::AppId& app_id) {
   absl::optional<int> value =
       GetIntWebAppPref(prefs, app_id, kLatestWebAppInstallSource);
   return value;
 }
 
-std::map<AppId, int> TakeAllWebAppInstallSources(PrefService* pref_service) {
+std::map<webapps::AppId, int> TakeAllWebAppInstallSources(
+    PrefService* pref_service) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const base::Value* web_apps_prefs =
       pref_service->GetUserPrefValue(prefs::kWebAppsPreferences);
   if (!web_apps_prefs || !web_apps_prefs->is_dict())
     return {};
 
-  std::map<AppId, int> return_value;
+  std::map<webapps::AppId, int> return_value;
   for (auto item : web_apps_prefs->GetDict()) {
-    const AppId& app_id = item.first;
+    const webapps::AppId& app_id = item.first;
     absl::optional<int> install_source =
         item.second.GetDict().FindInt(kLatestWebAppInstallSource);
     if (install_source)
@@ -212,7 +215,7 @@
 }
 
 void RecordInstallIphIgnored(PrefService* pref_service,
-                             const AppId& app_id,
+                             const webapps::AppId& app_id,
                              base::Time time) {
   absl::optional<int> ignored_count =
       GetIntWebAppPref(pref_service, app_id, kIphIgnoreCount);
@@ -227,7 +230,8 @@
   update->Set(kIphLastIgnoreTime, base::TimeToValue(time));
 }
 
-void RecordInstallIphInstalled(PrefService* pref_service, const AppId& app_id) {
+void RecordInstallIphInstalled(PrefService* pref_service,
+                               const webapps::AppId& app_id) {
   // The ignored count is meant to track consecutive occurrences of the user
   // ignoring IPH, to help determine when IPH should be muted. Therefore
   // resetting ignored count on successful install.
@@ -237,7 +241,7 @@
   update->Set(kIphIgnoreCount, 0);
 }
 
-bool ShouldShowIph(PrefService* pref_service, const AppId& app_id) {
+bool ShouldShowIph(PrefService* pref_service, const webapps::AppId& app_id) {
   // Do not show IPH if the user ignored the last N+ promos for this app.
   int app_ignored_count =
       GetIntWebAppPref(pref_service, app_id, kIphIgnoreCount).value_or(0);
@@ -274,7 +278,7 @@
 const char kMLPromotionGuardrailBlockReason[] = "ML_guardrail_blocked";
 
 void RecordMlInstallIgnored(PrefService* pref_service,
-                            const AppId& app_id,
+                            const webapps::AppId& app_id,
                             base::Time time) {
   CHECK(pref_service);
 
@@ -295,7 +299,7 @@
 }
 
 void RecordMlInstallDismissed(PrefService* pref_service,
-                              const AppId& app_id,
+                              const webapps::AppId& app_id,
                               base::Time time) {
   CHECK(pref_service);
 
@@ -316,7 +320,7 @@
 }
 
 void RecordMlInstallAccepted(PrefService* pref_service,
-                             const AppId& app_id,
+                             const webapps::AppId& app_id,
                              base::Time time) {
   // The ignored count is meant to track consecutive occurrences of the user
   // ignoring ML install, to help determine when ML install should be muted.
@@ -329,7 +333,7 @@
 }
 
 bool IsMlPromotionBlockedByHistoryGuardrail(PrefService* pref_service,
-                                            const AppId& app_id) {
+                                            const webapps::AppId& app_id) {
   constexpr int kMuteMlInstallAfterConsecutiveAppSpecificNotAcceptedCount = 3;
   constexpr int kMuteMlInstallAfterIgnoreForDays = 2;
   constexpr int kMuteMlInstallAfterDismissForDays = 14;
diff --git a/chrome/browser/web_applications/web_app_prefs_utils.h b/chrome/browser/web_applications/web_app_prefs_utils.h
index 1be50dc..ae201a5 100644
--- a/chrome/browser/web_applications/web_app_prefs_utils.h
+++ b/chrome/browser/web_applications/web_app_prefs_utils.h
@@ -10,6 +10,7 @@
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class PrefService;
@@ -25,49 +26,51 @@
 extern const char kIphLastIgnoreTime[];
 
 absl::optional<int> GetIntWebAppPref(const PrefService* pref_service,
-                                     const AppId& app_id,
+                                     const webapps::AppId& app_id,
                                      base::StringPiece path);
 
 void UpdateIntWebAppPref(PrefService* pref_service,
-                         const AppId& app_id,
+                         const webapps::AppId& app_id,
                          base::StringPiece path,
                          int value);
 
 absl::optional<base::Time> GetTimeWebAppPref(const PrefService* pref_service,
-                                             const AppId& app_id,
+                                             const webapps::AppId& app_id,
                                              base::StringPiece path);
 
 void UpdateTimeWebAppPref(PrefService* pref_service,
-                          const AppId& app_id,
+                          const webapps::AppId& app_id,
                           base::StringPiece path,
                           base::Time value);
 
 void RemoveWebAppPref(PrefService* pref_service,
-                      const AppId& app_id,
+                      const webapps::AppId& app_id,
                       base::StringPiece path);
 
 void WebAppPrefsUtilsRegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry);
 
 // Deprecated. See crbug.com/1287292
-absl::optional<int> GetWebAppInstallSourceDeprecated(PrefService* prefs,
-                                                     const AppId& app_id);
+absl::optional<int> GetWebAppInstallSourceDeprecated(
+    PrefService* prefs,
+    const webapps::AppId& app_id);
 
 // Looks up all install sources in the web apps prefs dictionary and returns
 // them as a map. Also deletes the values from the dictionary. Used for
 // migration to the WebApp database. This should be safe to delete one year
 // after 02-2022.
-std::map<AppId, int> TakeAllWebAppInstallSources(PrefService* prefs);
+std::map<webapps::AppId, int> TakeAllWebAppInstallSources(PrefService* prefs);
 
 void RecordInstallIphIgnored(PrefService* pref_service,
-                             const AppId& app_id,
+                             const webapps::AppId& app_id,
                              base::Time time);
 
-void RecordInstallIphInstalled(PrefService* pref_service, const AppId& app_id);
+void RecordInstallIphInstalled(PrefService* pref_service,
+                               const webapps::AppId& app_id);
 
 // Returns whether Web App Install In Product Help should be shown based on
 // previous interactions with this promo.
-bool ShouldShowIph(PrefService* pref_service, const AppId& app_id);
+bool ShouldShowIph(PrefService* pref_service, const webapps::AppId& app_id);
 
 extern const char kLastTimeMlInstallIgnored[];
 extern const char kLastTimeMlInstallDismissed[];
@@ -77,18 +80,18 @@
 // The user has ignored the installation dialog and it went away due to
 // another interaction (e.g. the tab was changed, page navigated, etc).
 void RecordMlInstallIgnored(PrefService* pref_service,
-                            const AppId& app_id,
+                            const webapps::AppId& app_id,
                             base::Time time);
 // The user has taken active action on the dialog to make it go away.
 void RecordMlInstallDismissed(PrefService* pref_service,
-                              const AppId& app_id,
+                              const webapps::AppId& app_id,
                               base::Time time);
 void RecordMlInstallAccepted(PrefService* pref_service,
-                             const AppId& app_id,
+                             const webapps::AppId& app_id,
                              base::Time time);
 
 bool IsMlPromotionBlockedByHistoryGuardrail(PrefService* pref_service,
-                                            const AppId& app_id);
+                                            const webapps::AppId& app_id);
 
 }  // namespace web_app
 
diff --git a/chrome/browser/web_applications/web_app_prefs_utils_unittest.cc b/chrome/browser/web_applications/web_app_prefs_utils_unittest.cc
index 50e451bda..9915dbd2 100644
--- a/chrome/browser/web_applications/web_app_prefs_utils_unittest.cc
+++ b/chrome/browser/web_applications/web_app_prefs_utils_unittest.cc
@@ -12,10 +12,10 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_task_environment.h"
@@ -24,8 +24,8 @@
 namespace web_app {
 
 namespace {
-const AppId app_id = "test_app";
-const AppId app_id_2 = "test_app_2";
+const webapps::AppId app_id = "test_app";
+const webapps::AppId app_id_2 = "test_app_2";
 const base::Time time_before_app_mute =
     base::Time::Now() - base::Days(kIphAppSpecificMuteTimeSpanDays) -
     base::Hours(1);
@@ -152,7 +152,7 @@
   EXPECT_TRUE(GetWebAppInstallSourceDeprecated(prefs(), "app2"));
   EXPECT_TRUE(GetWebAppInstallSourceDeprecated(prefs(), "app3"));
 
-  std::map<AppId, int> values = TakeAllWebAppInstallSources(prefs());
+  std::map<webapps::AppId, int> values = TakeAllWebAppInstallSources(prefs());
 
   // Verify the returned map.
   ASSERT_EQ(2u, values.size());
@@ -324,11 +324,11 @@
 }
 
 TEST_F(WebAppPrefsUtilsTest, MLGuardrailConsecutiveAppAgnosticIgnores) {
-  const AppId& app_id1 = "app1";
-  const AppId& app_id2 = "app2";
-  const AppId& app_id3 = "app3";
-  const AppId& app_id4 = "app4";
-  const AppId& app_id5 = "app5";
+  const webapps::AppId& app_id1 = "app1";
+  const webapps::AppId& app_id2 = "app2";
+  const webapps::AppId& app_id3 = "app3";
+  const webapps::AppId& app_id4 = "app4";
+  const webapps::AppId& app_id5 = "app5";
   RecordMlInstallIgnored(prefs(), app_id1, base::Time::Now());
   {
     const auto& dict = prefs()->GetDict(prefs::kWebAppsAppAgnosticMlState);
@@ -368,7 +368,7 @@
 }
 
 TEST_F(WebAppPrefsUtilsTest, MLGuardrailConsecutiveAppAgnosticIgnoreDays) {
-  const AppId& app_id1 = "app1";
+  const webapps::AppId& app_id1 = "app1";
   RecordMlInstallIgnored(prefs(), app_id1, base::Time::Now());
   auto last_ignored_time =
       GetTimeWebAppPref(prefs(), app_id1, kLastTimeMlInstallIgnored);
@@ -387,7 +387,7 @@
 }
 
 TEST_F(WebAppPrefsUtilsTest, MLGuardrailConsecutiveAppAgnosticDismissDays) {
-  const AppId& app_id1 = "app1";
+  const webapps::AppId& app_id1 = "app1";
 
   // Dismissing any app within the last 7 days should trigger the app agnostic
   // dismiss guardrail response.
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc
index cb443add..ad2b5e1 100644
--- a/chrome/browser/web_applications/web_app_provider.cc
+++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -41,7 +41,6 @@
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_database_factory.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_origin_association_manager.h"
@@ -54,6 +53,7 @@
 #include "chrome/browser/web_applications/web_app_ui_manager.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/browser/web_applications/web_contents/web_contents_manager.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -480,7 +480,7 @@
 }
 
 void WebAppProvider::DoMigrateProfilePrefs(Profile* profile) {
-  std::map<AppId, int> sources =
+  std::map<webapps::AppId, int> sources =
       TakeAllWebAppInstallSources(profile->GetPrefs());
   ScopedRegistryUpdate update = sync_bridge_->BeginUpdate();
   for (const auto& iter : sources) {
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc
index 6085921..c5b7b2c0 100644
--- a/chrome/browser/web_applications/web_app_registrar.cc
+++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -85,14 +85,14 @@
 }
 
 blink::ParsedPermissionsPolicy WebAppRegistrar::GetPermissionsPolicy(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->permissions_policy()
                  : blink::ParsedPermissionsPolicy();
 }
 
 bool WebAppRegistrar::IsPlaceholderApp(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const WebAppManagement::Type source_type) const {
   const WebApp* web_app = GetAppById(app_id);
   if (!web_app)
@@ -115,7 +115,7 @@
 // TODO(crbug.com/1434692): Revert changes back to old code
 // once the system starts enforcing a single install URL per
 // app_id.
-absl::optional<AppId> WebAppRegistrar::LookupPlaceholderAppId(
+absl::optional<webapps::AppId> WebAppRegistrar::LookupPlaceholderAppId(
     const GURL& install_url,
     const WebAppManagement::Type source_type) const {
   for (const WebApp& web_app : GetApps()) {
@@ -150,7 +150,7 @@
 }
 
 void WebAppRegistrar::NotifyWebAppFileHandlerApprovalStateChanged(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppFileHandlerApprovalStateChanged(app_id);
   }
@@ -163,8 +163,9 @@
   }
 }
 
-void WebAppRegistrar::NotifyWebAppDisabledStateChanged(const AppId& app_id,
-                                                       bool is_disabled) {
+void WebAppRegistrar::NotifyWebAppDisabledStateChanged(
+    const webapps::AppId& app_id,
+    bool is_disabled) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppDisabledStateChanged(app_id, is_disabled);
   }
@@ -177,7 +178,7 @@
 }
 
 void WebAppRegistrar::NotifyWebAppLastBadgingTimeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::Time& time) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppLastBadgingTimeChanged(app_id, time);
@@ -185,7 +186,7 @@
 }
 
 void WebAppRegistrar::NotifyWebAppLastLaunchTimeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::Time& time) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppLastLaunchTimeChanged(app_id, time);
@@ -193,21 +194,22 @@
 }
 
 void WebAppRegistrar::NotifyWebAppFirstInstallTimeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::Time& time) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppFirstInstallTimeChanged(app_id, time);
   }
 }
 
-void WebAppRegistrar::NotifyWebAppProfileWillBeDeleted(const AppId& app_id) {
+void WebAppRegistrar::NotifyWebAppProfileWillBeDeleted(
+    const webapps::AppId& app_id) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppProfileWillBeDeleted(app_id);
   }
 }
 
 void WebAppRegistrar::NotifyWebAppUserDisplayModeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     mojom::UserDisplayMode user_display_mode) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppUserDisplayModeChanged(app_id, user_display_mode);
@@ -215,7 +217,7 @@
 }
 
 void WebAppRegistrar::NotifyWebAppRunOnOsLoginModeChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     RunOnOsLoginMode run_on_os_login_mode) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppRunOnOsLoginModeChanged(app_id, run_on_os_login_mode);
@@ -230,7 +232,7 @@
 
 #if !BUILDFLAG(IS_CHROMEOS)
 void WebAppRegistrar::NotifyWebAppUserLinkCapturingPreferencesChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool is_preferred) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnWebAppUserLinkCapturingPreferencesChanged(app_id, is_preferred);
@@ -238,10 +240,10 @@
 }
 #endif  // !BUILDFLAG(IS_CHROMEOS)
 
-base::flat_map<AppId, base::flat_set<GURL>>
+base::flat_map<webapps::AppId, base::flat_set<GURL>>
 WebAppRegistrar::GetExternallyInstalledApps(
     ExternalInstallSource install_source) const {
-  base::flat_map<AppId, base::flat_set<GURL>> installed_apps;
+  base::flat_map<webapps::AppId, base::flat_set<GURL>> installed_apps;
   WebAppManagement::Type management_source =
       ConvertExternalInstallSourceToSource(install_source);
   for (const WebApp& web_app : GetApps()) {
@@ -254,16 +256,16 @@
   return installed_apps;
 }
 
-absl::optional<AppId> WebAppRegistrar::LookupExternalAppId(
+absl::optional<webapps::AppId> WebAppRegistrar::LookupExternalAppId(
     const GURL& install_url) const {
-  absl::optional<AppId> app_id = LookUpAppIdByInstallUrl(install_url);
+  absl::optional<webapps::AppId> app_id = LookUpAppIdByInstallUrl(install_url);
   if (app_id.has_value())
     return app_id;
 
   return absl::nullopt;
 }
 
-bool WebAppRegistrar::HasExternalApp(const AppId& app_id) const {
+bool WebAppRegistrar::HasExternalApp(const webapps::AppId& app_id) const {
   if (!IsInstalled(app_id))
     return false;
 
@@ -274,7 +276,7 @@
 }
 
 bool WebAppRegistrar::HasExternalAppWithInstallSource(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     ExternalInstallSource install_source) const {
   if (!IsInstalled(app_id))
     return false;
@@ -285,7 +287,7 @@
                         ConvertExternalInstallSourceToSource(install_source));
 }
 
-GURL WebAppRegistrar::GetAppLaunchUrl(const AppId& app_id) const {
+GURL WebAppRegistrar::GetAppLaunchUrl(const webapps::AppId& app_id) const {
   const GURL& start_url = GetAppStartUrl(app_id);
   const std::string* launch_query_params = GetAppLaunchQueryParams(app_id);
   if (!start_url.is_valid() || !launch_query_params)
@@ -307,15 +309,16 @@
   return start_url.ReplaceComponents(replacements);
 }
 
-GURL WebAppRegistrar::GetAppScope(const AppId& app_id) const {
+GURL WebAppRegistrar::GetAppScope(const webapps::AppId& app_id) const {
   absl::optional<GURL> scope = GetAppScopeInternal(app_id);
   if (scope)
     return *scope;
   return GetAppStartUrl(app_id).GetWithoutFilename();
 }
 
-size_t WebAppRegistrar::GetAppExtendedScopeScore(const GURL& url,
-                                                 const AppId& app_id) const {
+size_t WebAppRegistrar::GetAppExtendedScopeScore(
+    const GURL& url,
+    const webapps::AppId& app_id) const {
   if (!url.is_valid()) {
     return 0;
   }
@@ -367,17 +370,19 @@
 }
 
 bool WebAppRegistrar::IsUrlInAppScope(const GURL& url,
-                                      const AppId& app_id) const {
+                                      const webapps::AppId& app_id) const {
   return GetUrlInAppScopeScore(url.spec(), app_id) > 0;
 }
 
-bool WebAppRegistrar::IsUrlInAppExtendedScope(const GURL& url,
-                                              const AppId& app_id) const {
+bool WebAppRegistrar::IsUrlInAppExtendedScope(
+    const GURL& url,
+    const webapps::AppId& app_id) const {
   return GetAppExtendedScopeScore(url, app_id) > 0;
 }
 
-size_t WebAppRegistrar::GetUrlInAppScopeScore(const std::string& url_spec,
-                                              const AppId& app_id) const {
+size_t WebAppRegistrar::GetUrlInAppScopeScore(
+    const std::string& url_spec,
+    const webapps::AppId& app_id) const {
   std::string app_scope = GetAppScope(app_id).spec();
 
   // The app may have been uninstalled.
@@ -399,18 +404,18 @@
   return score;
 }
 
-absl::optional<AppId> WebAppRegistrar::FindAppWithUrlInScope(
+absl::optional<webapps::AppId> WebAppRegistrar::FindAppWithUrlInScope(
     const GURL& url) const {
   if (!url.is_valid())
     return absl::nullopt;
 
   const std::string url_spec = url.spec();
 
-  absl::optional<AppId> best_app_id;
+  absl::optional<webapps::AppId> best_app_id;
   size_t best_score = 0U;
   bool best_app_is_shortcut = true;
 
-  for (const AppId& app_id : GetAppIdsForAppSet(GetApps())) {
+  for (const webapps::AppId& app_id : GetAppIdsForAppSet(GetApps())) {
     // TODO(crbug.com/1469482): Consider treating shortcuts differently to PWAs.
     bool app_is_shortcut = IsShortcutApp(app_id);
     if (app_is_shortcut && !best_app_is_shortcut)
@@ -446,10 +451,11 @@
   return false;
 }
 
-std::vector<AppId> WebAppRegistrar::FindAppsInScope(const GURL& scope) const {
+std::vector<webapps::AppId> WebAppRegistrar::FindAppsInScope(
+    const GURL& scope) const {
   std::string scope_str = scope.spec();
 
-  std::vector<AppId> in_scope;
+  std::vector<webapps::AppId> in_scope;
   for (const auto& app_id : GetAppIds()) {
     if (!IsLocallyInstalled(app_id))
       continue;
@@ -466,16 +472,16 @@
   return in_scope;
 }
 
-absl::optional<AppId> WebAppRegistrar::FindInstalledAppWithUrlInScope(
+absl::optional<webapps::AppId> WebAppRegistrar::FindInstalledAppWithUrlInScope(
     const GURL& url,
     bool window_only) const {
   const std::string url_spec = url.spec();
 
-  absl::optional<AppId> best_app_id;
+  absl::optional<webapps::AppId> best_app_id;
   size_t best_score = 0U;
   bool best_app_is_shortcut = true;
 
-  for (const AppId& app_id : GetAppIds()) {
+  for (const webapps::AppId& app_id : GetAppIds()) {
     // TODO(crbug.com/1469482): Consider treating shortcuts differently to PWAs.
     bool app_is_shortcut = IsShortcutApp(app_id);
     if (app_is_shortcut && !best_app_is_shortcut) {
@@ -524,19 +530,19 @@
   return false;
 }
 
-bool WebAppRegistrar::IsShortcutApp(const AppId& app_id) const {
+bool WebAppRegistrar::IsShortcutApp(const webapps::AppId& app_id) const {
   // TODO(crbug.com/1469482): Record shortcut distinction explicitly instead of
   // using scope.
   return !GetAppScopeInternal(app_id).has_value();
 }
 
-bool WebAppRegistrar::IsSystemApp(const AppId& app_id) const {
+bool WebAppRegistrar::IsSystemApp(const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app && web_app->IsSystemApp();
 }
 
 DisplayMode WebAppRegistrar::GetAppEffectiveDisplayMode(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   if (!IsLocallyInstalled(app_id))
     return DisplayMode::kBrowser;
 
@@ -555,7 +561,7 @@
 }
 
 DisplayMode WebAppRegistrar::GetEffectiveDisplayModeFromManifest(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   std::vector<DisplayMode> display_mode_overrides =
       GetAppDisplayModeOverride(app_id);
 
@@ -565,19 +571,21 @@
   return GetAppDisplayMode(app_id);
 }
 
-GURL WebAppRegistrar::GetComputedManifestId(const AppId& app_id) const {
+GURL WebAppRegistrar::GetComputedManifestId(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->manifest_id() : GURL();
 }
 
-bool WebAppRegistrar::IsTabbedWindowModeEnabled(const AppId& app_id) const {
+bool WebAppRegistrar::IsTabbedWindowModeEnabled(
+    const webapps::AppId& app_id) const {
   if (!base::FeatureList::IsEnabled(blink::features::kDesktopPWAsTabStrip)) {
     return false;
   }
   return GetAppEffectiveDisplayMode(app_id) == DisplayMode::kTabbed;
 }
 
-GURL WebAppRegistrar::GetAppNewTabUrl(const AppId& app_id) const {
+GURL WebAppRegistrar::GetAppNewTabUrl(const webapps::AppId& app_id) const {
   if (IsTabbedWindowModeEnabled(app_id)) {
     auto* web_app = GetAppById(app_id);
     if (!web_app)
@@ -595,7 +603,7 @@
 }
 
 absl::optional<GURL> WebAppRegistrar::GetAppPinnedHomeTabUrl(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   if (IsTabbedWindowModeEnabled(app_id)) {
     const WebApp* web_app = GetAppById(app_id);
     if (!web_app)
@@ -612,7 +620,8 @@
 }
 
 absl::optional<proto::WebAppOsIntegrationState>
-WebAppRegistrar::GetAppCurrentOsIntegrationState(const AppId& app_id) const {
+WebAppRegistrar::GetAppCurrentOsIntegrationState(
+    const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   if (!web_app)
     return absl::nullopt;
@@ -621,13 +630,14 @@
 }
 
 #if BUILDFLAG(IS_MAC)
-bool WebAppRegistrar::AlwaysShowToolbarInFullscreen(const AppId& app_id) const {
+bool WebAppRegistrar::AlwaysShowToolbarInFullscreen(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->always_show_toolbar_in_fullscreen() : true;
 }
 
 void WebAppRegistrar::NotifyAlwaysShowToolbarInFullscreenChanged(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool show) {
   for (WebAppRegistrarObserver& observer : observers_) {
     observer.OnAlwaysShowToolbarInFullscreenChanged(app_id, show);
@@ -635,7 +645,7 @@
 }
 #endif
 
-const WebApp* WebAppRegistrar::GetAppById(const AppId& app_id) const {
+const WebApp* WebAppRegistrar::GetAppById(const webapps::AppId& app_id) const {
   if (registry_profile_being_deleted_)
     return nullptr;
 
@@ -658,8 +668,8 @@
   return nullptr;
 }
 
-std::vector<AppId> WebAppRegistrar::GetAppsFromSyncAndPendingInstallation()
-    const {
+std::vector<webapps::AppId>
+WebAppRegistrar::GetAppsFromSyncAndPendingInstallation() const {
   AppSet apps_in_sync_install = AppSet(
       this,
       [](const WebApp& web_app) {
@@ -668,14 +678,14 @@
       },
       /*empty=*/registry_profile_being_deleted_);
 
-  std::vector<AppId> app_ids;
+  std::vector<webapps::AppId> app_ids;
   for (const WebApp& app : apps_in_sync_install)
     app_ids.push_back(app.app_id());
 
   return app_ids;
 }
 
-std::vector<AppId> WebAppRegistrar::GetAppsPendingUninstall() const {
+std::vector<webapps::AppId> WebAppRegistrar::GetAppsPendingUninstall() const {
   AppSet apps_in_sync_uninstall = AppSet(
       this,
       [](const WebApp& web_app) {
@@ -685,7 +695,7 @@
       },
       /*empty=*/registry_profile_being_deleted_);
 
-  std::vector<AppId> app_ids;
+  std::vector<webapps::AppId> app_ids;
   for (const WebApp& app : apps_in_sync_uninstall)
     app_ids.push_back(app.app_id());
 
@@ -728,7 +738,7 @@
   return weak_factory_.GetWeakPtr();
 }
 
-absl::optional<AppId> WebAppRegistrar::LookUpAppIdByInstallUrl(
+absl::optional<webapps::AppId> WebAppRegistrar::LookUpAppIdByInstallUrl(
     const GURL& install_url) const {
   for (const WebApp& web_app : GetApps()) {
     for (auto it : web_app.management_to_external_config_map()) {
@@ -756,7 +766,7 @@
   return nullptr;
 }
 
-bool WebAppRegistrar::IsInstalled(const AppId& app_id) const {
+bool WebAppRegistrar::IsInstalled(const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   if (!web_app || web_app->is_uninstalling())
     return false;
@@ -770,19 +780,19 @@
            sources_except_sync.Empty());
 }
 
-bool WebAppRegistrar::IsUninstalling(const AppId& app_id) const {
+bool WebAppRegistrar::IsUninstalling(const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app && web_app->is_uninstalling();
 }
 
-bool WebAppRegistrar::IsLocallyInstalled(const AppId& app_id) const {
+bool WebAppRegistrar::IsLocallyInstalled(const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app
              ? !web_app->is_uninstalling() && web_app->is_locally_installed()
              : false;
 }
 
-bool WebAppRegistrar::IsActivelyInstalled(const AppId& app_id) const {
+bool WebAppRegistrar::IsActivelyInstalled(const webapps::AppId& app_id) const {
   if (!IsInstalled(app_id) || !IsLocallyInstalled(app_id))
     return false;
 
@@ -792,13 +802,13 @@
          GetAppEffectiveDisplayMode(app_id) != DisplayMode::kBrowser;
 }
 
-bool WebAppRegistrar::IsIsolated(const AppId& app_id) const {
+bool WebAppRegistrar::IsIsolated(const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app && web_app->isolation_data().has_value();
 }
 
 bool WebAppRegistrar::IsInstalledByDefaultManagement(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   if (!IsInstalled(app_id))
     return false;
 
@@ -807,38 +817,41 @@
   return web_app->GetSources().Has(WebAppManagement::kDefault);
 }
 
-bool WebAppRegistrar::WasInstalledByDefaultOnly(const AppId& app_id) const {
+bool WebAppRegistrar::WasInstalledByDefaultOnly(
+    const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app && web_app->HasOnlySource(WebAppManagement::Type::kDefault);
 }
 
-bool WebAppRegistrar::WasInstalledByUser(const AppId& app_id) const {
+bool WebAppRegistrar::WasInstalledByUser(const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app && web_app->WasInstalledByUser();
 }
 
-bool WebAppRegistrar::WasInstalledByOem(const AppId& app_id) const {
+bool WebAppRegistrar::WasInstalledByOem(const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app && web_app->chromeos_data().has_value() &&
          web_app->chromeos_data()->oem_installed;
 }
 
-bool WebAppRegistrar::WasInstalledBySubApp(const AppId& app_id) const {
+bool WebAppRegistrar::WasInstalledBySubApp(const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app && web_app->IsSubAppInstalledApp();
 }
 
-bool WebAppRegistrar::CanUserUninstallWebApp(const AppId& app_id) const {
+bool WebAppRegistrar::CanUserUninstallWebApp(
+    const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app && web_app->CanUserUninstallWebApp();
 }
 
-bool WebAppRegistrar::IsPreventCloseEnabled(const AppId& app_id) const {
+bool WebAppRegistrar::IsPreventCloseEnabled(
+    const webapps::AppId& app_id) const {
   return provider_->policy_manager().IsPreventCloseEnabled(app_id);
 }
 
 bool WebAppRegistrar::IsAllowedLaunchProtocol(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& protocol_scheme) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app &&
@@ -846,7 +859,7 @@
 }
 
 bool WebAppRegistrar::IsDisallowedLaunchProtocol(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& protocol_scheme) const {
   const WebApp* web_app = GetAppById(app_id);
   return web_app && base::Contains(web_app->disallowed_launch_protocols(),
@@ -854,7 +867,7 @@
 }
 
 bool WebAppRegistrar::IsRegisteredLaunchProtocol(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const std::string& protocol_scheme) const {
   const WebApp* web_app = GetAppById(app_id);
   if (!web_app)
@@ -905,7 +918,7 @@
 
 std::vector<content::StoragePartitionConfig>
 WebAppRegistrar::GetIsolatedWebAppStoragePartitionConfigs(
-    const AppId& isolated_web_app_id) const {
+    const webapps::AppId& isolated_web_app_id) const {
   if (!content::IsolatedWebAppsPolicy::AreIsolatedWebAppsEnabled(profile_)) {
     return {};
   }
@@ -964,7 +977,7 @@
       profile_, partition_name, true);
 }
 
-bool WebAppRegistrar::CapturesLinksInScope(const AppId& app_id) const {
+bool WebAppRegistrar::CapturesLinksInScope(const webapps::AppId& app_id) const {
   if (!IsLocallyInstalled(app_id) || IsShortcutApp(app_id)) {
     return false;
   }
@@ -974,15 +987,15 @@
   return web_app->is_user_selected_app_for_capturing_links();
 }
 
-absl::optional<AppId> WebAppRegistrar::FindAppThatCapturesLinksInScope(
+absl::optional<webapps::AppId> WebAppRegistrar::FindAppThatCapturesLinksInScope(
     const GURL& url) const {
   // Nested apps remove that URL space from the parent app, so links from a
   // nested app cannot be captured by a parent app. Even so, there can be
   // multiple apps with the same score, but the only one that matters is the
   // first one that also captures links.
   size_t top_score = 0;
-  std::vector<AppId> top_apps;
-  for (const AppId& app_id : GetAppIds()) {
+  std::vector<webapps::AppId> top_apps;
+  for (const webapps::AppId& app_id : GetAppIds()) {
     if (!IsLocallyInstalled(app_id)) {
       continue;
     }
@@ -1003,7 +1016,7 @@
   if (top_apps.empty()) {
     return absl::nullopt;
   }
-  for (const AppId& app_id : top_apps) {
+  for (const webapps::AppId& app_id : top_apps) {
     if (CapturesLinksInScope(app_id)) {
       return app_id;
     }
@@ -1011,9 +1024,9 @@
   return absl::nullopt;
 }
 
-std::vector<AppId> WebAppRegistrar::GetOverlappingAppsMatchingScope(
-    const AppId& app_id) const {
-  std::vector<AppId> all_apps_with_supported_links;
+std::vector<webapps::AppId> WebAppRegistrar::GetOverlappingAppsMatchingScope(
+    const webapps::AppId& app_id) const {
+  std::vector<webapps::AppId> all_apps_with_supported_links;
   const GURL& required_scope = GetAppScope(app_id);
   if (!IsValidScopeForLinkCapturing(required_scope)) {
     return all_apps_with_supported_links;
@@ -1046,8 +1059,8 @@
 }
 
 bool WebAppRegistrar::AppScopesMatchForUserLinkCapturing(
-    const AppId& app_id1,
-    const AppId& app_id2) const {
+    const webapps::AppId& app_id1,
+    const webapps::AppId& app_id2) const {
   if (!IsLocallyInstalled(app_id1) || !IsLocallyInstalled(app_id2)) {
     return false;
   }
@@ -1062,7 +1075,8 @@
   return app_scope1 == app_scope2;
 }
 
-std::string WebAppRegistrar::GetAppShortName(const AppId& app_id) const {
+std::string WebAppRegistrar::GetAppShortName(
+    const webapps::AppId& app_id) const {
   if (base::FeatureList::IsEnabled(
           blink::features::kWebAppEnableTranslations)) {
     std::string translated_name =
@@ -1075,7 +1089,8 @@
   return web_app ? web_app->untranslated_name() : std::string();
 }
 
-std::string WebAppRegistrar::GetAppDescription(const AppId& app_id) const {
+std::string WebAppRegistrar::GetAppDescription(
+    const webapps::AppId& app_id) const {
   if (base::FeatureList::IsEnabled(
           blink::features::kWebAppEnableTranslations)) {
     std::string translated_description =
@@ -1089,47 +1104,49 @@
 }
 
 absl::optional<SkColor> WebAppRegistrar::GetAppThemeColor(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->theme_color() : absl::nullopt;
 }
 
 absl::optional<SkColor> WebAppRegistrar::GetAppDarkModeThemeColor(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->dark_mode_theme_color() : absl::nullopt;
 }
 
 absl::optional<SkColor> WebAppRegistrar::GetAppBackgroundColor(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->background_color() : absl::nullopt;
 }
 
 absl::optional<SkColor> WebAppRegistrar::GetAppDarkModeBackgroundColor(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->dark_mode_background_color() : absl::nullopt;
 }
 
-const GURL& WebAppRegistrar::GetAppStartUrl(const AppId& app_id) const {
+const GURL& WebAppRegistrar::GetAppStartUrl(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->start_url() : GURL::EmptyGURL();
 }
 
-ManifestId WebAppRegistrar::GetAppManifestId(const AppId& app_id) const {
+webapps::ManifestId WebAppRegistrar::GetAppManifestId(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
-  return web_app ? web_app->manifest_id() : ManifestId();
+  return web_app ? web_app->manifest_id() : webapps::ManifestId();
 }
 
 const std::string* WebAppRegistrar::GetAppLaunchQueryParams(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->launch_query_params() : nullptr;
 }
 
 const apps::ShareTarget* WebAppRegistrar::GetAppShareTarget(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return (web_app && web_app->share_target().has_value())
              ? &web_app->share_target().value()
@@ -1137,13 +1154,13 @@
 }
 
 const apps::FileHandlers* WebAppRegistrar::GetAppFileHandlers(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? &web_app->file_handlers() : nullptr;
 }
 
 bool WebAppRegistrar::IsAppFileHandlerPermissionBlocked(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   if (!web_app)
     return false;
@@ -1153,7 +1170,7 @@
 }
 
 ApiApprovalState WebAppRegistrar::GetAppFileHandlerApprovalState(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   if (!web_app)
     return ApiApprovalState::kDisallowed;
@@ -1167,7 +1184,7 @@
 }
 
 bool WebAppRegistrar::ExpectThatFileHandlersAreRegisteredWithOs(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   if (!web_app) {
     return false;
@@ -1180,7 +1197,7 @@
 }
 
 absl::optional<GURL> WebAppRegistrar::GetAppScopeInternal(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   if (!web_app)
     return absl::nullopt;
@@ -1196,13 +1213,14 @@
   return web_app->scope();
 }
 
-DisplayMode WebAppRegistrar::GetAppDisplayMode(const AppId& app_id) const {
+DisplayMode WebAppRegistrar::GetAppDisplayMode(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->display_mode() : DisplayMode::kUndefined;
 }
 
 absl::optional<mojom::UserDisplayMode> WebAppRegistrar::GetAppUserDisplayMode(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   if (web_app == nullptr) {
     return absl::nullopt;
@@ -1222,48 +1240,51 @@
 }
 
 std::vector<DisplayMode> WebAppRegistrar::GetAppDisplayModeOverride(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->display_mode_override()
                  : std::vector<DisplayMode>();
 }
 
 apps::UrlHandlers WebAppRegistrar::GetAppUrlHandlers(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->url_handlers()
                  : std::vector<apps::UrlHandlerInfo>();
 }
 
 base::flat_set<ScopeExtensionInfo> WebAppRegistrar::GetValidatedScopeExtensions(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->validated_scope_extensions()
                  : base::flat_set<ScopeExtensionInfo>();
 }
 
-GURL WebAppRegistrar::GetAppManifestUrl(const AppId& app_id) const {
+GURL WebAppRegistrar::GetAppManifestUrl(const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->manifest_url() : GURL::EmptyGURL();
 }
 
-base::Time WebAppRegistrar::GetAppLastBadgingTime(const AppId& app_id) const {
+base::Time WebAppRegistrar::GetAppLastBadgingTime(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->last_badging_time() : base::Time();
 }
 
-base::Time WebAppRegistrar::GetAppLastLaunchTime(const AppId& app_id) const {
+base::Time WebAppRegistrar::GetAppLastLaunchTime(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->last_launch_time() : base::Time();
 }
 
-base::Time WebAppRegistrar::GetAppFirstInstallTime(const AppId& app_id) const {
+base::Time WebAppRegistrar::GetAppFirstInstallTime(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->first_install_time() : base::Time();
 }
 
 absl::optional<webapps::WebappInstallSource>
-WebAppRegistrar::GetLatestAppInstallSource(const AppId& app_id) const {
+WebAppRegistrar::GetLatestAppInstallSource(const webapps::AppId& app_id) const {
   const WebApp* web_app = GetAppById(app_id);
   if (!web_app)
     return absl::nullopt;
@@ -1285,32 +1306,33 @@
 }
 
 std::vector<apps::IconInfo> WebAppRegistrar::GetAppIconInfos(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->manifest_icons() : std::vector<apps::IconInfo>();
 }
 
 SortedSizesPx WebAppRegistrar::GetAppDownloadedIconSizesAny(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->downloaded_icon_sizes(IconPurpose::ANY)
                  : SortedSizesPx();
 }
 
 std::vector<WebAppShortcutsMenuItemInfo>
-WebAppRegistrar::GetAppShortcutsMenuItemInfos(const AppId& app_id) const {
+WebAppRegistrar::GetAppShortcutsMenuItemInfos(
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->shortcuts_menu_item_infos()
                  : std::vector<WebAppShortcutsMenuItemInfo>();
 }
 
-std::vector<AppId> WebAppRegistrar::GetAppIds() const {
+std::vector<webapps::AppId> WebAppRegistrar::GetAppIds() const {
   return GetAppIdsForAppSet(GetApps());
 }
 
-std::vector<AppId> WebAppRegistrar::GetAllSubAppIds(
-    const AppId& parent_app_id) const {
-  std::vector<AppId> sub_app_ids;
+std::vector<webapps::AppId> WebAppRegistrar::GetAllSubAppIds(
+    const webapps::AppId& parent_app_id) const {
+  std::vector<webapps::AppId> sub_app_ids;
 
   for (const WebApp& app : GetApps()) {
     if (app.parent_app_id().has_value() &&
@@ -1322,8 +1344,9 @@
   return sub_app_ids;
 }
 
-base::flat_map<AppId, AppId> WebAppRegistrar::GetSubAppToParentMap() const {
-  base::flat_map<AppId, AppId> parent_app_ids;
+base::flat_map<webapps::AppId, webapps::AppId>
+WebAppRegistrar::GetSubAppToParentMap() const {
+  base::flat_map<webapps::AppId, webapps::AppId> parent_app_ids;
 
   for (const WebApp& app : GetApps()) {
     if (app.parent_app_id().has_value()) {
@@ -1335,7 +1358,7 @@
 }
 
 ValueWithPolicy<RunOnOsLoginMode> WebAppRegistrar::GetAppRunOnOsLoginMode(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   RunOnOsLoginPolicy login_policy =
       provider_->policy_manager().GetUrlRunOnOsLoginPolicy(app_id);
 
@@ -1355,14 +1378,14 @@
 
 absl::optional<RunOnOsLoginMode>
 WebAppRegistrar::GetExpectedRunOnOsLoginOsIntegrationState(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->run_on_os_login_os_integration_state()
                  : absl::nullopt;
 }
 
 bool WebAppRegistrar::GetWindowControlsOverlayEnabled(
-    const AppId& app_id) const {
+    const webapps::AppId& app_id) const {
   auto* web_app = GetAppById(app_id);
   return web_app ? web_app->window_controls_overlay_enabled() : false;
 }
@@ -1372,7 +1395,8 @@
   if (profile() != profile_to_be_deleted)
     return;
 
-  for (const AppId& app_id : GetAppIdsForAppSet(GetAppsIncludingStubs())) {
+  for (const webapps::AppId& app_id :
+       GetAppIdsForAppSet(GetAppsIncludingStubs())) {
     NotifyWebAppProfileWillBeDeleted(app_id);
   }
   // We can't do registry_.clear() here because it makes in-memory registry
@@ -1449,7 +1473,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS)
 void WebAppRegistrar::SetUserDisplayModeOverridesForExperiment(
-    base::flat_map<AppId, mojom::UserDisplayMode> overrides) {
+    base::flat_map<webapps::AppId, mojom::UserDisplayMode> overrides) {
   DCHECK(base::FeatureList::IsEnabled(
       features::kPreinstalledWebAppWindowExperiment));
   user_display_mode_overrides_for_experiment_ = std::move(overrides);
@@ -1545,7 +1569,8 @@
   SetRegistry(std::move(registry));
 }
 
-WebApp* WebAppRegistrarMutable::GetAppByIdMutable(const AppId& app_id) {
+WebApp* WebAppRegistrarMutable::GetAppByIdMutable(
+    const webapps::AppId& app_id) {
   return const_cast<WebApp*>(GetAppById(app_id));
 }
 
@@ -1592,9 +1617,9 @@
   return true;
 }
 
-std::vector<AppId> WebAppRegistrar::GetAppIdsForAppSet(
+std::vector<webapps::AppId> WebAppRegistrar::GetAppIdsForAppSet(
     const AppSet& app_set) const {
-  std::vector<AppId> app_ids;
+  std::vector<webapps::AppId> app_ids;
 
   for (const WebApp& app : app_set)
     app_ids.push_back(app.app_id());
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h
index 8368e252..c1d008b 100644
--- a/chrome/browser/web_applications/web_app_registrar.h
+++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -30,6 +30,7 @@
 #include "components/services/app_service/public/cpp/file_handler.h"
 #include "components/services/app_service/public/cpp/protocol_handler_info.h"
 #include "components/services/app_service/public/cpp/url_handler_info.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -55,7 +56,7 @@
 class WebApp;
 class WebAppProvider;
 
-using Registry = std::map<AppId, std::unique_ptr<WebApp>>;
+using Registry = std::map<webapps::AppId, std::unique_ptr<WebApp>>;
 
 template <typename T>
 struct ValueWithPolicy {
@@ -73,13 +74,13 @@
 
   bool is_empty() const { return registry_.empty(); }
 
-  const WebApp* GetAppById(const AppId& app_id) const;
+  const WebApp* GetAppById(const webapps::AppId& app_id) const;
 
   // TODO(https://crbug.com/1182363): should be removed when id is introduced to
   // manifest.
   const WebApp* GetAppByStartUrl(const GURL& start_url) const;
-  std::vector<AppId> GetAppsFromSyncAndPendingInstallation() const;
-  std::vector<AppId> GetAppsPendingUninstall() const;
+  std::vector<webapps::AppId> GetAppsFromSyncAndPendingInstallation() const;
+  std::vector<webapps::AppId> GetAppsPendingUninstall() const;
 
   bool AppsExistWithExternalConfigData() const;
 
@@ -89,9 +90,10 @@
 
   base::WeakPtr<WebAppRegistrar> AsWeakPtr();
 
-  // Returns an AppId if there exists an app inside the registry that
+  // Returns an webapps::AppId if there exists an app inside the registry that
   // has a specific install_url.
-  absl::optional<AppId> LookUpAppIdByInstallUrl(const GURL& install_url) const;
+  absl::optional<webapps::AppId> LookUpAppIdByInstallUrl(
+      const GURL& install_url) const;
 
   // Returns a WebApp if there exists an app inside the registry that
   // has a specific `install_source` with `install_url`.
@@ -103,90 +105,91 @@
   // Returns whether the app with |app_id| is currently listed in the registry.
   // ie. we have data for web app manifest and icons, and this |app_id| can be
   // used in other registrar methods.
-  bool IsInstalled(const AppId& app_id) const;
+  bool IsInstalled(const webapps::AppId& app_id) const;
 
   // Returns whether the app is currently being uninstalled. This will be true
   // after uninstall has begun but before the OS integration hooks for uninstall
   // have completed. It will return false after uninstallation has completed.
-  bool IsUninstalling(const AppId& app_id) const;
+  bool IsUninstalling(const webapps::AppId& app_id) const;
 
   // Returns whether the app with |app_id| is currently fully locally installed.
   // ie. app is not grey in chrome://apps UI surface and may have OS integration
   // like shortcuts. |IsLocallyInstalled| apps is a subset of |IsInstalled|
   // apps. On Chrome OS all apps are always locally installed.
-  bool IsLocallyInstalled(const AppId& app_id) const;
+  bool IsLocallyInstalled(const webapps::AppId& app_id) const;
 
   // Returns true if the app was actively installed, meaning the app has
   // involved some form of user or administrator action to either install it or
   // configure it to behave like an app.
-  bool IsActivelyInstalled(const AppId& app_id) const;
+  bool IsActivelyInstalled(const webapps::AppId& app_id) const;
 
   // Returns the permissions policy declared as declared in the manifest for
   // the app with |app_id|. This permissions policy is not yet parsed by the
   // PermissionsPolicyParser, and thus may contain invalid permissions and/or
   // origin allowlists.
   blink::ParsedPermissionsPolicy GetPermissionsPolicy(
-      const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
   // Returns true if there exists a currently installed app that has been
   // installed by PreinstalledWebAppManager.
-  bool IsInstalledByDefaultManagement(const AppId& app_id) const;
+  bool IsInstalledByDefaultManagement(const webapps::AppId& app_id) const;
 
   // Returns true if the app was preinstalled and NOT installed via any other
   // mechanism.
-  bool WasInstalledByDefaultOnly(const AppId& app_id) const;
+  bool WasInstalledByDefaultOnly(const webapps::AppId& app_id) const;
 
   // Returns true if the app was installed by user, false if default installed.
-  bool WasInstalledByUser(const AppId& app_id) const;
+  bool WasInstalledByUser(const webapps::AppId& app_id) const;
 
   // Returns true if the app was installed by the device OEM. Always false on
   // on non-Chrome OS.
-  bool WasInstalledByOem(const AppId& app_id) const;
+  bool WasInstalledByOem(const webapps::AppId& app_id) const;
 
   // Returns true if the app was installed by the SubApp API.
-  bool WasInstalledBySubApp(const AppId& app_id) const;
+  bool WasInstalledBySubApp(const webapps::AppId& app_id) const;
 
   // Returns true if the app exists and is allowed to be uninstalled by the user
   // e.g. it is not policy installed.
-  bool CanUserUninstallWebApp(const AppId& app_id) const;
+  bool CanUserUninstallWebApp(const webapps::AppId& app_id) const;
 
   // Returns true if the prevent-close feature is enabled for the given app
-  bool IsPreventCloseEnabled(const AppId& app_id) const;
+  bool IsPreventCloseEnabled(const webapps::AppId& app_id) const;
 
   // Returns the AppIds and URLs of apps externally installed from
   // |install_source|.
-  base::flat_map<AppId, base::flat_set<GURL>> GetExternallyInstalledApps(
-      ExternalInstallSource install_source) const;
+  base::flat_map<webapps::AppId, base::flat_set<GURL>>
+  GetExternallyInstalledApps(ExternalInstallSource install_source) const;
 
   // Returns the app id for |install_url| if the WebAppRegistrar is aware of an
   // externally installed app for it. Note that the |install_url| is the URL
   // that the app was installed from, which may not necessarily match the app's
   // current start URL.
-  absl::optional<AppId> LookupExternalAppId(const GURL& install_url) const;
+  absl::optional<webapps::AppId> LookupExternalAppId(
+      const GURL& install_url) const;
 
   // Returns whether the WebAppRegistrar has an externally installed app with
   // |app_id| from any |install_source|.
-  bool HasExternalApp(const AppId& app_id) const;
+  bool HasExternalApp(const webapps::AppId& app_id) const;
 
   // Returns whether the WebAppRegistrar has an externally installed app with
   // |app_id| from |install_source|.
   bool HasExternalAppWithInstallSource(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       ExternalInstallSource install_source) const;
 
   // Returns true if the web app with the |app_id| contains |protocol_scheme|
   // as one of its allowed launch protocols.
-  bool IsAllowedLaunchProtocol(const AppId& app_id,
+  bool IsAllowedLaunchProtocol(const webapps::AppId& app_id,
                                const std::string& protocol_scheme) const;
 
   // Returns true if the web app with the |app_id| contains |protocol_scheme|
   // as one of its disallowed launch protocols.
-  bool IsDisallowedLaunchProtocol(const AppId& app_id,
+  bool IsDisallowedLaunchProtocol(const webapps::AppId& app_id,
                                   const std::string& protocol_scheme) const;
 
   // Returns true if the web app with the |app_id| has registered to handle
   // |protocol_scheme|.
-  bool IsRegisteredLaunchProtocol(const AppId& app_id,
+  bool IsRegisteredLaunchProtocol(const webapps::AppId& app_id,
                                   const std::string& protocol_scheme) const;
 
   // Gets all allowed launch protocols from all installed apps.
@@ -204,40 +207,48 @@
   int CountUserInstalledNotLocallyInstalledApps() const;
 
   // All names are UTF8 encoded.
-  std::string GetAppShortName(const AppId& app_id) const;
-  std::string GetAppDescription(const AppId& app_id) const;
-  absl::optional<SkColor> GetAppThemeColor(const AppId& app_id) const;
-  absl::optional<SkColor> GetAppDarkModeThemeColor(const AppId& app_id) const;
-  absl::optional<SkColor> GetAppBackgroundColor(const AppId& app_id) const;
+  std::string GetAppShortName(const webapps::AppId& app_id) const;
+  std::string GetAppDescription(const webapps::AppId& app_id) const;
+  absl::optional<SkColor> GetAppThemeColor(const webapps::AppId& app_id) const;
+  absl::optional<SkColor> GetAppDarkModeThemeColor(
+      const webapps::AppId& app_id) const;
+  absl::optional<SkColor> GetAppBackgroundColor(
+      const webapps::AppId& app_id) const;
   absl::optional<SkColor> GetAppDarkModeBackgroundColor(
-      const AppId& app_id) const;
-  const GURL& GetAppStartUrl(const AppId& app_id) const;
-  ManifestId GetAppManifestId(const AppId& app_id) const;
-  const std::string* GetAppLaunchQueryParams(const AppId& app_id) const;
-  const apps::ShareTarget* GetAppShareTarget(const AppId& app_id) const;
-  const apps::FileHandlers* GetAppFileHandlers(const AppId& app_id) const;
-  bool IsAppFileHandlerPermissionBlocked(const AppId& app_id) const;
-  bool IsIsolated(const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
+  const GURL& GetAppStartUrl(const webapps::AppId& app_id) const;
+  webapps::ManifestId GetAppManifestId(const webapps::AppId& app_id) const;
+  const std::string* GetAppLaunchQueryParams(
+      const webapps::AppId& app_id) const;
+  const apps::ShareTarget* GetAppShareTarget(
+      const webapps::AppId& app_id) const;
+  const apps::FileHandlers* GetAppFileHandlers(
+      const webapps::AppId& app_id) const;
+  bool IsAppFileHandlerPermissionBlocked(const webapps::AppId& app_id) const;
+  bool IsIsolated(const webapps::AppId& app_id) const;
 
   // Returns the state of the File Handling API for the given app.
-  ApiApprovalState GetAppFileHandlerApprovalState(const AppId& app_id) const;
+  ApiApprovalState GetAppFileHandlerApprovalState(
+      const webapps::AppId& app_id) const;
   // Returns true iff it's expected that File Handlers have been, **or are in
   // the process of being**, registered with the OS.
-  bool ExpectThatFileHandlersAreRegisteredWithOs(const AppId& app_id) const;
+  bool ExpectThatFileHandlersAreRegisteredWithOs(
+      const webapps::AppId& app_id) const;
 
   // Returns the start_url with launch_query_params appended to the end if any.
-  GURL GetAppLaunchUrl(const AppId& app_id) const;
+  GURL GetAppLaunchUrl(const webapps::AppId& app_id) const;
 
   // TODO(crbug.com/1469482): Replace uses of this with GetAppScope().
-  absl::optional<GURL> GetAppScopeInternal(const AppId& app_id) const;
+  absl::optional<GURL> GetAppScopeInternal(const webapps::AppId& app_id) const;
 
-  DisplayMode GetAppDisplayMode(const AppId& app_id) const;
+  DisplayMode GetAppDisplayMode(const webapps::AppId& app_id) const;
   absl::optional<mojom::UserDisplayMode> GetAppUserDisplayMode(
-      const AppId& app_id) const;
-  std::vector<DisplayMode> GetAppDisplayModeOverride(const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
+  std::vector<DisplayMode> GetAppDisplayModeOverride(
+      const webapps::AppId& app_id) const;
 
   // Returns the "url_handlers" field from the app manifest.
-  apps::UrlHandlers GetAppUrlHandlers(const AppId& app_id) const;
+  apps::UrlHandlers GetAppUrlHandlers(const webapps::AppId& app_id) const;
 
   // Returns the `scope_extensions` field from the app manifest after
   // validation. Entries with an origin that validated association with this web
@@ -245,87 +256,92 @@
   // https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-explainer.md
   // for association requirements.
   base::flat_set<ScopeExtensionInfo> GetValidatedScopeExtensions(
-      const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
-  GURL GetAppManifestUrl(const AppId& app_id) const;
+  GURL GetAppManifestUrl(const webapps::AppId& app_id) const;
 
-  base::Time GetAppLastBadgingTime(const AppId& app_id) const;
-  base::Time GetAppLastLaunchTime(const AppId& app_id) const;
-  base::Time GetAppFirstInstallTime(const AppId& app_id) const;
+  base::Time GetAppLastBadgingTime(const webapps::AppId& app_id) const;
+  base::Time GetAppLastLaunchTime(const webapps::AppId& app_id) const;
+  base::Time GetAppFirstInstallTime(const webapps::AppId& app_id) const;
 
   absl::optional<webapps::WebappInstallSource> GetLatestAppInstallSource(
-      const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
   // Returns the "icons" field from the app manifest, use |WebAppIconManager| to
   // load icon bitmap data.
-  std::vector<apps::IconInfo> GetAppIconInfos(const AppId& app_id) const;
+  std::vector<apps::IconInfo> GetAppIconInfos(
+      const webapps::AppId& app_id) const;
 
   // Represents which icon sizes we successfully downloaded from the IconInfos.
-  SortedSizesPx GetAppDownloadedIconSizesAny(const AppId& app_id) const;
+  SortedSizesPx GetAppDownloadedIconSizesAny(
+      const webapps::AppId& app_id) const;
 
   // Returns the "shortcuts" field from the app manifest, use
   // |WebAppIconManager| to load shortcuts menu icons bitmaps data.
   std::vector<WebAppShortcutsMenuItemInfo> GetAppShortcutsMenuItemInfos(
-      const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
   // Returns the Run on OS Login mode and enterprise policy value.
   ValueWithPolicy<RunOnOsLoginMode> GetAppRunOnOsLoginMode(
-      const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
   // Returns true iff it's expected that the app has been, **or is in
   // the process of being**, registered with the OS.
   absl::optional<RunOnOsLoginMode> GetExpectedRunOnOsLoginOsIntegrationState(
-      const AppId& app_id) const;
+      const webapps::AppId& app_id) const;
 
-  bool GetWindowControlsOverlayEnabled(const AppId& app_id) const;
+  bool GetWindowControlsOverlayEnabled(const webapps::AppId& app_id) const;
 
   // Gets the IDs for all apps in `GetApps()`.
-  std::vector<AppId> GetAppIds() const;
+  std::vector<webapps::AppId> GetAppIds() const;
 
   // Gets the IDs for all sub-apps of parent app with id |parent_app_id|.
-  std::vector<AppId> GetAllSubAppIds(const AppId& parent_app_id) const;
+  std::vector<webapps::AppId> GetAllSubAppIds(
+      const webapps::AppId& parent_app_id) const;
 
   // Maps all app IDs to their parent apps' IDs. Maps that do not have a parent
   // are omitted. This query should only be called with an AllAppsLock since all
   // apps are queried for their parent.
-  base::flat_map<AppId, AppId> GetSubAppToParentMap() const;
+  base::flat_map<webapps::AppId, webapps::AppId> GetSubAppToParentMap() const;
 
   // Returns the "scope" field from the app manifest, or infers a scope from the
   // "start_url" field if unavailable. Returns an invalid GURL iff the |app_id|
   // does not refer to an installed web app.
-  GURL GetAppScope(const AppId& app_id) const;
+  GURL GetAppScope(const webapps::AppId& app_id) const;
 
   // Returns whether |url| is in the scope of |app_id|.
-  bool IsUrlInAppScope(const GURL& url, const AppId& app_id) const;
+  bool IsUrlInAppScope(const GURL& url, const webapps::AppId& app_id) const;
 
   // Returns whether |url| is in scope or scope_extensions of |app_id|.
   // Only checks scope if scope_extensions is disabled.
-  bool IsUrlInAppExtendedScope(const GURL& url, const AppId& app_id) const;
+  bool IsUrlInAppExtendedScope(const GURL& url,
+                               const webapps::AppId& app_id) const;
 
   // Returns the strength of matching |url| to the scope and scope_extensions of
   // |app_id|. Returns 0 if not in either.
   // Only checks scope if scope_extensions is disabled.
-  size_t GetAppExtendedScopeScore(const GURL& url, const AppId& app_id) const;
+  size_t GetAppExtendedScopeScore(const GURL& url,
+                                  const webapps::AppId& app_id) const;
 
   // Returns the strength of matching |url_spec| to the scope of |app_id|,
   // returns 0 if not in scope.
   size_t GetUrlInAppScopeScore(const std::string& url_spec,
-                               const AppId& app_id) const;
+                               const webapps::AppId& app_id) const;
 
   // Returns the app id of an app in the registry with the longest scope that is
   // a prefix of |url|, if any.
-  absl::optional<AppId> FindAppWithUrlInScope(const GURL& url) const;
+  absl::optional<webapps::AppId> FindAppWithUrlInScope(const GURL& url) const;
 
   // Returns true if there exists at least one app installed under |scope|.
   bool DoesScopeContainAnyApp(const GURL& scope) const;
 
   // Finds all apps that are installed under |scope|.
-  std::vector<AppId> FindAppsInScope(const GURL& scope) const;
+  std::vector<webapps::AppId> FindAppsInScope(const GURL& scope) const;
 
   // Returns the app id of an installed app in the registry with the longest
   // scope that is a prefix of |url|, if any. If |window_only| is specified,
   // only apps that open in app windows will be considered.
-  absl::optional<AppId> FindInstalledAppWithUrlInScope(
+  absl::optional<webapps::AppId> FindInstalledAppWithUrlInScope(
       const GURL& url,
       bool window_only = false) const;
 
@@ -334,7 +350,7 @@
   bool IsNonLocallyInstalledAppWithUrlInScope(const GURL& url) const;
 
   // Returns whether the app is a shortcut app (as opposed to a PWA).
-  bool IsShortcutApp(const AppId& app_id) const;
+  bool IsShortcutApp(const webapps::AppId& app_id) const;
 
   // Returns true if the app with the specified |start_url| is currently fully
   // locally installed. The provided |start_url| must exactly match the launch
@@ -344,49 +360,51 @@
 
   // Returns whether the app is pending successful navigation in order to
   // complete installation via the ExternallyManagedAppManager.
-  bool IsPlaceholderApp(const AppId& app_id,
+  bool IsPlaceholderApp(const webapps::AppId& app_id,
                         const WebAppManagement::Type source_type) const;
 
   // Returns an |app_id| if there is a placeholder app for |install_url|.
   // Returning a nullopt does not mean that there is no app for |install_url|,
   // just that there is no *placeholder app*.
-  absl::optional<AppId> LookupPlaceholderAppId(
+  absl::optional<webapps::AppId> LookupPlaceholderAppId(
       const GURL& install_url,
       const WebAppManagement::Type source_type) const;
 
-  bool IsSystemApp(const AppId& app_id) const;
+  bool IsSystemApp(const webapps::AppId& app_id) const;
 
   // Computes and returns the DisplayMode, accounting for user preference
   // to launch in a browser window and entries in the web app manifest.
-  DisplayMode GetAppEffectiveDisplayMode(const AppId& app_id) const;
+  DisplayMode GetAppEffectiveDisplayMode(const webapps::AppId& app_id) const;
 
   // Computes and returns the DisplayMode only accounting for
   // entries in the web app manifest.
-  DisplayMode GetEffectiveDisplayModeFromManifest(const AppId& app_id) const;
+  DisplayMode GetEffectiveDisplayModeFromManifest(
+      const webapps::AppId& app_id) const;
 
   // Computes and returns the unhashed app id from entries in the web app
   // manifest.
-  GURL GetComputedManifestId(const AppId& app_id) const;
+  GURL GetComputedManifestId(const webapps::AppId& app_id) const;
 
   // Returns whether the app should be opened in tabbed window mode.
-  bool IsTabbedWindowModeEnabled(const AppId& app_id) const;
+  bool IsTabbedWindowModeEnabled(const webapps::AppId& app_id) const;
 
-  GURL GetAppNewTabUrl(const AppId& app_id) const;
+  GURL GetAppNewTabUrl(const webapps::AppId& app_id) const;
 
   // Returns the URL of the pinned home tab for tabbed apps which have this
   // enabled, otherwise returns nullopt.
-  absl::optional<GURL> GetAppPinnedHomeTabUrl(const AppId& app_id) const;
+  absl::optional<GURL> GetAppPinnedHomeTabUrl(
+      const webapps::AppId& app_id) const;
 
   // Returns the current WebAppOsIntegrationState stored in the web_app DB.
   absl::optional<proto::WebAppOsIntegrationState>
-  GetAppCurrentOsIntegrationState(const AppId& app_id) const;
+  GetAppCurrentOsIntegrationState(const webapps::AppId& app_id) const;
 
   // Returns the StoragePartitionConfig of all StoragePartitions used by
   // |isolated_web_app_id|. Both the primary and any <controlledframe>
   // StoragePartitions will be returned.
   std::vector<content::StoragePartitionConfig>
   GetIsolatedWebAppStoragePartitionConfigs(
-      const AppId& isolated_web_app_id) const;
+      const webapps::AppId& isolated_web_app_id) const;
 
   // Saves a record of the |partition_name| in
   // |isolated_web_app_in_memory_controlled_frame_partitions_|.
@@ -400,21 +418,23 @@
   // Returns true if a web app is set to be the default app to
   // capture links by the user. If an app is not locally installed or is a
   // shortcut, this returns false.
-  bool CapturesLinksInScope(const AppId& app_id) const;
+  bool CapturesLinksInScope(const webapps::AppId& app_id) const;
   // Searches for all apps that can control this url, and chooses the best one
   // that also captures links.
-  absl::optional<AppId> FindAppThatCapturesLinksInScope(const GURL& url) const;
+  absl::optional<webapps::AppId> FindAppThatCapturesLinksInScope(
+      const GURL& url) const;
 
   // Returns a set of app ids that match the scope for user link capturing.
-  std::vector<AppId> GetOverlappingAppsMatchingScope(const AppId& app_id) const;
+  std::vector<webapps::AppId> GetOverlappingAppsMatchingScope(
+      const webapps::AppId& app_id) const;
 
   // Verifies if the scopes of 2 apps match for user link capturing.
-  bool AppScopesMatchForUserLinkCapturing(const AppId& app_id1,
-                                          const AppId& app_id2) const;
+  bool AppScopesMatchForUserLinkCapturing(const webapps::AppId& app_id1,
+                                          const webapps::AppId& app_id2) const;
 
 #if BUILDFLAG(IS_MAC)
-  bool AlwaysShowToolbarInFullscreen(const AppId& app_id) const;
-  void NotifyAlwaysShowToolbarInFullscreenChanged(const AppId& app_id,
+  bool AlwaysShowToolbarInFullscreen(const webapps::AppId& app_id) const;
+  void NotifyAlwaysShowToolbarInFullscreenChanged(const webapps::AppId& app_id,
                                                   bool show);
 #endif
 
@@ -422,28 +442,31 @@
   void RemoveObserver(WebAppRegistrarObserver* observer);
 
   void NotifyWebAppProtocolSettingsChanged();
-  void NotifyWebAppFileHandlerApprovalStateChanged(const AppId& app_id);
+  void NotifyWebAppFileHandlerApprovalStateChanged(
+      const webapps::AppId& app_id);
   void NotifyWebAppsWillBeUpdatedFromSync(
       const std::vector<const WebApp*>& new_apps_state);
-  void NotifyWebAppDisabledStateChanged(const AppId& app_id, bool is_disabled);
+  void NotifyWebAppDisabledStateChanged(const webapps::AppId& app_id,
+                                        bool is_disabled);
   void NotifyWebAppsDisabledModeChanged();
-  void NotifyWebAppLastBadgingTimeChanged(const AppId& app_id,
+  void NotifyWebAppLastBadgingTimeChanged(const webapps::AppId& app_id,
                                           const base::Time& time);
-  void NotifyWebAppLastLaunchTimeChanged(const AppId& app_id,
+  void NotifyWebAppLastLaunchTimeChanged(const webapps::AppId& app_id,
                                          const base::Time& time);
-  void NotifyWebAppFirstInstallTimeChanged(const AppId& app_id,
+  void NotifyWebAppFirstInstallTimeChanged(const webapps::AppId& app_id,
                                            const base::Time& time);
   void NotifyWebAppUserDisplayModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       mojom::UserDisplayMode user_display_mode);
   void NotifyWebAppRunOnOsLoginModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       RunOnOsLoginMode run_on_os_login_mode);
   void NotifyWebAppSettingsPolicyChanged();
 
 #if !BUILDFLAG(IS_CHROMEOS)
-  void NotifyWebAppUserLinkCapturingPreferencesChanged(const AppId& app_id,
-                                                       bool is_preferred);
+  void NotifyWebAppUserLinkCapturingPreferencesChanged(
+      const webapps::AppId& app_id,
+      bool is_preferred);
 #endif  // !BUILDFLAG(IS_CHROMEOS)
 
   // ProfileManagerObserver:
@@ -531,7 +554,7 @@
   // Set (or replace existing) temporary experimental overrides for
   // UserDisplayMode. `overrides` maps app IDs to their overridden value.
   void SetUserDisplayModeOverridesForExperiment(
-      base::flat_map<AppId, mojom::UserDisplayMode> overrides);
+      base::flat_map<webapps::AppId, mojom::UserDisplayMode> overrides);
 #endif
 
   // Returns a dict with debug values for each app in the registry, including
@@ -541,7 +564,7 @@
  protected:
   Profile* profile() const { return profile_; }
 
-  void NotifyWebAppProfileWillBeDeleted(const AppId& app_id);
+  void NotifyWebAppProfileWillBeDeleted(const webapps::AppId& app_id);
 
   Registry& registry() { return registry_; }
   void SetRegistry(Registry&& registry);
@@ -549,7 +572,7 @@
   void CountMutation();
 
   // Gets the IDs for all apps in `app_set`.
-  std::vector<AppId> GetAppIdsForAppSet(const AppSet& app_set) const;
+  std::vector<webapps::AppId> GetAppIdsForAppSet(const AppSet& app_set) const;
 
   bool registry_profile_being_deleted_ = false;
 
@@ -566,13 +589,13 @@
   size_t mutations_count_ = 0;
 #endif
 
-  base::flat_map<AppId, mojom::UserDisplayMode>
+  base::flat_map<webapps::AppId, mojom::UserDisplayMode>
       user_display_mode_overrides_for_experiment_;
 
   // Keeps a record of in-memory (non-persistent) Storage Partitions created by
   // Isolated Web Apps' Controlled Frames. This table will expire on browser
   // shutdown same as in-memory Storage Partitions.
-  base::flat_map<AppId, base::flat_set<std::string>>
+  base::flat_map<webapps::AppId, base::flat_set<std::string>>
       isolated_web_app_in_memory_controlled_frame_partitions_;
 
   base::WeakPtrFactory<WebAppRegistrar> weak_factory_{this};
@@ -587,7 +610,7 @@
 
   void InitRegistry(Registry&& registry);
 
-  WebApp* GetAppByIdMutable(const AppId& app_id);
+  WebApp* GetAppByIdMutable(const webapps::AppId& app_id);
 
   AppSet FilterAppsMutableForTesting(Filter filter);
 
diff --git a/chrome/browser/web_applications/web_app_registrar_observer.h b/chrome/browser/web_applications/web_app_registrar_observer.h
index 49529d5..dfe4cf30 100644
--- a/chrome/browser/web_applications/web_app_registrar_observer.h
+++ b/chrome/browser/web_applications/web_app_registrar_observer.h
@@ -9,6 +9,7 @@
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace base {
 class Time;
@@ -25,7 +26,7 @@
   virtual void OnWebAppsWillBeUpdatedFromSync(
       const std::vector<const WebApp*>& new_apps_state) {}
 
-  virtual void OnWebAppProfileWillBeDeleted(const AppId& app_id) {}
+  virtual void OnWebAppProfileWillBeDeleted(const webapps::AppId& app_id) {}
 
   virtual void OnAppRegistrarDestroyed() = 0;
 
@@ -35,24 +36,25 @@
 
   // Called after the app's access to the File Handling API has changed, e.g. by
   // a user selecting "always allow" in the prompt or after a policy update.
-  virtual void OnWebAppFileHandlerApprovalStateChanged(const AppId& app_id) {}
+  virtual void OnWebAppFileHandlerApprovalStateChanged(
+      const webapps::AppId& app_id) {}
 
   // The disabled status WebApp::chromeos_data().is_disabled of the app backing
   // |app_id| changed.
-  virtual void OnWebAppDisabledStateChanged(const AppId& app_id,
+  virtual void OnWebAppDisabledStateChanged(const webapps::AppId& app_id,
                                             bool is_disabled) {}
   virtual void OnWebAppsDisabledModeChanged() {}
-  virtual void OnWebAppLastBadgingTimeChanged(const AppId& app_id,
+  virtual void OnWebAppLastBadgingTimeChanged(const webapps::AppId& app_id,
                                               const base::Time& time) {}
-  virtual void OnWebAppLastLaunchTimeChanged(const AppId& app_id,
+  virtual void OnWebAppLastLaunchTimeChanged(const webapps::AppId& app_id,
                                              const base::Time& time) {}
-  virtual void OnWebAppFirstInstallTimeChanged(const AppId& app_id,
+  virtual void OnWebAppFirstInstallTimeChanged(const webapps::AppId& app_id,
                                                const base::Time& time) {}
   virtual void OnWebAppUserDisplayModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       mojom::UserDisplayMode user_display_mode) {}
   virtual void OnWebAppRunOnOsLoginModeChanged(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       RunOnOsLoginMode run_on_os_login_mode) {}
 
   // Called after the WebAppSettings policy has been updated. If a policy is set
@@ -60,13 +62,15 @@
   // applied.
   virtual void OnWebAppSettingsPolicyChanged() {}
 
-  virtual void OnAlwaysShowToolbarInFullscreenChanged(const AppId& app_id,
-                                                      bool show) {}
+  virtual void OnAlwaysShowToolbarInFullscreenChanged(
+      const webapps::AppId& app_id,
+      bool show) {}
 
   // Called after the user link capturing preferences have been modified from
   // various Chrome surfaces.
-  virtual void OnWebAppUserLinkCapturingPreferencesChanged(const AppId& app_id,
-                                                           bool is_preferred) {}
+  virtual void OnWebAppUserLinkCapturingPreferencesChanged(
+      const webapps::AppId& app_id,
+      bool is_preferred) {}
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_registrar_unittest.cc b/chrome/browser/web_applications/web_app_registrar_unittest.cc
index 475872d5..66e04cd 100644
--- a/chrome/browser/web_applications/web_app_registrar_unittest.cc
+++ b/chrome/browser/web_applications/web_app_registrar_unittest.cc
@@ -74,7 +74,7 @@
 
   for (int i = 0; i < num_apps; ++i) {
     const auto url = base_url + base::NumberToString(i);
-    const AppId app_id =
+    const webapps::AppId app_id =
         GenerateAppId(/*manifest_id=*/absl::nullopt, GURL(url));
 
     auto web_app = std::make_unique<WebApp>(app_id);
@@ -156,8 +156,8 @@
   WebAppRegistrarMutable& mutable_registrar() { return *registrar_mutable_; }
   WebAppSyncBridge& sync_bridge() { return *sync_bridge_; }
 
-  base::flat_set<AppId> RegisterAppsForTesting(Registry registry) {
-    base::flat_set<AppId> ids;
+  base::flat_set<webapps::AppId> RegisterAppsForTesting(Registry registry) {
+    base::flat_set<webapps::AppId> ids;
 
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
     for (auto& kv : registry) {
@@ -173,22 +173,22 @@
     update->CreateApp(std::move(web_app));
   }
 
-  void UnregisterApp(const AppId& app_id) {
+  void UnregisterApp(const webapps::AppId& app_id) {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
     update->DeleteApp(app_id);
   }
 
   void UnregisterAll() {
     ScopedRegistryUpdate update = sync_bridge().BeginUpdate();
-    for (const AppId& app_id : registrar().GetAppIds()) {
+    for (const webapps::AppId& app_id : registrar().GetAppIds()) {
       update->DeleteApp(app_id);
     }
   }
 
-  AppId InitRegistrarWithApp(std::unique_ptr<WebApp> app) {
+  webapps::AppId InitRegistrarWithApp(std::unique_ptr<WebApp> app) {
     DCHECK(registrar().is_empty());
 
-    AppId app_id = app->app_id();
+    webapps::AppId app_id = app->app_id();
 
     Registry registry;
     registry.emplace(app_id, std::move(app));
@@ -197,16 +197,18 @@
     return app_id;
   }
 
-  base::flat_set<AppId> InitRegistrarWithApps(const std::string& base_url,
-                                              int num_apps) {
+  base::flat_set<webapps::AppId> InitRegistrarWithApps(
+      const std::string& base_url,
+      int num_apps) {
     DCHECK(registrar().is_empty());
 
     Registry registry = CreateRegistryForTesting(base_url, num_apps);
     return InitRegistrarWithRegistry(registry);
   }
 
-  base::flat_set<AppId> InitRegistrarWithRegistry(const Registry& registry) {
-    base::flat_set<AppId> app_ids;
+  base::flat_set<webapps::AppId> InitRegistrarWithRegistry(
+      const Registry& registry) {
+    base::flat_set<webapps::AppId> app_ids;
     for (auto& kv : registry) {
       app_ids.insert(kv.second->app_id());
     }
@@ -246,18 +248,19 @@
 TEST_F(WebAppRegistrarTest, CreateRegisterUnregister) {
   InitSyncBridge();
 
-  EXPECT_EQ(nullptr, registrar().GetAppById(AppId()));
-  EXPECT_FALSE(registrar().GetAppById(AppId()));
+  EXPECT_EQ(nullptr, registrar().GetAppById(webapps::AppId()));
+  EXPECT_FALSE(registrar().GetAppById(webapps::AppId()));
 
   const GURL start_url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  const webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   const std::string name = "Name";
   const std::string description = "Description";
   const GURL scope = GURL("https://example.com/scope");
   const absl::optional<SkColor> theme_color = 0xAABBCCDD;
 
   const GURL start_url2 = GURL("https://example.com/path2");
-  const AppId app_id2 =
+  const webapps::AppId app_id2 =
       GenerateAppId(/*manifest_id=*/absl::nullopt, start_url2);
 
   auto web_app = std::make_unique<WebApp>(app_id);
@@ -333,7 +336,7 @@
 }
 
 TEST_F(WebAppRegistrarTest, InitRegistrarAndDoForEachApp) {
-  base::flat_set<AppId> ids =
+  base::flat_set<webapps::AppId> ids =
       InitRegistrarWithApps("https://example.com/path", 100);
 
   for (const WebApp& web_app : registrar().GetAppsIncludingStubs()) {
@@ -345,7 +348,7 @@
 }
 
 TEST_F(WebAppRegistrarTest, GetAppsIncludingStubsMutable) {
-  base::flat_set<AppId> ids =
+  base::flat_set<webapps::AppId> ids =
       InitRegistrarWithApps("https://example.com/path", 10);
 
   for (WebApp& web_app : mutable_registrar().GetAppsIncludingStubsMutable()) {
@@ -451,7 +454,7 @@
 }
 
 TEST_F(WebAppRegistrarTest, GetApps) {
-  base::flat_set<AppId> ids =
+  base::flat_set<webapps::AppId> ids =
       InitRegistrarWithApps("https://example.com/path", 10);
 
   int not_in_sync_install_count = 0;
@@ -463,12 +466,12 @@
 
   auto web_app_in_sync1 = test::CreateWebApp(GURL("https://example.org/sync1"));
   web_app_in_sync1->SetIsFromSyncAndPendingInstallation(true);
-  const AppId web_app_id_in_sync1 = web_app_in_sync1->app_id();
+  const webapps::AppId web_app_id_in_sync1 = web_app_in_sync1->app_id();
   RegisterApp(std::move(web_app_in_sync1));
 
   auto web_app_in_sync2 = test::CreateWebApp(GURL("https://example.org/sync2"));
   web_app_in_sync2->SetIsFromSyncAndPendingInstallation(true);
-  const AppId web_app_id_in_sync2 = web_app_in_sync2->app_id();
+  const webapps::AppId web_app_id_in_sync2 = web_app_in_sync2->app_id();
   RegisterApp(std::move(web_app_in_sync2));
 
   int all_apps_count = 0;
@@ -498,12 +501,12 @@
 }
 
 TEST_F(WebAppRegistrarTest, WebAppSyncBridge) {
-  base::flat_set<AppId> ids =
+  base::flat_set<webapps::AppId> ids =
       InitRegistrarWithApps("https://example.com/path", 100);
 
   // Add 1 app after Init.
   auto web_app = test::CreateWebApp(GURL("https://example.com/path"));
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   RegisterApp(std::move(web_app));
 
@@ -525,7 +528,8 @@
   InitSyncBridge();
 
   const GURL start_url = GURL("https://example.com/path");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  const webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   const std::string name = "Name";
   const std::string description = "Description";
   const absl::optional<SkColor> theme_color = 0xAABBCCDD;
@@ -609,14 +613,15 @@
   const GURL app2_scope("https://example.com/app-two");
   const GURL app3_scope("https://not-example.com/app");
 
-  const AppId app1_id =
+  const webapps::AppId app1_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app1_scope);
-  const AppId app2_id =
+  const webapps::AppId app2_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app2_scope);
-  const AppId app3_id =
+  const webapps::AppId app3_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app3_scope);
 
-  std::vector<AppId> in_scope = registrar().FindAppsInScope(origin_scope);
+  std::vector<webapps::AppId> in_scope =
+      registrar().FindAppsInScope(origin_scope);
   EXPECT_EQ(0u, in_scope.size());
   EXPECT_FALSE(registrar().DoesScopeContainAnyApp(origin_scope));
   EXPECT_FALSE(registrar().DoesScopeContainAnyApp(app3_scope));
@@ -674,29 +679,29 @@
   const GURL app3_scope("https://not-example.com/app");
   const GURL app4_scope("https://app-four.com/");
 
-  const AppId app1_id =
+  const webapps::AppId app1_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app1_scope);
-  const AppId app2_id =
+  const webapps::AppId app2_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app2_scope);
-  const AppId app3_id =
+  const webapps::AppId app3_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app3_scope);
-  const AppId app4_id =
+  const webapps::AppId app4_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app3_scope);
 
   auto app1 = test::CreateWebApp(app1_scope);
   app1->SetScope(app1_scope);
   RegisterApp(std::move(app1));
 
-  absl::optional<AppId> app2_match =
+  absl::optional<webapps::AppId> app2_match =
       registrar().FindAppWithUrlInScope(app2_scope);
   DCHECK(app2_match);
   EXPECT_EQ(*app2_match, app1_id);
 
-  absl::optional<AppId> app3_match =
+  absl::optional<webapps::AppId> app3_match =
       registrar().FindAppWithUrlInScope(app3_scope);
   EXPECT_FALSE(app3_match);
 
-  absl::optional<AppId> app4_match =
+  absl::optional<webapps::AppId> app4_match =
       registrar().FindAppWithUrlInScope(app4_scope);
   EXPECT_FALSE(app4_match);
 
@@ -713,11 +718,11 @@
   app4->SetIsUninstalling(true);
   RegisterApp(std::move(app4));
 
-  absl::optional<AppId> origin_match =
+  absl::optional<webapps::AppId> origin_match =
       registrar().FindAppWithUrlInScope(origin_scope);
   EXPECT_FALSE(origin_match);
 
-  absl::optional<AppId> app1_match =
+  absl::optional<webapps::AppId> app1_match =
       registrar().FindAppWithUrlInScope(app1_scope);
   DCHECK(app1_match);
   EXPECT_EQ(*app1_match, app1_id);
@@ -746,22 +751,22 @@
   const GURL app2_launch("https://example.com/app-two/launch");
   const GURL app3_launch("https://not-example.com/app/launch");
 
-  const AppId app1_id =
+  const webapps::AppId app1_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app1_launch);
-  const AppId app2_id =
+  const webapps::AppId app2_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app2_launch);
-  const AppId app3_id =
+  const webapps::AppId app3_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app3_launch);
 
   // Implicit scope "https://example.com/app/"
   auto app1 = test::CreateWebApp(app1_launch);
   RegisterApp(std::move(app1));
 
-  absl::optional<AppId> app2_match =
+  absl::optional<webapps::AppId> app2_match =
       registrar().FindAppWithUrlInScope(app2_page);
   EXPECT_FALSE(app2_match);
 
-  absl::optional<AppId> app3_match =
+  absl::optional<webapps::AppId> app3_match =
       registrar().FindAppWithUrlInScope(app3_page);
   EXPECT_FALSE(app3_match);
 
@@ -771,18 +776,18 @@
   auto app3 = test::CreateWebApp(app3_launch);
   RegisterApp(std::move(app3));
 
-  absl::optional<AppId> app1_match =
+  absl::optional<webapps::AppId> app1_match =
       registrar().FindAppWithUrlInScope(app1_page);
   DCHECK(app1_match);
-  EXPECT_EQ(app1_match, absl::optional<AppId>(app1_id));
+  EXPECT_EQ(app1_match, absl::optional<webapps::AppId>(app1_id));
 
   app2_match = registrar().FindAppWithUrlInScope(app2_page);
   DCHECK(app2_match);
-  EXPECT_EQ(app2_match, absl::optional<AppId>(app2_id));
+  EXPECT_EQ(app2_match, absl::optional<webapps::AppId>(app2_id));
 
   app3_match = registrar().FindAppWithUrlInScope(app3_page);
   DCHECK(app3_match);
-  EXPECT_EQ(app3_match, absl::optional<AppId>(app3_id));
+  EXPECT_EQ(app3_match, absl::optional<webapps::AppId>(app3_id));
 }
 
 TEST_F(WebAppRegistrarTest, FindPwaOverShortcut) {
@@ -792,7 +797,7 @@
 
   const GURL app2_scope("https://example.com/app");
   const GURL app2_page("https://example.com/app/specific/page2");
-  const AppId app2_id =
+  const webapps::AppId app2_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, app2_scope);
 
   const GURL app3_launch("https://example.com/app/specific/launch3");
@@ -807,14 +812,14 @@
   auto app3 = test::CreateWebApp(app3_launch);
   RegisterApp(std::move(app3));
 
-  absl::optional<AppId> app2_match =
+  absl::optional<webapps::AppId> app2_match =
       registrar().FindAppWithUrlInScope(app2_page);
   DCHECK(app2_match);
-  EXPECT_EQ(app2_match, absl::optional<AppId>(app2_id));
+  EXPECT_EQ(app2_match, absl::optional<webapps::AppId>(app2_id));
 }
 
 TEST_F(WebAppRegistrarTest, BeginAndCommitUpdate) {
-  base::flat_set<AppId> ids =
+  base::flat_set<webapps::AppId> ids =
       InitRegistrarWithApps("https://example.com/path", 10);
 
   base::test::TestFuture<bool> future;
@@ -850,7 +855,7 @@
 }
 
 TEST_F(WebAppRegistrarTest, CommitEmptyUpdate) {
-  base::flat_set<AppId> ids =
+  base::flat_set<webapps::AppId> ids =
       InitRegistrarWithApps("https://example.com/path", 10);
   const auto initial_registry = database_factory().ReadRegistry();
 
@@ -883,7 +888,7 @@
 }
 
 TEST_F(WebAppRegistrarTest, ScopedRegistryUpdate) {
-  base::flat_set<AppId> ids =
+  base::flat_set<webapps::AppId> ids =
       InitRegistrarWithApps("https://example.com/path", 10);
   const auto initial_registry = database_factory().ReadRegistry();
 
@@ -918,7 +923,8 @@
   InitSyncBridge();
 
   const GURL start_url("https://example.com");
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  const webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
   const WebApp* app = nullptr;
   {
     auto new_app = test::CreateWebApp(start_url);
@@ -982,7 +988,7 @@
   GURL start_url(base::StrCat({chrome::kIsolatedAppScheme,
                                url::kStandardSchemeSeparator, kIwaHostname}));
   auto isolated_web_app = test::CreateWebApp(start_url);
-  const AppId app_id = isolated_web_app->app_id();
+  const webapps::AppId app_id = isolated_web_app->app_id();
 
   isolated_web_app->SetScope(isolated_web_app->start_url());
   isolated_web_app->SetIsolationData(WebApp::IsolationData(
@@ -1009,7 +1015,7 @@
       "isolated-app://"
       "berugqztij5biqquuk3mfwpsaibuegaqcitgfchwuosuofdjabzqaaic");
   auto isolated_web_app = test::CreateWebApp(start_url);
-  const AppId app_id = isolated_web_app->app_id();
+  const webapps::AppId app_id = isolated_web_app->app_id();
 
   isolated_web_app->SetScope(isolated_web_app->start_url());
   isolated_web_app->SetIsolationData(WebApp::IsolationData(
@@ -1032,7 +1038,7 @@
   GURL start_url(base::StrCat({chrome::kIsolatedAppScheme,
                                url::kStandardSchemeSeparator, kIwaHostname}));
   auto isolated_web_app = test::CreateWebApp(start_url);
-  const AppId app_id = isolated_web_app->app_id();
+  const webapps::AppId app_id = isolated_web_app->app_id();
   auto url_info = IsolatedWebAppUrlInfo::Create(start_url);
   ASSERT_TRUE(url_info.has_value());
 
@@ -1062,13 +1068,14 @@
       test::CreateWebApp(GURL("https://example.org/"));
   web_app_in_sync_install->SetIsFromSyncAndPendingInstallation(true);
 
-  const AppId web_app_in_sync_install_id = web_app_in_sync_install->app_id();
+  const webapps::AppId web_app_in_sync_install_id =
+      web_app_in_sync_install->app_id();
   RegisterApp(std::move(web_app_in_sync_install));
 
   // Tests that GetAppIds() excludes web app in sync install:
-  std::vector<AppId> ids = registrar().GetAppIds();
+  std::vector<webapps::AppId> ids = registrar().GetAppIds();
   EXPECT_EQ(100u, ids.size());
-  for (const AppId& app_id : ids) {
+  for (const webapps::AppId& app_id : ids) {
     EXPECT_NE(app_id, web_app_in_sync_install_id);
   }
 
@@ -1089,7 +1096,7 @@
   InitSyncBridge();
 
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   web_app->SetDisplayMode(DisplayMode::kStandalone);
   web_app->SetUserDisplayMode(mojom::UserDisplayMode::kStandalone);
   web_app->SetIsLocallyInstalled(false);
@@ -1109,7 +1116,7 @@
   InitSyncBridge();
 
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   web_app->SetDisplayMode(DisplayMode::kStandalone);
   web_app->SetUserDisplayMode(mojom::UserDisplayMode::kStandalone);
   web_app->SetIsLocallyInstalled(false);
@@ -1125,7 +1132,7 @@
   InitSyncBridge();
 
   std::unique_ptr<WebApp> web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
 
   // Valid manifest must have standalone display mode
   web_app->SetDisplayMode(DisplayMode::kStandalone);
@@ -1146,7 +1153,7 @@
   InitSyncBridge();
 
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   std::vector<DisplayMode> display_mode_overrides;
   display_mode_overrides.push_back(DisplayMode::kFullscreen);
   display_mode_overrides.push_back(DisplayMode::kMinimalUi);
@@ -1171,7 +1178,7 @@
   InitSyncBridge();
 
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   std::vector<DisplayMode> display_mode_overrides;
   display_mode_overrides.push_back(DisplayMode::kFullscreen);
   display_mode_overrides.push_back(DisplayMode::kMinimalUi);
@@ -1194,7 +1201,7 @@
   InitSyncBridge();
 
   auto web_app = test::CreateWebApp();
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   RegisterApp(std::move(web_app));
 
   EXPECT_EQ(false, registrar().GetWindowControlsOverlayEnabled(app_id));
@@ -1218,7 +1225,7 @@
   protocol_handler_info2.url = GURL("http://example.com/test2=%s");
 
   auto web_app = test::CreateWebApp(GURL("https://example.com/path"));
-  const AppId app_id = web_app->app_id();
+  const webapps::AppId app_id = web_app->app_id();
   web_app->SetProtocolHandlers(
       {protocol_handler_info1, protocol_handler_info2});
   RegisterApp(std::move(web_app));
@@ -1236,8 +1243,8 @@
       test::CreateWebApp(GURL("https://start.com"), WebAppManagement::kDefault);
   auto web_app2 = test::CreateWebApp(GURL("https://starter.com"),
                                      WebAppManagement::kPolicy);
-  const AppId app_id1 = web_app1->app_id();
-  const AppId app_id2 = web_app2->app_id();
+  const webapps::AppId app_id1 = web_app1->app_id();
+  const webapps::AppId app_id2 = web_app2->app_id();
   RegisterApp(std::move(web_app1));
   RegisterApp(std::move(web_app2));
 
@@ -1257,7 +1264,7 @@
   default_app->SetDisplayMode(DisplayMode::kStandalone);
   default_app->SetUserDisplayMode(mojom::UserDisplayMode::kBrowser);
 
-  const AppId app_id = default_app->app_id();
+  const webapps::AppId app_id = default_app->app_id();
   const GURL external_app_url("https://example.com/path/default");
 
   Registry registry;
@@ -1284,8 +1291,8 @@
   web_app2->SetIsUserSelectedAppForSupportedLinks(
       /*is_user_selected_app_for_capturing_links=*/true);
 
-  const AppId app_id1 = web_app1->app_id();
-  const AppId app_id2 = web_app2->app_id();
+  const webapps::AppId app_id1 = web_app1->app_id();
+  const webapps::AppId app_id2 = web_app2->app_id();
   RegisterApp(std::move(web_app1));
   RegisterApp(std::move(web_app2));
 
@@ -1309,8 +1316,8 @@
   web_app2->SetIsUserSelectedAppForSupportedLinks(
       /*is_user_selected_app_for_capturing_links=*/true);
 
-  const AppId app_id1 = web_app1->app_id();
-  const AppId app_id2 = web_app2->app_id();
+  const webapps::AppId app_id1 = web_app1->app_id();
+  const webapps::AppId app_id2 = web_app2->app_id();
   RegisterApp(std::move(web_app1));
   RegisterApp(std::move(web_app2));
 
@@ -1330,7 +1337,7 @@
   InitSyncBridge();
 
   auto web_app = test::CreateWebApp(GURL("https://example.com/start"));
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
 
   auto extended_scope_url = GURL("https://example.app");
   auto extended_scope_origin = url::Origin::Create(extended_scope_url);
@@ -1390,7 +1397,7 @@
   InitSyncBridge();
 
   auto web_app = test::CreateWebApp(GURL("https://example.com/path"));
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
   GURL new_tab_url = GURL("https://example.com/path/newtab");
 
   blink::Manifest::NewTabButtonParams new_tab_button_params;
@@ -1409,7 +1416,7 @@
   InitSyncBridge();
 
   auto web_app = test::CreateWebApp(GURL("https://example.com/path"));
-  AppId app_id = web_app->app_id();
+  webapps::AppId app_id = web_app->app_id();
 
   web_app->SetDisplayMode(DisplayMode::kTabbed);
   RegisterApp(std::move(web_app));
@@ -1428,7 +1435,7 @@
   GURL install_url("https://start_install.com/");
   auto web_app1 =
       test::CreateWebApp(GURL("https://start1.com"), WebAppManagement::kPolicy);
-  const AppId app_id1 = web_app1->app_id();
+  const webapps::AppId app_id1 = web_app1->app_id();
   RegisterApp(std::move(web_app1));
   test::AddInstallUrlAndPlaceholderData(
       profile()->GetPrefs(), &sync_bridge(), app_id1, install_url,
@@ -1442,7 +1449,7 @@
   // verify that app shows up as a placeholder.
   auto web_app2 =
       test::CreateWebApp(GURL("https://start2.com"), WebAppManagement::kPolicy);
-  const AppId app_id2 = web_app2->app_id();
+  const webapps::AppId app_id2 = web_app2->app_id();
   RegisterApp(std::move(web_app2));
   test::AddInstallUrlAndPlaceholderData(
       profile()->GetPrefs(), &sync_bridge(), app_id2, install_url,
@@ -1491,9 +1498,9 @@
   const GURL swa_url("chrome://swa/start");
   const GURL uninstalling_url("https://example.com/uninstalling/start");
 
-  AppId example_id;
-  AppId swa_id;
-  AppId uninstalling_id;
+  webapps::AppId example_id;
+  webapps::AppId swa_id;
+  webapps::AppId uninstalling_id;
   WebAppRegistrarMutable registrar(profile());
   {
     Registry registry;
@@ -1561,9 +1568,9 @@
   const GURL swa_url("chrome://swa/start");
   const GURL uninstalling_url("https://example.com/uninstalling/start");
 
-  AppId example_id;
-  AppId swa_id;
-  AppId uninstalling_id;
+  webapps::AppId example_id;
+  webapps::AppId swa_id;
+  webapps::AppId uninstalling_id;
   WebAppRegistrarMutable registrar(profile());
   {
     Registry registry;
diff --git a/chrome/browser/web_applications/web_app_registry_update.cc b/chrome/browser/web_applications/web_app_registry_update.cc
index 9624deb..ab19ba0 100644
--- a/chrome/browser/web_applications/web_app_registry_update.cc
+++ b/chrome/browser/web_applications/web_app_registry_update.cc
@@ -41,7 +41,7 @@
   update_data_->apps_to_create.push_back(std::move(web_app));
 }
 
-void WebAppRegistryUpdate::DeleteApp(const AppId& app_id) {
+void WebAppRegistryUpdate::DeleteApp(const webapps::AppId& app_id) {
   DCHECK(update_data_);
   DCHECK(!app_id.empty());
   DCHECK(registrar_->GetAppById(app_id));
@@ -50,7 +50,7 @@
   update_data_->apps_to_delete.push_back(app_id);
 }
 
-WebApp* WebAppRegistryUpdate::UpdateApp(const AppId& app_id) {
+WebApp* WebAppRegistryUpdate::UpdateApp(const webapps::AppId& app_id) {
   DCHECK(update_data_);
   const WebApp* original_app = registrar_->GetAppById(app_id);
   if (!original_app)
diff --git a/chrome/browser/web_applications/web_app_registry_update.h b/chrome/browser/web_applications/web_app_registry_update.h
index 5b5a8e2..d1138cd 100644
--- a/chrome/browser/web_applications/web_app_registry_update.h
+++ b/chrome/browser/web_applications/web_app_registry_update.h
@@ -12,6 +12,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/types/pass_key.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 
 namespace web_app {
 
@@ -30,7 +31,7 @@
   Apps apps_to_create;
   Apps apps_to_update;
 
-  std::vector<AppId> apps_to_delete;
+  std::vector<webapps::AppId> apps_to_delete;
 
   bool IsEmpty() const;
 
@@ -50,9 +51,9 @@
   // Register a new app.
   void CreateApp(std::unique_ptr<WebApp> web_app);
   // Delete registered app.
-  void DeleteApp(const AppId& app_id);
+  void DeleteApp(const webapps::AppId& app_id);
   // Acquire a mutable existing app to set new field values.
-  WebApp* UpdateApp(const AppId& app_id);
+  WebApp* UpdateApp(const webapps::AppId& app_id);
 
   std::unique_ptr<RegistryUpdateData> TakeUpdateData(
       base::PassKey<WebAppSyncBridge> pass_key);
diff --git a/chrome/browser/web_applications/web_app_run_on_os_login_manager.cc b/chrome/browser/web_applications/web_app_run_on_os_login_manager.cc
index c0b1ec5..93d2ad4 100644
--- a/chrome/browser/web_applications/web_app_run_on_os_login_manager.cc
+++ b/chrome/browser/web_applications/web_app_run_on_os_login_manager.cc
@@ -54,7 +54,7 @@
 void WebAppRunOnOsLoginManager::RunAppsOnOsLogin(AllAppsLock& lock) {
   std::vector<std::string> app_names;
 
-  for (const AppId& app_id : lock.registrar().GetAppIds()) {
+  for (const webapps::AppId& app_id : lock.registrar().GetAppIds()) {
     if (!IsRunOnOsLoginModeEnabledForAutostart(
             lock.registrar().GetAppRunOnOsLoginMode(app_id).value)) {
       continue;
diff --git a/chrome/browser/web_applications/web_app_run_on_os_login_manager_browsertest.cc b/chrome/browser/web_applications/web_app_run_on_os_login_manager_browsertest.cc
index b8108d4..9e70ee2 100644
--- a/chrome/browser/web_applications/web_app_run_on_os_login_manager_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_run_on_os_login_manager_browsertest.cc
@@ -77,7 +77,7 @@
     if (!web_app) {
       return nullptr;
     }
-    AppId app_id = web_app.value();
+    webapps::AppId app_id = web_app.value();
 
     return AppBrowserController::FindForWebApp(*profile(), app_id);
   }
diff --git a/chrome/browser/web_applications/web_app_run_on_os_login_manager_unittest.cc b/chrome/browser/web_applications/web_app_run_on_os_login_manager_unittest.cc
index db49e8b0..b185701e 100644
--- a/chrome/browser/web_applications/web_app_run_on_os_login_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_run_on_os_login_manager_unittest.cc
@@ -27,13 +27,13 @@
 #include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_database_factory.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
 #include "chrome/browser/web_applications/web_app_sync_bridge.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "components/webapps/common/web_app_id.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
 #include "url/gurl.h"
@@ -211,7 +211,7 @@
   }
 
  private:
-  AppId app_id_;
+  webapps::AppId app_id_;
 };
 
 TEST_F(WebAppRunOnOsLoginManagerSimpleSettingsTest, SimpleAppStarted) {
diff --git a/chrome/browser/web_applications/web_app_scope_extensions_browsertest.cc b/chrome/browser/web_applications/web_app_scope_extensions_browsertest.cc
index 1850d82..6630c170 100644
--- a/chrome/browser/web_applications/web_app_scope_extensions_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_scope_extensions_browsertest.cc
@@ -110,7 +110,7 @@
     url_overrides_[manifest_url] = manifest_file;
     url_overrides_[association_url] = association_file;
 
-    AppId app_id = InstallWebAppFromPageAndCloseAppBrowser(
+    webapps::AppId app_id = InstallWebAppFromPageAndCloseAppBrowser(
         browser(),
         primary_server_.GetURL("/web_apps/get_manifest.html?manifest.json"));
 
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc
index 9388321..f10615eb 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.cc
+++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/web_applications/web_app_database.h"
 #include "chrome/browser/web_applications/web_app_database_factory.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_prefs_utils.h"
 #include "chrome/browser/web_applications/web_app_proto_utils.h"
@@ -40,6 +39,7 @@
 #include "components/sync/model/model_type_store.h"
 #include "components/sync/model/mutable_data_batch.h"
 #include "components/sync/protocol/web_app_specifics.pb.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/common/content_features.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
@@ -75,7 +75,7 @@
     DLOG(ERROR) << "ApplySyncDataToApp: start_url parse error.";
     return;
   }
-  ManifestId manifest_id;
+  webapps::ManifestId manifest_id;
   if (sync_data.has_relative_manifest_id()) {
     manifest_id =
         GenerateManifestId(sync_data.relative_manifest_id(), start_url);
@@ -176,7 +176,7 @@
 }
 
 void WebAppSyncBridge::SetAppUserDisplayMode(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     mojom::UserDisplayMode user_display_mode,
     bool is_user_action) {
   if (is_user_action) {
@@ -206,8 +206,9 @@
   registrar_->NotifyWebAppUserDisplayModeChanged(app_id, user_display_mode);
 }
 
-void WebAppSyncBridge::SetAppWindowControlsOverlayEnabled(const AppId& app_id,
-                                                          bool enabled) {
+void WebAppSyncBridge::SetAppWindowControlsOverlayEnabled(
+    const webapps::AppId& app_id,
+    bool enabled) {
   ScopedRegistryUpdate update = BeginUpdate();
   WebApp* web_app = update->UpdateApp(app_id);
   if (web_app) {
@@ -216,7 +217,7 @@
 }
 
 void WebAppSyncBridge::SetAppIsDisabled(AppLock& lock,
-                                        const AppId& app_id,
+                                        const webapps::AppId& app_id,
                                         bool is_disabled) {
   if (!IsChromeOsDataMandatory()) {
     return;
@@ -253,7 +254,7 @@
   registrar_->NotifyWebAppsDisabledModeChanged();
 }
 
-void WebAppSyncBridge::SetAppLastBadgingTime(const AppId& app_id,
+void WebAppSyncBridge::SetAppLastBadgingTime(const webapps::AppId& app_id,
                                              const base::Time& time) {
   {
     ScopedRegistryUpdate update = BeginUpdate();
@@ -265,7 +266,7 @@
   registrar_->NotifyWebAppLastBadgingTimeChanged(app_id, time);
 }
 
-void WebAppSyncBridge::SetAppLastLaunchTime(const AppId& app_id,
+void WebAppSyncBridge::SetAppLastLaunchTime(const webapps::AppId& app_id,
                                             const base::Time& time) {
   {
     ScopedRegistryUpdate update = BeginUpdate();
@@ -277,7 +278,7 @@
   registrar_->NotifyWebAppLastLaunchTimeChanged(app_id, time);
 }
 
-void WebAppSyncBridge::SetAppFirstInstallTime(const AppId& app_id,
+void WebAppSyncBridge::SetAppFirstInstallTime(const webapps::AppId& app_id,
                                               const base::Time& time) {
   {
     ScopedRegistryUpdate update = BeginUpdate();
@@ -289,7 +290,7 @@
   registrar_->NotifyWebAppFirstInstallTimeChanged(app_id, time);
 }
 
-void WebAppSyncBridge::SetAppManifestUpdateTime(const AppId& app_id,
+void WebAppSyncBridge::SetAppManifestUpdateTime(const webapps::AppId& app_id,
                                                 const base::Time& time) {
   {
     ScopedRegistryUpdate update = BeginUpdate();
@@ -300,7 +301,7 @@
   }
 }
 
-void WebAppSyncBridge::SetUserPageOrdinal(const AppId& app_id,
+void WebAppSyncBridge::SetUserPageOrdinal(const webapps::AppId& app_id,
                                           syncer::StringOrdinal page_ordinal) {
   ScopedRegistryUpdate update = BeginUpdate();
   WebApp* web_app = update->UpdateApp(app_id);
@@ -317,7 +318,7 @@
 }
 
 void WebAppSyncBridge::SetUserLaunchOrdinal(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     syncer::StringOrdinal launch_ordinal) {
   ScopedRegistryUpdate update = BeginUpdate();
   // Due to the extensions sync system setting ordinals on sync, this can get
@@ -334,8 +335,9 @@
 }
 
 #if BUILDFLAG(IS_MAC)
-void WebAppSyncBridge::SetAlwaysShowToolbarInFullscreen(const AppId& app_id,
-                                                        bool show) {
+void WebAppSyncBridge::SetAlwaysShowToolbarInFullscreen(
+    const webapps::AppId& app_id,
+    bool show) {
   if (!registrar_->IsInstalled(app_id)) {
     return;
   }
@@ -347,8 +349,9 @@
 }
 #endif
 
-void WebAppSyncBridge::SetAppFileHandlerApprovalState(const AppId& app_id,
-                                                      ApiApprovalState state) {
+void WebAppSyncBridge::SetAppFileHandlerApprovalState(
+    const webapps::AppId& app_id,
+    ApiApprovalState state) {
   {
     ScopedRegistryUpdate update = BeginUpdate();
     update->UpdateApp(app_id)->SetFileHandlerApprovalState(state);
@@ -373,7 +376,7 @@
   // Remove all unchanged apps.
   RegistryUpdateData::Apps changed_apps_to_update;
   for (std::unique_ptr<WebApp>& app_to_update : update_data->apps_to_update) {
-    const AppId& app_id = app_to_update->app_id();
+    const webapps::AppId& app_id = app_to_update->app_id();
     if (*app_to_update != *registrar().GetAppById(app_id)) {
       changed_apps_to_update.push_back(std::move(app_to_update));
     }
@@ -417,8 +420,9 @@
     DCHECK(web_app->manifest_id().is_valid());
   }
 
-  for (const AppId& app_id : update_data.apps_to_delete)
+  for (const webapps::AppId& app_id : update_data.apps_to_delete) {
     DCHECK(registrar_->GetAppById(app_id));
+  }
 #endif
 }
 
@@ -427,7 +431,7 @@
   registrar_->CountMutation();
 
   for (std::unique_ptr<WebApp>& web_app : update_data->apps_to_create) {
-    AppId app_id = web_app->app_id();
+    webapps::AppId app_id = web_app->app_id();
     DCHECK(!registrar_->GetAppById(app_id));
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     // We do not install non-system web apps in Ash when Lacros web apps are
@@ -445,7 +449,7 @@
     // object pointer value (the object's identity) to support stored pointers.
     *original_web_app = std::move(*web_app);
   }
-  for (const AppId& app_id : update_data->apps_to_delete) {
+  for (const webapps::AppId& app_id : update_data->apps_to_delete) {
     auto it = registrar_->registry().find(app_id);
     DCHECK(it != registrar_->registry().end());
     registrar_->registry().erase(it);
@@ -472,7 +476,7 @@
   }
 
   for (const std::unique_ptr<WebApp>& new_state : update_data.apps_to_update) {
-    const AppId& app_id = new_state->app_id();
+    const webapps::AppId& app_id = new_state->app_id();
     // Find the current state of the app to be overritten.
     const WebApp* current_state = registrar_->GetAppById(app_id);
     DCHECK(current_state);
@@ -488,7 +492,7 @@
     }
   }
 
-  for (const AppId& app_id_to_delete : update_data.apps_to_delete) {
+  for (const webapps::AppId& app_id_to_delete : update_data.apps_to_delete) {
     const WebApp* current_state = registrar_->GetAppById(app_id_to_delete);
     DCHECK(current_state);
     // Exclude the app from the sync "view" if IsSynced flag was true.
@@ -529,7 +533,7 @@
 }
 
 void WebAppSyncBridge::OnWebAppUninstallComplete(
-    const AppId& app,
+    const webapps::AppId& app,
     webapps::UninstallResultCode code) {
   base::UmaHistogramBoolean("Webapp.SyncInitiatedUninstallResult",
                             UninstallSucceeded(code));
@@ -543,7 +547,7 @@
 void WebAppSyncBridge::MergeLocalAppsToSync(
     const syncer::EntityChangeList& entity_data,
     syncer::MetadataChangeList* metadata_change_list) {
-  auto sync_server_apps = base::MakeFlatSet<AppId>(
+  auto sync_server_apps = base::MakeFlatSet<webapps::AppId>(
       entity_data, {}, &syncer::EntityChange::storage_key);
 
   for (const WebApp& app : registrar_->GetAppsIncludingStubs()) {
@@ -561,9 +565,9 @@
 void WebAppSyncBridge::PrepareLocalUpdateFromSyncChange(
     const syncer::EntityChange& change,
     RegistryUpdateData* update_local_data,
-    std::vector<AppId>& apps_display_mode_changed) {
+    std::vector<webapps::AppId>& apps_display_mode_changed) {
   // app_id is storage key.
-  const AppId& app_id = change.storage_key();
+  const webapps::AppId& app_id = change.storage_key();
 
   const WebApp* existing_web_app = registrar_->GetAppByIdMutable(app_id);
 
@@ -618,7 +622,7 @@
 
     // Set the manifest id first, as ApplySyncDataToApp verifies that the
     // computed manifest ids match.
-    ManifestId manifest_id;
+    webapps::ManifestId manifest_id;
     if (specifics.has_relative_manifest_id()) {
       manifest_id =
           GenerateManifestId(specifics.relative_manifest_id(), start_url);
@@ -650,7 +654,7 @@
 
 void WebAppSyncBridge::ApplyIncrementalSyncChangesToRegistrar(
     std::unique_ptr<RegistryUpdateData> update_local_data,
-    const std::vector<AppId>& apps_display_mode_changed) {
+    const std::vector<webapps::AppId>& apps_display_mode_changed) {
   if (update_local_data->IsEmpty())
     return;
 
@@ -673,14 +677,14 @@
 
   UpdateRegistrar(std::move(update_local_data));
 
-  for (const AppId& app_id : apps_display_mode_changed) {
+  for (const webapps::AppId& app_id : apps_display_mode_changed) {
     const WebApp* app = registrar_->GetAppById(app_id);
     DCHECK(app->user_display_mode().has_value());
     registrar_->NotifyWebAppUserDisplayModeChanged(
         app_id, app->user_display_mode().value());
   }
 
-  std::vector<AppId> apps_to_delete;
+  std::vector<webapps::AppId> apps_to_delete;
   for (const WebApp& app : registrar_->GetAppsIncludingStubsMutable()) {
     if (app.is_uninstalling())
       apps_to_delete.push_back(app.app_id());
@@ -695,7 +699,7 @@
       uninstall_from_sync_before_registry_update_callback_for_testing_.Run(
           apps_to_delete, callback);
     } else {
-      for (const AppId& app_id : apps_to_delete) {
+      for (const webapps::AppId& app_id : apps_to_delete) {
         command_scheduler_->UninstallWebApp(
             app_id, webapps::WebappUninstallSource::kSync,
             base::BindOnce(callback, app_id));
@@ -723,7 +727,7 @@
   CHECK(change_processor()->IsTrackingMetadata());
 
   auto update_local_data = std::make_unique<RegistryUpdateData>();
-  std::vector<AppId> apps_display_mode_changed;
+  std::vector<webapps::AppId> apps_display_mode_changed;
 
   for (const auto& change : entity_data) {
     DCHECK_NE(change->type(), syncer::EntityChange::ACTION_DELETE);
@@ -756,7 +760,7 @@
   // metadata is invalid and ClearPersistedMetadataIfInvalid() is resetting it.
 
   auto update_local_data = std::make_unique<RegistryUpdateData>();
-  std::vector<AppId> apps_display_mode_changed;
+  std::vector<webapps::AppId> apps_display_mode_changed;
 
   for (const auto& change : entity_changes) {
     PrepareLocalUpdateFromSyncChange(*change, update_local_data.get(),
@@ -782,7 +786,7 @@
                                DataCallback callback) {
   auto data_batch = std::make_unique<syncer::MutableDataBatch>();
 
-  for (const AppId& app_id : storage_keys) {
+  for (const webapps::AppId& app_id : storage_keys) {
     const WebApp* app = registrar_->GetAppById(app_id);
     if (app && app->IsSynced())
       data_batch->Put(app->app_id(), CreateSyncEntityData(*app));
@@ -813,7 +817,7 @@
     return std::string();
   }
 
-  ManifestId manifest_id;
+  webapps::ManifestId manifest_id;
   if (specifics.has_relative_manifest_id()) {
     manifest_id =
         GenerateManifestId(specifics.relative_manifest_id(), start_url);
@@ -845,7 +849,7 @@
 }
 
 void WebAppSyncBridge::SetAppIsLocallyInstalledForTesting(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     bool is_locally_installed) {
   {
     ScopedRegistryUpdate update = BeginUpdate();
@@ -858,7 +862,7 @@
 }
 
 void WebAppSyncBridge::MaybeUninstallAppsPendingUninstall() {
-  std::vector<AppId> apps_uninstalling;
+  std::vector<webapps::AppId> apps_uninstalling;
 
   for (WebApp& app : registrar_->GetAppsIncludingStubsMutable()) {
     if (app.is_uninstalling())
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.h b/chrome/browser/web_applications/web_app_sync_bridge.h
index 0351e00..3a6ad32 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.h
+++ b/chrome/browser/web_applications/web_app_sync_bridge.h
@@ -82,10 +82,10 @@
 
   using CommitCallback = base::OnceCallback<void(bool success)>;
   using RepeatingInstallCallback =
-      base::RepeatingCallback<void(const AppId& app_id,
+      base::RepeatingCallback<void(const webapps::AppId& app_id,
                                    webapps::InstallResultCode code)>;
   using RepeatingUninstallCallback =
-      base::RepeatingCallback<void(const AppId& app_id,
+      base::RepeatingCallback<void(const webapps::AppId& app_id,
                                    webapps::UninstallResultCode code)>;
   // This is the writable API for the registry. Any updates will be written to
   // LevelDb and sync service. There can be only 1 update at a time. The
@@ -107,37 +107,45 @@
 
   void Init(base::OnceClosure callback);
 
-  void SetAppUserDisplayMode(const AppId& app_id,
+  void SetAppUserDisplayMode(const webapps::AppId& app_id,
                              mojom::UserDisplayMode user_display_mode,
                              bool is_user_action);
 
-  void SetAppIsDisabled(AppLock& lock, const AppId& app_id, bool is_disabled);
+  void SetAppIsDisabled(AppLock& lock,
+                        const webapps::AppId& app_id,
+                        bool is_disabled);
 
   void UpdateAppsDisableMode();
 
-  void SetAppLastBadgingTime(const AppId& app_id, const base::Time& time);
+  void SetAppLastBadgingTime(const webapps::AppId& app_id,
+                             const base::Time& time);
 
-  void SetAppLastLaunchTime(const AppId& app_id, const base::Time& time);
+  void SetAppLastLaunchTime(const webapps::AppId& app_id,
+                            const base::Time& time);
 
-  void SetAppFirstInstallTime(const AppId& app_id, const base::Time& time);
+  void SetAppFirstInstallTime(const webapps::AppId& app_id,
+                              const base::Time& time);
 
-  void SetAppManifestUpdateTime(const AppId& app_id, const base::Time& time);
+  void SetAppManifestUpdateTime(const webapps::AppId& app_id,
+                                const base::Time& time);
 
-  void SetAppWindowControlsOverlayEnabled(const AppId& app_id, bool enabled);
+  void SetAppWindowControlsOverlayEnabled(const webapps::AppId& app_id,
+                                          bool enabled);
 
   // These methods are used by extensions::AppSorting, which manages the sorting
   // of web apps on chrome://apps.
-  void SetUserPageOrdinal(const AppId& app_id,
+  void SetUserPageOrdinal(const webapps::AppId& app_id,
                           syncer::StringOrdinal user_page_ordinal);
-  void SetUserLaunchOrdinal(const AppId& app_id,
+  void SetUserLaunchOrdinal(const webapps::AppId& app_id,
                             syncer::StringOrdinal user_launch_ordinal);
 
   // Stores the user's preference for the app's use of the File Handling API.
-  void SetAppFileHandlerApprovalState(const AppId& app_id,
+  void SetAppFileHandlerApprovalState(const webapps::AppId& app_id,
                                       ApiApprovalState state);
 
 #if BUILDFLAG(IS_MAC)
-  void SetAlwaysShowToolbarInFullscreen(const AppId& app_id, bool show);
+  void SetAlwaysShowToolbarInFullscreen(const webapps::AppId& app_id,
+                                        bool show);
 #endif
 
   // An access to read-only registry. Does an upcast to read-only type.
@@ -170,7 +178,7 @@
   }
 
   using RetryIncompleteUninstallsCallback = base::RepeatingCallback<void(
-      const base::flat_set<AppId>& apps_to_uninstall)>;
+      const base::flat_set<webapps::AppId>& apps_to_uninstall)>;
   void SetRetryIncompleteUninstallsCallbackForTesting(
       RetryIncompleteUninstallsCallback callback);
   using InstallWebAppsAfterSyncCallback =
@@ -179,12 +187,12 @@
   void SetInstallWebAppsAfterSyncCallbackForTesting(
       InstallWebAppsAfterSyncCallback callback);
   using UninstallFromSyncCallback =
-      base::RepeatingCallback<void(const std::vector<AppId>& web_apps,
+      base::RepeatingCallback<void(const std::vector<webapps::AppId>& web_apps,
                                    RepeatingUninstallCallback callback)>;
   void SetUninstallFromSyncCallbackForTesting(
       UninstallFromSyncCallback callback);
   WebAppDatabase* GetDatabaseForTesting() const { return database_.get(); }
-  void SetAppIsLocallyInstalledForTesting(const AppId& app_id,
+  void SetAppIsLocallyInstalledForTesting(const webapps::AppId& app_id,
                                           bool is_locally_installed);
 
  private:
@@ -204,7 +212,7 @@
                         Registry registry,
                         std::unique_ptr<syncer::MetadataBatch> metadata_batch);
   void OnDataWritten(CommitCallback callback, bool success);
-  void OnWebAppUninstallComplete(const AppId& app,
+  void OnWebAppUninstallComplete(const webapps::AppId& app,
                                  webapps::UninstallResultCode code);
 
   void ReportErrorToChangeProcessor(const syncer::ModelError& error);
@@ -216,12 +224,12 @@
   void PrepareLocalUpdateFromSyncChange(
       const syncer::EntityChange& change,
       RegistryUpdateData* update_local_data,
-      std::vector<AppId>& apps_display_mode_changed);
+      std::vector<webapps::AppId>& apps_display_mode_changed);
 
   // Update registrar and Install/Uninstall missing/excessive local apps.
   void ApplyIncrementalSyncChangesToRegistrar(
       std::unique_ptr<RegistryUpdateData> update_local_data,
-      const std::vector<AppId>& apps_display_mode_changed);
+      const std::vector<webapps::AppId>& apps_display_mode_changed);
 
   void MaybeUninstallAppsPendingUninstall();
   void MaybeInstallAppsFromSyncAndPendingInstallation();
diff --git a/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc b/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
index 0623dc1..35a986fc 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
+++ b/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
@@ -46,7 +46,8 @@
 
 using AppsList = std::vector<std::unique_ptr<WebApp>>;
 
-void RemoveWebAppFromAppsList(AppsList* apps_list, const AppId& app_id) {
+void RemoveWebAppFromAppsList(AppsList* apps_list,
+                              const webapps::AppId& app_id) {
   base::EraseIf(*apps_list, [app_id](const std::unique_ptr<WebApp>& app) {
     return app->app_id() == app_id;
   });
@@ -99,7 +100,8 @@
 
 std::unique_ptr<WebApp> CreateWebAppWithSyncOnlyFields(const std::string& url) {
   const GURL start_url(url);
-  const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
+  const webapps::AppId app_id =
+      GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
 
   auto web_app = std::make_unique<WebApp>(app_id);
   web_app->AddSource(WebAppManagement::kSync);
@@ -121,7 +123,7 @@
 }
 
 void InsertAppIntoRegistry(Registry* registry, std::unique_ptr<WebApp> app) {
-  AppId app_id = app->app_id();
+  webapps::AppId app_id = app->app_id();
   ASSERT_FALSE(base::Contains(*registry, app_id));
   registry->emplace(std::move(app_id), std::move(app));
 }
@@ -254,7 +256,7 @@
 
     sync_bridge().SetUninstallFromSyncCallbackForTesting(
         base::BindLambdaForTesting(
-            [&](const std::vector<AppId>& apps_to_uninstall,
+            [&](const std::vector<webapps::AppId>& apps_to_uninstall,
                 WebAppSyncBridge::RepeatingUninstallCallback callback) {
               ADD_FAILURE();
             }));
@@ -609,10 +611,10 @@
 
   sync_bridge().SetUninstallFromSyncCallbackForTesting(
       base::BindLambdaForTesting(
-          [&](const std::vector<AppId>& apps_to_uninstall,
+          [&](const std::vector<webapps::AppId>& apps_to_uninstall,
               WebAppSyncBridge::RepeatingUninstallCallback callback) {
             EXPECT_EQ(5ul, apps_to_uninstall.size());
-            for (const AppId& app_to_uninstall : apps_to_uninstall) {
+            for (const webapps::AppId& app_to_uninstall : apps_to_uninstall) {
               // The app must be registered.
               const WebApp* app = registrar().GetAppById(app_to_uninstall);
               // Sync expects that the apps are deleted by the delegate.
@@ -665,12 +667,12 @@
   EXPECT_CALL(processor(), Delete(_, _)).Times(0);
 
   base::RunLoop run_loop;
-  std::vector<AppId> to_uninstall;
+  std::vector<webapps::AppId> to_uninstall;
   WebAppSyncBridge::RepeatingUninstallCallback uninstall_complete_callback;
 
   sync_bridge().SetUninstallFromSyncCallbackForTesting(
       base::BindLambdaForTesting(
-          [&](const std::vector<AppId>& apps_to_uninstall,
+          [&](const std::vector<webapps::AppId>& apps_to_uninstall,
               WebAppSyncBridge::RepeatingUninstallCallback callback) {
             to_uninstall = apps_to_uninstall;
             uninstall_complete_callback = callback;
@@ -684,7 +686,7 @@
   EXPECT_EQ(5ul, to_uninstall.size());
 
   EXPECT_TRUE(IsDatabaseRegistryEqualToRegistrar());
-  for (const AppId& app_to_uninstall : to_uninstall) {
+  for (const webapps::AppId& app_to_uninstall : to_uninstall) {
     const WebApp* app = registrar().GetAppById(app_to_uninstall);
     EXPECT_TRUE(app);
     EXPECT_TRUE(app->is_uninstalling());
@@ -1262,7 +1264,7 @@
 
 TEST_F(WebAppSyncBridgeTest, RetryIncompleteUninstalls) {
   AppsList initial_registry_apps = CreateAppsList("https://example.com/", 5);
-  std::vector<AppId> initial_app_ids;
+  std::vector<webapps::AppId> initial_app_ids;
   for (std::unique_ptr<WebApp>& app : initial_registry_apps) {
     app->SetUserDisplayMode(mojom::UserDisplayMode::kBrowser);
     app->SetIsUninstalling(true);
@@ -1274,7 +1276,7 @@
   base::RunLoop run_loop;
   sync_bridge().SetRetryIncompleteUninstallsCallbackForTesting(
       base::BindLambdaForTesting(
-          [&](const base::flat_set<AppId>& apps_to_uninstall) {
+          [&](const base::flat_set<webapps::AppId>& apps_to_uninstall) {
             EXPECT_EQ(apps_to_uninstall.size(), 5ul);
             EXPECT_THAT(apps_to_uninstall, ::testing::UnorderedElementsAreArray(
                                                apps_to_uninstall));
diff --git a/chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.cc b/chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.cc
index 96a05a6..31024c43 100644
--- a/chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.cc
+++ b/chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.cc
@@ -12,7 +12,7 @@
 
 namespace web_app {
 
-absl::optional<AppId> GetAppIdForSystemApp(
+absl::optional<webapps::AppId> GetAppIdForSystemApp(
     const WebAppRegistrar& registrar,
     const ash::SystemWebAppDelegateMap& delegates,
     ash::SystemWebAppType type) {
@@ -31,7 +31,7 @@
 absl::optional<ash::SystemWebAppType> GetSystemAppTypeForAppId(
     const WebAppRegistrar& registrar,
     const ash::SystemWebAppDelegateMap& delegates,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   const WebApp* web_app = registrar.GetAppById(app_id);
   if (!web_app || !web_app->client_data().system_web_app_data.has_value()) {
     return absl::nullopt;
@@ -54,7 +54,7 @@
 
 bool IsSystemWebApp(const WebAppRegistrar& registrar,
                     const ash::SystemWebAppDelegateMap& delegates,
-                    const AppId& app_id) {
+                    const webapps::AppId& app_id) {
   return GetSystemAppTypeForAppId(registrar, delegates, app_id).has_value();
 }
 
diff --git a/chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.h b/chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.h
index 7ed992a..24cede7d 100644
--- a/chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.h
+++ b/chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.h
@@ -8,6 +8,7 @@
 #include "ash/webui/system_apps/public/system_web_app_type.h"
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate_map.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
@@ -15,7 +16,7 @@
 class WebAppRegistrar;
 
 // Returns the app id for the given System App |type|.
-absl::optional<AppId> GetAppIdForSystemApp(
+absl::optional<webapps::AppId> GetAppIdForSystemApp(
     const WebAppRegistrar& registrar,
     const ash::SystemWebAppDelegateMap& delegates,
     ash::SystemWebAppType type);
@@ -24,12 +25,12 @@
 absl::optional<ash::SystemWebAppType> GetSystemAppTypeForAppId(
     const WebAppRegistrar& registrar,
     const ash::SystemWebAppDelegateMap& delegates,
-    const AppId& app_id);
+    const webapps::AppId& app_id);
 
 // Returns whether |app_id| points to an installed System App.
 bool IsSystemWebApp(const WebAppRegistrar& registrar,
                     const ash::SystemWebAppDelegateMap& delegates,
-                    const AppId& app_id);
+                    const webapps::AppId& app_id);
 
 }  // namespace web_app
 
diff --git a/chrome/browser/web_applications/web_app_tab_helper.cc b/chrome/browser/web_applications/web_app_tab_helper.cc
index 3abdee222..ae2724a 100644
--- a/chrome/browser/web_applications/web_app_tab_helper.cc
+++ b/chrome/browser/web_applications/web_app_tab_helper.cc
@@ -31,7 +31,8 @@
   }
 }
 
-const AppId* WebAppTabHelper::GetAppId(content::WebContents* web_contents) {
+const webapps::AppId* WebAppTabHelper::GetAppId(
+    content::WebContents* web_contents) {
   auto* tab_helper = WebAppTabHelper::FromWebContents(web_contents);
   if (!tab_helper)
     return nullptr;
@@ -65,7 +66,7 @@
   return *launch_queue_;
 }
 
-void WebAppTabHelper::SetAppId(absl::optional<AppId> app_id) {
+void WebAppTabHelper::SetAppId(absl::optional<webapps::AppId> app_id) {
   // Empty string should not be used to indicate "no app ID".
   DCHECK(!app_id || !app_id->empty());
   DCHECK(!app_id || provider_->registrar_unsafe().IsInstalled(*app_id) ||
@@ -74,7 +75,7 @@
     return;
   }
 
-  absl::optional<AppId> previous_app_id = std::move(app_id_);
+  absl::optional<webapps::AppId> previous_app_id = std::move(app_id_);
   app_id_ = std::move(app_id);
 
   OnAssociatedAppChanged(previous_app_id, app_id_);
@@ -140,16 +141,17 @@
   return provider_->ui_manager().IsInAppWindow(web_contents());
 }
 
-void WebAppTabHelper::OnWebAppInstalled(const AppId& installed_app_id) {
+void WebAppTabHelper::OnWebAppInstalled(
+    const webapps::AppId& installed_app_id) {
   // Check if current web_contents url is in scope for the newly installed app.
-  absl::optional<AppId> app_id =
+  absl::optional<webapps::AppId> app_id =
       FindAppWithUrlInScope(web_contents()->GetURL());
   if (app_id == installed_app_id)
     SetAppId(app_id);
 }
 
 void WebAppTabHelper::OnWebAppWillBeUninstalled(
-    const AppId& uninstalled_app_id) {
+    const webapps::AppId& uninstalled_app_id) {
   if (app_id_ == uninstalled_app_id)
     SetAppId(absl::nullopt);
 }
@@ -160,8 +162,8 @@
 }
 
 void WebAppTabHelper::OnAssociatedAppChanged(
-    const absl::optional<AppId>& previous_app_id,
-    const absl::optional<AppId>& new_app_id) {
+    const absl::optional<webapps::AppId>& previous_app_id,
+    const absl::optional<webapps::AppId>& new_app_id) {
   provider_->ui_manager().NotifyOnAssociatedAppChanged(
       web_contents(), previous_app_id, new_app_id);
 
@@ -210,7 +212,7 @@
       url, base::DoNothing());
 }
 
-absl::optional<AppId> WebAppTabHelper::FindAppWithUrlInScope(
+absl::optional<webapps::AppId> WebAppTabHelper::FindAppWithUrlInScope(
     const GURL& url) const {
   return provider_->registrar_unsafe().FindAppWithUrlInScope(url);
 }
diff --git a/chrome/browser/web_applications/web_app_tab_helper.h b/chrome/browser/web_applications/web_app_tab_helper.h
index 2af4a4907..085ea128 100644
--- a/chrome/browser/web_applications/web_app_tab_helper.h
+++ b/chrome/browser/web_applications/web_app_tab_helper.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -34,14 +35,14 @@
 
   // Retrieves the WebAppTabHelper's app ID off |web_contents|, returns nullptr
   // if there is no tab helper or app ID.
-  static const AppId* GetAppId(content::WebContents* web_contents);
+  static const webapps::AppId* GetAppId(content::WebContents* web_contents);
 
   explicit WebAppTabHelper(content::WebContents* web_contents);
   WebAppTabHelper(const WebAppTabHelper&) = delete;
   WebAppTabHelper& operator=(const WebAppTabHelper&) = delete;
   ~WebAppTabHelper() override;
 
-  void SetAppId(absl::optional<AppId> app_id);
+  void SetAppId(absl::optional<webapps::AppId> app_id);
   const base::UnguessableToken& GetAudioFocusGroupIdForTesting() const;
 
   bool acting_as_app() const { return acting_as_app_; }
@@ -70,15 +71,17 @@
   bool IsInAppWindow() const;
 
   // WebAppInstallManagerObserver:
-  void OnWebAppInstalled(const AppId& installed_app_id) override;
-  void OnWebAppWillBeUninstalled(const AppId& uninstalled_app_id) override;
+  void OnWebAppInstalled(const webapps::AppId& installed_app_id) override;
+  void OnWebAppWillBeUninstalled(
+      const webapps::AppId& uninstalled_app_id) override;
   void OnWebAppInstallManagerDestroyed() override;
 
   void ResetAppId();
 
   // Runs any logic when the associated app is added, changed or removed.
-  void OnAssociatedAppChanged(const absl::optional<AppId>& previous_app_id,
-                              const absl::optional<AppId>& new_app_id);
+  void OnAssociatedAppChanged(
+      const absl::optional<webapps::AppId>& previous_app_id,
+      const absl::optional<webapps::AppId>& new_app_id);
 
   // Updates the audio focus group id based on the current web app.
   void UpdateAudioFocusGroupId();
@@ -86,10 +89,10 @@
   // Triggers a reinstall of a placeholder app for |url|.
   void ReinstallPlaceholderAppIfNecessary(const GURL& url);
 
-  absl::optional<AppId> FindAppWithUrlInScope(const GURL& url) const;
+  absl::optional<webapps::AppId> FindAppWithUrlInScope(const GURL& url) const;
 
   // WebApp associated with this tab.
-  absl::optional<AppId> app_id_;
+  absl::optional<webapps::AppId> app_id_;
 
   // True when the associated `WebContents` is acting as an app. Specifically,
   // this should only be true if `app_id_` is non empty, and the WebContents was
diff --git a/chrome/browser/web_applications/web_app_translation_manager.cc b/chrome/browser/web_applications/web_app_translation_manager.cc
index 3176b815..56ba6e1aa 100644
--- a/chrome/browser/web_applications/web_app_translation_manager.cc
+++ b/chrome/browser/web_applications/web_app_translation_manager.cc
@@ -88,7 +88,7 @@
 
 bool DeleteTranslationsBlocking(scoped_refptr<FileUtilsWrapper> utils,
                                 const base::FilePath& web_apps_directory,
-                                const AppId& app_id) {
+                                const webapps::AppId& app_id) {
   if (!utils->CreateDirectory(web_apps_directory)) {
     return false;
   }
@@ -102,7 +102,7 @@
 bool WriteTranslationsBlocking(
     scoped_refptr<FileUtilsWrapper> utils,
     const base::FilePath& web_apps_directory,
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     base::flat_map<Locale, blink::Manifest::TranslationItem> translations) {
   if (!utils->CreateDirectory(web_apps_directory)) {
     return false;
@@ -146,7 +146,7 @@
 }
 
 void WebAppTranslationManager::WriteTranslations(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::flat_map<Locale, blink::Manifest::TranslationItem>&
         translations,
     WriteCallback callback) {
@@ -171,7 +171,7 @@
       std::move(callback));
 }
 
-void WebAppTranslationManager::DeleteTranslations(const AppId& app_id,
+void WebAppTranslationManager::DeleteTranslations(const webapps::AppId& app_id,
                                                   WriteCallback callback) {
   if (!base::FeatureList::IsEnabled(
           blink::features::kWebAppEnableTranslations)) {
@@ -203,7 +203,7 @@
   const std::string& locale = g_browser_process->GetApplicationLocale();
 
   for (const auto& id_to_translations : proto.id_to_translations_map()) {
-    const AppId& app_id = id_to_translations.first;
+    const webapps::AppId& app_id = id_to_translations.first;
 
     for (const auto& locale_to_overrides :
          id_to_translations.second.locale_to_overrides_map()) {
@@ -218,7 +218,8 @@
   std::move(callback).Run(translation_cache_);
 }
 
-std::string WebAppTranslationManager::GetTranslatedName(const AppId& app_id) {
+std::string WebAppTranslationManager::GetTranslatedName(
+    const webapps::AppId& app_id) {
   auto it = translation_cache_.find(app_id);
   if (it != translation_cache_.end() && it->second.name) {
     return it->second.name.value();
@@ -227,7 +228,7 @@
 }
 
 std::string WebAppTranslationManager::GetTranslatedDescription(
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   auto it = translation_cache_.find(app_id);
   if (it != translation_cache_.end() && it->second.description) {
     return it->second.description.value();
diff --git a/chrome/browser/web_applications/web_app_translation_manager.h b/chrome/browser/web_applications/web_app_translation_manager.h
index 5f2e797b..7f18117 100644
--- a/chrome/browser/web_applications/web_app_translation_manager.h
+++ b/chrome/browser/web_applications/web_app_translation_manager.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/web_applications/file_utils_wrapper.h"
 #include "chrome/browser/web_applications/proto/web_app_translations.pb.h"
 #include "chrome/browser/web_applications/web_app_id.h"
+#include "components/webapps/common/web_app_id.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
 
 namespace web_app {
@@ -29,7 +30,7 @@
 class WebAppTranslationManager {
  public:
   using ReadCallback = base::OnceCallback<void(
-      const std::map<AppId, blink::Manifest::TranslationItem>& cache)>;
+      const std::map<webapps::AppId, blink::Manifest::TranslationItem>& cache)>;
   using WriteCallback = base::OnceCallback<void(bool success)>;
 
   explicit WebAppTranslationManager(Profile* profile);
@@ -41,20 +42,20 @@
   void Start();
 
   void WriteTranslations(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const base::flat_map<Locale, blink::Manifest::TranslationItem>&
           translations,
       WriteCallback callback);
-  void DeleteTranslations(const AppId& app_id, WriteCallback callback);
+  void DeleteTranslations(const webapps::AppId& app_id, WriteCallback callback);
   void ReadTranslations(ReadCallback callback);
 
   // Returns the translated web app name, if available in the browser's locale,
   // otherwise returns an empty string.
-  std::string GetTranslatedName(const AppId& app_id);
+  std::string GetTranslatedName(const webapps::AppId& app_id);
 
   // Returns the translated web app description, if available in the browser's
   // locale, otherwise returns an empty string.
-  std::string GetTranslatedDescription(const AppId& app_id);
+  std::string GetTranslatedDescription(const webapps::AppId& app_id);
 
   // TODO(crbug.com/1212519): Add a method to get the short_name.
 
@@ -64,7 +65,7 @@
   raw_ptr<WebAppProvider> provider_ = nullptr;
   base::FilePath web_apps_directory_;
   // Cache of the translations on disk for the current device language.
-  std::map<AppId, blink::Manifest::TranslationItem> translation_cache_;
+  std::map<webapps::AppId, blink::Manifest::TranslationItem> translation_cache_;
 
   base::WeakPtrFactory<WebAppTranslationManager> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/web_applications/web_app_translation_manager_unittest.cc b/chrome/browser/web_applications/web_app_translation_manager_unittest.cc
index 78a795467..7601d3a8 100644
--- a/chrome/browser/web_applications/web_app_translation_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_translation_manager_unittest.cc
@@ -35,7 +35,7 @@
 
  protected:
   void AwaitWriteTranslations(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const base::flat_map<Locale, blink::Manifest::TranslationItem>&
           translations) {
     base::RunLoop run_loop;
@@ -47,7 +47,7 @@
     run_loop.Run();
   }
 
-  void AwaitDeleteTranslations(const AppId& app_id) {
+  void AwaitDeleteTranslations(const webapps::AppId& app_id) {
     base::RunLoop run_loop;
     translation_manager().DeleteTranslations(
         app_id, base::BindLambdaForTesting([&](bool success) {
@@ -57,11 +57,13 @@
     run_loop.Run();
   }
 
-  std::map<AppId, blink::Manifest::TranslationItem> AwaitReadTranslations() {
+  std::map<webapps::AppId, blink::Manifest::TranslationItem>
+  AwaitReadTranslations() {
     base::RunLoop run_loop;
-    std::map<AppId, blink::Manifest::TranslationItem> result;
+    std::map<webapps::AppId, blink::Manifest::TranslationItem> result;
     translation_manager().ReadTranslations(base::BindLambdaForTesting(
-        [&](const std::map<AppId, blink::Manifest::TranslationItem>& cache) {
+        [&](const std::map<webapps::AppId, blink::Manifest::TranslationItem>&
+                cache) {
           result = cache;
           run_loop.Quit();
         }));
@@ -84,12 +86,14 @@
   auto app_info1 = std::make_unique<WebAppInstallInfo>();
   app_info1->start_url = GURL("https://example.com/path");
   app_info1->title = u"App1 name";
-  const AppId app_id1 = test::InstallWebApp(profile(), std::move(app_info1));
+  const webapps::AppId app_id1 =
+      test::InstallWebApp(profile(), std::move(app_info1));
 
   auto app_info2 = std::make_unique<WebAppInstallInfo>();
   app_info2->start_url = GURL("https://example.com/path2");
   app_info2->title = u"App2 name";
-  const AppId app_id2 = test::InstallWebApp(profile(), std::move(app_info2));
+  const webapps::AppId app_id2 =
+      test::InstallWebApp(profile(), std::move(app_info2));
 
   g_browser_process->SetApplicationLocale("en");
 
@@ -122,7 +126,7 @@
 
   // Read translations for the current language.
   {
-    std::map<AppId, blink::Manifest::TranslationItem> cache =
+    std::map<webapps::AppId, blink::Manifest::TranslationItem> cache =
         AwaitReadTranslations();
     ASSERT_EQ(cache.size(), static_cast<size_t>(2));
     EXPECT_EQ(cache.find(app_id1)->second, item1);
@@ -159,7 +163,7 @@
 
   // Read translations to ensure web_app1 deleted.
   {
-    std::map<AppId, blink::Manifest::TranslationItem> cache =
+    std::map<webapps::AppId, blink::Manifest::TranslationItem> cache =
         AwaitReadTranslations();
     ASSERT_EQ(cache.size(), static_cast<size_t>(1));
     EXPECT_EQ(cache.find(app_id2)->second, item3);
@@ -170,7 +174,8 @@
   auto app_info1 = std::make_unique<WebAppInstallInfo>();
   app_info1->start_url = GURL("https://example.com/path");
   app_info1->title = u"App1 name";
-  const AppId app_id1 = test::InstallWebApp(profile(), std::move(app_info1));
+  const webapps::AppId app_id1 =
+      test::InstallWebApp(profile(), std::move(app_info1));
 
   g_browser_process->SetApplicationLocale("en");
 
@@ -229,7 +234,7 @@
   app_info->translations = translations;
 
   // Install app
-  AppId app_id = test::InstallWebApp(profile(), std::move(app_info));
+  webapps::AppId app_id = test::InstallWebApp(profile(), std::move(app_info));
 
   // Check translations are stored
   EXPECT_EQ(provider().translation_manager().GetTranslatedName(app_id),
diff --git a/chrome/browser/web_applications/web_app_ui_manager.cc b/chrome/browser/web_applications/web_app_ui_manager.cc
index de2c5f39..df1df7a 100644
--- a/chrome/browser/web_applications/web_app_ui_manager.cc
+++ b/chrome/browser/web_applications/web_app_ui_manager.cc
@@ -38,7 +38,7 @@
 
 // static
 apps::AppLaunchParams WebAppUiManager::CreateAppLaunchParamsWithoutWindowConfig(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     const base::CommandLine& command_line,
     const base::FilePath& current_directory,
     const absl::optional<GURL>& url_handler_launch_url,
@@ -104,7 +104,7 @@
 }
 
 void WebAppUiManager::NotifyReadyToCommitNavigation(
-    const AppId& app_id,
+    const webapps::AppId& app_id,
     content::NavigationHandle* navigation_handle) {
   for (WebAppUiManagerObserver& observer : observers_)
     observer.OnReadyToCommitNavigation(app_id, navigation_handle);
diff --git a/chrome/browser/web_applications/web_app_ui_manager.h b/chrome/browser/web_applications/web_app_ui_manager.h
index 749d53e3..ae3dc36 100644
--- a/chrome/browser/web_applications/web_app_ui_manager.h
+++ b/chrome/browser/web_applications/web_app_ui_manager.h
@@ -21,6 +21,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/webapps/browser/uninstall_result_code.h"
+#include "components/webapps/common/web_app_id.h"
 #include "ui/gfx/native_widget_types.h"
 
 class Browser;
@@ -58,7 +59,7 @@
   // navigation is about to commit in a web app identified by `app_id`
   // (including navigations in sub frames).
   virtual void OnReadyToCommitNavigation(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       content::NavigationHandle* navigation_handle) {}
 
   // Called when the WebAppUiManager is about to be destroyed.
@@ -91,7 +92,7 @@
   // which is expected to be populated later when using `LaunchWebApp`
   // with `kOverrideWithWebAppConfig`.
   static apps::AppLaunchParams CreateAppLaunchParamsWithoutWindowConfig(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       const base::CommandLine& command_line,
       const base::FilePath& current_directory,
       const absl::optional<GURL>& url_handler_launch_url,
@@ -110,44 +111,44 @@
   // A safe downcast.
   virtual WebAppUiManagerImpl* AsImpl() = 0;
 
-  virtual size_t GetNumWindowsForApp(const AppId& app_id) = 0;
+  virtual size_t GetNumWindowsForApp(const webapps::AppId& app_id) = 0;
 
   // Close app windows. Does not affect tabs in a non-app browser.
-  virtual void CloseAppWindows(const AppId& app_id) = 0;
+  virtual void CloseAppWindows(const webapps::AppId& app_id) = 0;
 
-  virtual void NotifyOnAllAppWindowsClosed(const AppId& app_id,
+  virtual void NotifyOnAllAppWindowsClosed(const webapps::AppId& app_id,
                                            base::OnceClosure callback) = 0;
 
   void AddObserver(WebAppUiManagerObserver* observer);
   void RemoveObserver(WebAppUiManagerObserver* observer);
   void NotifyReadyToCommitNavigation(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       content::NavigationHandle* navigation_handle);
 
   virtual bool CanAddAppToQuickLaunchBar() const = 0;
-  virtual void AddAppToQuickLaunchBar(const AppId& app_id) = 0;
-  virtual bool IsAppInQuickLaunchBar(const AppId& app_id) const = 0;
+  virtual void AddAppToQuickLaunchBar(const webapps::AppId& app_id) = 0;
+  virtual bool IsAppInQuickLaunchBar(const webapps::AppId& app_id) const = 0;
 
   // Returns whether |web_contents| is in a web app window belonging to
   // |app_id|, or any web app window if |app_id| is nullptr.
   virtual bool IsInAppWindow(content::WebContents* web_contents,
-                             const AppId* app_id = nullptr) const = 0;
+                             const webapps::AppId* app_id = nullptr) const = 0;
   virtual void NotifyOnAssociatedAppChanged(
       content::WebContents* web_contents,
-      const absl::optional<AppId>& previous_app_id,
-      const absl::optional<AppId>& new_app_id) const = 0;
+      const absl::optional<webapps::AppId>& previous_app_id,
+      const absl::optional<webapps::AppId>& new_app_id) const = 0;
 
-  virtual bool CanReparentAppTabToWindow(const AppId& app_id,
+  virtual bool CanReparentAppTabToWindow(const webapps::AppId& app_id,
                                          bool shortcut_created) const = 0;
   virtual void ReparentAppTabToWindow(content::WebContents* contents,
-                                      const AppId& app_id,
+                                      const webapps::AppId& app_id,
                                       bool shortcut_created) = 0;
 
   // Shows the pre-launch dialog for a file handling web app launch. The user
   // can allow or block the launch.
   virtual void ShowWebAppFileLaunchDialog(
       const std::vector<base::FilePath>& file_paths,
-      const web_app::AppId& app_id,
+      const webapps::AppId& app_id,
       WebAppLaunchAcceptanceCallback launch_callback) = 0;
 
   virtual void ShowWebAppIdentityUpdateDialog(
@@ -162,7 +163,7 @@
       AppIdentityDialogCallback callback) = 0;
 
   // Show the settings UI for the given app.
-  virtual void ShowWebAppSettings(const AppId& app_id) = 0;
+  virtual void ShowWebAppSettings(const webapps::AppId& app_id) = 0;
 
   // This launches the web app in the appropriate configuration, the behavior of
   // which depends on the given configuration here and the configuration of the
@@ -180,8 +181,8 @@
   // Migrates launcher state, such as parent folder id, position in App Launcher
   // and pin position on the shelf from one app to another app.
   // Avoids migrating if the to_app_id is already pinned.
-  virtual void MigrateLauncherState(const AppId& from_app_id,
-                                    const AppId& to_app_id,
+  virtual void MigrateLauncherState(const webapps::AppId& from_app_id,
+                                    const webapps::AppId& to_app_id,
                                     base::OnceClosure callback) = 0;
 
   // Displays a notification for web apps launched on login via the RunOnOsLogin
@@ -204,7 +205,7 @@
   // |parent_window| is nullptr. Use this API if a Browser window needs to be
   // passed in along with an UninstallCompleteCallback.
   virtual void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       BrowserWindow* parent_window,
       UninstallCompleteCallback callback) = 0;
@@ -212,7 +213,7 @@
   // Use this API if a gfx::NativeWindow needs to be passed in along with an
   // UninstallCompleteCallback.
   virtual void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       gfx::NativeWindow parent_window,
       UninstallCompleteCallback callback) = 0;
@@ -220,7 +221,7 @@
   // Use this API if a gfx::NativeWindow needs to be passed in along with a
   // UninstallCompleteCallback and an UninstallScheduledCallback.
   virtual void PresentUserUninstallDialog(
-      const AppId& app_id,
+      const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source,
       gfx::NativeWindow parent_window,
       UninstallCompleteCallback callback,
diff --git a/chrome/browser/web_applications/web_app_utils.cc b/chrome/browser/web_applications/web_app_utils.cc
index 83a80b4..43a8f762 100644
--- a/chrome/browser/web_applications/web_app_utils.cc
+++ b/chrome/browser/web_applications/web_app_utils.cc
@@ -121,7 +121,7 @@
   // the `web_app_provider` and supplies the icon to the web_page via jscript.
   static void FetchAndPopulateIcon(content::WebContents* web_contents,
                                    WebAppProvider* web_app_provider,
-                                   const AppId& app_id) {
+                                   const webapps::AppId& app_id) {
     new AppIconFetcherTask(web_contents, web_app_provider, app_id);
   }
 
@@ -130,7 +130,7 @@
  private:
   AppIconFetcherTask(content::WebContents* web_contents,
                      WebAppProvider* web_app_provider,
-                     const AppId& app_id)
+                     const webapps::AppId& app_id)
       : WebContentsObserver(web_contents) {
     DCHECK(web_contents);
     // For best results, this should be of equal (or slightly higher) value than
@@ -401,7 +401,7 @@
 
 base::FilePath GetManifestResourcesDirectoryForApp(
     const base::FilePath& web_apps_root_directory,
-    const AppId& app_id) {
+    const webapps::AppId& app_id) {
   return GetManifestResourcesDirectory(web_apps_root_directory)
       .AppendASCII(app_id);
 }
@@ -480,7 +480,7 @@
 
 std::tuple<std::u16string, size_t>
 GetFileTypeAssociationsHandledByWebAppForDisplay(Profile* profile,
-                                                 const AppId& app_id) {
+                                                 const webapps::AppId& app_id) {
   auto* provider = WebAppProvider::GetForLocalAppsUnchecked(profile);
   if (!provider)
     return {};
@@ -602,12 +602,12 @@
                                                  kUserUninstallableSources);
 }
 
-AppId GetAppIdFromAppSettingsUrl(const GURL& url) {
+webapps::AppId GetAppIdFromAppSettingsUrl(const GURL& url) {
   // App Settings page is served under chrome://app-settings/<app-id>.
   // url.path() returns "/<app-id>" with a leading slash.
   std::string path = url.path();
   if (path.size() <= 1)
-    return AppId();
+    return webapps::AppId();
   return path.substr(1);
 }
 
@@ -686,7 +686,7 @@
   }
 
   WebAppRegistrar& web_app_registrar = web_app_provider->registrar_unsafe();
-  const absl::optional<AppId> app_id =
+  const absl::optional<webapps::AppId> app_id =
       web_app_registrar.FindAppWithUrlInScope(url);
   if (!app_id.has_value()) {
     return nullptr;
diff --git a/chrome/browser/web_applications/web_app_utils.h b/chrome/browser/web_applications/web_app_utils.h
index f98d4e6..2dc9e24 100644
--- a/chrome/browser/web_applications/web_app_utils.h
+++ b/chrome/browser/web_applications/web_app_utils.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
+#include "components/webapps/common/web_app_id.h"
 #include "content/public/common/alternative_error_page_override_info.mojom-forward.h"
 
 class GURL;
@@ -87,7 +88,7 @@
 // Returns per-app directory name to store manifest resources.
 base::FilePath GetManifestResourcesDirectoryForApp(
     const base::FilePath& web_apps_root_directory,
-    const AppId& app_id);
+    const webapps::AppId& app_id);
 
 base::FilePath GetWebAppsTempDirectory(
     const base::FilePath& web_apps_root_directory);
@@ -118,7 +119,7 @@
 // accepted.
 std::tuple<std::u16string, size_t /*count*/>
 GetFileTypeAssociationsHandledByWebAppForDisplay(Profile* profile,
-                                                 const AppId& app_id);
+                                                 const webapps::AppId& app_id);
 
 // As above, but returns the extensions handled by the app as a vector of
 // strings.
@@ -134,7 +135,7 @@
 bool CanUserUninstallWebApp(WebAppManagementTypes sources);
 
 // Extracts app_id from chrome://app-settings/<app-id> URL path.
-AppId GetAppIdFromAppSettingsUrl(const GURL& url);
+webapps::AppId GetAppIdFromAppSettingsUrl(const GURL& url);
 
 // Returns whether `url` is in scope `scope`. False if scope is invalid.
 bool IsInScope(const GURL& url, const GURL& scope);
@@ -161,7 +162,7 @@
 
 // Generates an appropriate path for a new web app profile. This does not create
 // the profile.
-base::FilePath GenerateWebAppProfilePath(const AppId& app_id);
+base::FilePath GenerateWebAppProfilePath(const webapps::AppId& app_id);
 
 enum class ExperimentalWebAppIsolationMode {
   kDisabled,
diff --git a/chrome/browser/webapps/web_app_offline_browsertest.cc b/chrome/browser/webapps/web_app_offline_browsertest.cc
index 5ca1eaf..5aeb588 100644
--- a/chrome/browser/webapps/web_app_offline_browsertest.cc
+++ b/chrome/browser/webapps/web_app_offline_browsertest.cc
@@ -69,11 +69,11 @@
   }
 
   // Start a web app without a service worker and disconnect.
-  web_app::AppId StartWebAppAndDisconnect(content::WebContents* web_contents,
+  webapps::AppId StartWebAppAndDisconnect(content::WebContents* web_contents,
                                           base::StringPiece relative_url) {
     GURL target_url(embedded_test_server()->GetURL(relative_url));
     web_app::NavigateToURLAndWait(browser(), target_url);
-    web_app::AppId app_id = web_app::test::InstallPwaForCurrentUrl(browser());
+    webapps::AppId app_id = web_app::test::InstallPwaForCurrentUrl(browser());
     WebAppIconWaiter(browser()->profile(), app_id).Wait();
     std::unique_ptr<content::URLLoaderInterceptor> interceptor =
         content::URLLoaderInterceptor::SetupRequestFailForURL(
@@ -93,7 +93,7 @@
         browser()->profile(), target_url);
     web_app::NavigateToURLAndWait(browser(), target_url);
     registration_waiter.AwaitRegistration();
-    web_app::AppId app_id = web_app::test::InstallPwaForCurrentUrl(browser());
+    webapps::AppId app_id = web_app::test::InstallPwaForCurrentUrl(browser());
     WebAppIconWaiter(browser()->profile(), app_id).Wait();
     std::unique_ptr<content::URLLoaderInterceptor> interceptor =
         content::URLLoaderInterceptor::SetupRequestFailForURL(
@@ -464,7 +464,7 @@
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   ExpectUniqueSample(net::ERR_INTERNET_DISCONNECTED, 0);
-  web_app::AppId app_id =
+  webapps::AppId app_id =
       StartWebAppAndDisconnect(web_contents, "/banners/no-sw-with-colors.html");
 
   SyncHistograms();
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 84ccacd..71c39f3a 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1695642859-d3b4cb97f8b03116a8b3633926415bb8e17a76be.profdata
+chrome-android64-main-1695664785-44d72b2e8d4b94ba4d5911b7d5829c079851df59.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 4ede68b..9c20be4 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1695642859-76c2f6628943cff7f17ceed3b11866b13922fc55.profdata
+chrome-mac-main-1695664785-37a0b1feeb020f3cc7b25bdf7c42cae5fe9ea65f.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index f89160f..f440d33 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1695642859-aa00bc0d8d65275522c4ee34625dbc91e5df0d49.profdata
+chrome-win-arm64-main-1695664785-0d5f9c725b42dfae2bf853216e66461ce6d2c242.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 4e693d1..29254c3 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1695642859-52ad812765f5b29b3f0cafc08d6c428b5d343a58.profdata
+chrome-win32-main-1695653701-02bbfb651cab302ec6d42833e801ab28ce50f3ab.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index e083f6c..631600c 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1695642859-915cf304f7d743d87ee91c223f6cbf918ea216f9.profdata
+chrome-win64-main-1695653701-0f1ba024ea31314714fd860d2eab5d2c64deb139.profdata
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 506dba0..203854c1 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -797,6 +797,12 @@
 // This flag is only relevant for Windows currently.
 const char kNoNetworkProfileWarning[] = "no-network-profile-warning";
 
+// Whether this process should PrefetchVirtualMemory on the contents of
+// Chrome.dll. This warms up the pages in memory to speed up startup but might
+// not be required in later renderers and/or GPU. For experiment info see
+// crbug.com/1350257.
+const char kNoPreReadMainDll[] = "no-pre-read-main-dll";
+
 // Used in combination with kNotificationLaunchId to specify the inline reply
 // entered in the toast in the Windows Action Center.
 const char kNotificationInlineReply[] = "notification-inline-reply";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index eabdb36..3939a1c4 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -251,6 +251,7 @@
 extern const char kFromInstaller[];
 extern const char kHideIcons[];
 extern const char kNoNetworkProfileWarning[];
+extern const char kNoPreReadMainDll[];
 extern const char kNotificationInlineReply[];
 extern const char kNotificationLaunchId[];
 extern const char kPrefetchArgumentBrowserBackground[];
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc
index 206f7b94..ff9e892 100644
--- a/chrome/renderer/autofill/form_autofill_browsertest.cc
+++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -2345,6 +2345,8 @@
   ASSERT_NE(nullptr, frame);
 
   WebFormControlElement element = GetFormControlElementById("element");
+  element.SetSelectionRange(1, 4);
+
   FormFieldData result1;
   WebFormControlElementToFormField(WebFormElement(), element, nullptr,
                                    EXTRACT_NONE, &result1);
@@ -2352,20 +2354,24 @@
   FormFieldData expected;
   expected.form_control_type = "text";
   expected.max_length = WebInputElement::DefaultMaxLength();
-
   expected.id_attribute = u"element";
   expected.name = expected.id_attribute;
+
   expected.value.clear();
   EXPECT_FORM_FIELD_DATA_EQUALS(expected, result1);
+  EXPECT_EQ(0u, result1.selection_start);
+  EXPECT_EQ(0u, result1.selection_end);
 
   FormFieldData result2;
   WebFormControlElementToFormField(WebFormElement(), element, nullptr,
                                    EXTRACT_VALUE, &result2);
 
-  expected.id_attribute = u"element";
-  expected.name = expected.id_attribute;
   expected.value = u"value";
   EXPECT_FORM_FIELD_DATA_EQUALS(expected, result2);
+  EXPECT_EQ(1u, result2.selection_start);
+  EXPECT_EQ(4u, result2.selection_end);
+  EXPECT_EQ(u"alu", result2.GetSelection());
+  EXPECT_EQ(u"alu", result2.GetSelectionAsStringView());
 }
 
 // We should be able to extract a text field with autocomplete="off".
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ea3246e3..62ef159 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -331,6 +331,7 @@
     "//components/user_education/common",
     "//components/user_manager",
     "//components/webapps/browser:browser",
+    "//components/webapps/common",
     "//ui/webui",
   ]
 
@@ -2665,7 +2666,6 @@
       "base/web_ui_mocha_browser_test_browsertest.cc",
       "data/webui/async_gen.cc",
       "data/webui/async_gen.h",
-      "data/webui/certificate_viewer_ui_test-inl.h",
       "data/webui/chrome_send_browsertest.cc",
       "data/webui/chrome_send_browsertest.h",
       "data/webui/mojo/mojo_file_system_access_browsertest.cc",
@@ -3094,7 +3094,6 @@
       sources -= [
         "../browser/invalidation/profile_invalidation_provider_factory_browsertest.cc",
         "../browser/net/nss_context_chromeos_browsertest.cc",
-        "data/webui/certificate_viewer_ui_test-inl.h",
       ]
     }
 
@@ -3131,26 +3130,24 @@
     if (include_js_tests) {
       deps += [ "//chrome/test/data/webui:browser_tests" ]
     }
-    if (include_js2gtest_tests) {
-      deps += [ "//chrome/test/data/webui:browser_tests_js_webui" ]
-      if (is_chromeos_ash) {
-        deps += [
-          "//ash/webui/color_internals:browser_tests_js",
-          "//ash/webui/eche_app_ui:browser_tests_js",
-          "//ash/webui/help_app_ui:browser_tests_js",
-          "//ash/webui/media_app_ui:browser_tests_js",
-          "//ash/webui/system_apps:browser_tests",
-          "//ash/webui/system_extensions_internals_ui:browser_tests_js",
-          "//chrome/test/data/webui:browser_tests_js_mojo_lite_webui",
-          "//chrome/test/data/webui:browser_tests_js_mojo_webui",
-          "//chromeos/ash/components/human_presence:browser_tests_js",
-        ]
+    if (include_js2gtest_tests && is_chromeos_ash) {
+      deps += [
+        "//ash/webui/color_internals:browser_tests_js",
+        "//ash/webui/eche_app_ui:browser_tests_js",
+        "//ash/webui/help_app_ui:browser_tests_js",
+        "//ash/webui/media_app_ui:browser_tests_js",
+        "//ash/webui/system_apps:browser_tests",
+        "//ash/webui/system_extensions_internals_ui:browser_tests_js",
+        "//chrome/test/data/webui:browser_tests_js_mojo_lite_webui",
+        "//chrome/test/data/webui:browser_tests_js_mojo_webui",
+        "//chrome/test/data/webui:browser_tests_js_webui",
+        "//chromeos/ash/components/human_presence:browser_tests_js",
+      ]
 
-        data_deps += [ "//chrome/test/data/webui:browser_tests_js_webui" ]
+      data_deps += [ "//chrome/test/data/webui:browser_tests_js_webui" ]
 
-        if (!is_official_build) {
-          deps += [ "//ash/webui/sample_system_web_app_ui:browser_tests_js" ]
-        }
+      if (!is_official_build) {
+        deps += [ "//ash/webui/sample_system_web_app_ui:browser_tests_js" ]
       }
     }
 
@@ -5470,6 +5467,7 @@
       "//components/soda:constants",
       "//components/user_manager:user_manager",
       "//components/webapps/browser",
+      "//components/webapps/common",
       "//services/preferences/public/cpp:cpp",
       "//ui/display:test_support",
       "//ui/events:test_support",
@@ -6731,6 +6729,7 @@
     "//components/variations/service:service",
     "//components/vector_icons",
     "//components/version_info:generate_version_info",
+    "//components/webapps/common",
     "//components/webauthn/core/browser:browser",
     "//components/webrtc",
     "//content/public/app",
@@ -7681,6 +7680,7 @@
       "../browser/ui/webui/settings/site_settings_helper_unittest.cc",
       "../browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler_unittest.cc",
       "../browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc",
+      "../browser/ui/webui/side_panel/performance_controls/performance_page_handler_unittest.cc",
       "../browser/ui/webui/side_panel/reading_list/reading_list_page_handler_unittest.cc",
       "../browser/ui/webui/side_panel/user_notes/user_notes_page_handler_unittest.cc",
       "../browser/ui/webui/signin/login_ui_service_unittest.cc",
@@ -10042,6 +10042,7 @@
       "//components/sync:test_support",
       "//components/user_manager",
       "//components/webapps/browser",
+      "//components/webapps/common",
       "//content/public/browser",
       "//extensions/buildflags",
       "//google_apis",
@@ -10453,6 +10454,7 @@
       "//components/user_education/common",
       "//components/user_education/test",
       "//components/webapps/browser:test_support",
+      "//components/webapps/common",
       "//components/webauthn/core/browser:test_support",
       "//content/test:browsertest_support",
       "//content/test:test_support",
@@ -10658,6 +10660,7 @@
         "//components/power_bookmarks/core:features",
         "//components/privacy_sandbox/privacy_sandbox_attestations",
         "//components/privacy_sandbox/privacy_sandbox_attestations:test_support",
+        "//components/user_education/common:events",
         "//components/user_education/views",
         "//components/user_education/webui",
         "//components/user_notes:features",
@@ -11207,6 +11210,7 @@
     "//components/signin/public/identity_manager:test_support",
     "//components/sync",
     "//components/sync:test_support",
+    "//components/webapps/common",
     "//content/public/browser",
     "//content/test:test_support",
     "//net",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/browser/tab/MockTab.java b/chrome/test/android/javatests/src/org/chromium/chrome/browser/tab/MockTab.java
index 9d2a4e6..b68f4b6 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/browser/tab/MockTab.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/browser/tab/MockTab.java
@@ -6,7 +6,6 @@
 
 import androidx.annotation.Nullable;
 
-import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.url.GURL;
@@ -45,13 +44,6 @@
         return tab;
     }
 
-    public static TabImpl initializeWithCriticalPersistedTabData(
-            TabImpl tab, CriticalPersistedTabData criticalPersistedTabData) {
-        tab.getUserDataHost().setUserData(CriticalPersistedTabData.class, criticalPersistedTabData);
-        tab.initialize(null, null, null, null, null, false, null, false);
-        return tab;
-    }
-
     /**
      * Constructor for id and incognito attribute. Tests often need to initialize
      * these two fields only.
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 65e7573..fb73acc4 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -59,6 +59,7 @@
     "side_panel/bookmarks/sp_bookmarks_browsertest.cc",
     "side_panel/commerce/commerce_browsertest.cc",
     "side_panel/customize_chrome/customize_chrome_browsertest.cc",
+    "side_panel/performance_controls/performance_controls_browsertest.cc",
     "side_panel/read_anything/read_anything_browsertest.cc",
     "side_panel/user_notes/user_notes_browsertest.cc",
     "sync_internals/sync_internals_browsertest.cc",
@@ -91,6 +92,10 @@
     sources += [ "print_preview/print_preview_browsertest.cc" ]
   }
 
+  if (enable_webui_certificate_viewer) {
+    sources += [ "certificate_viewer_dialog_browsertest.cc" ]
+  }
+
   if (is_chromeos_ash) {
     sources +=
         [ "chromeos/personalization_app/personalization_app_browsertest.cc" ]
@@ -206,33 +211,18 @@
     }
   }
 
-  js2gtest("browser_tests_js_webui") {
-    test_type = "webui"
+  if (is_chromeos_ash) {
+    js2gtest("browser_tests_js_webui") {
+      test_type = "webui"
 
-    # Javascript sources. These are combined with the .cc files in the GYP build
-    # and are handled by a rule, but in the GN build they're in a separate
-    # action so need to be separated out.
-    sources = [
-      "assertions.js",
-      "async_gen.js",
-      "js2gtest_browsertest.js",
-    ]
-
-    gen_include_files = [ "polymer_browser_test_base.js" ]
-
-    deps = [
-      "//build:branding_buildflags",
-      "//build/config/coverage:buildflags",
-      "//chrome/browser/ui",
-      "//crypto:buildflags",
-      "//services/network/public/cpp",
-      "//skia",
-    ]
-
-    if (is_chromeos_ash) {
-      sources += [
+      # Javascript sources. These are combined with the .cc files in the GYP
+      # build and are handled by a rule, but in the GN build they're in a
+      # separate action so need to be separated out.
+      sources = [
         "../../../browser/resources/chromeos/login/security_token_pin_browsertest.js",
         "../../../browser/ui/webui/ash/certificate_manager_dialog_browsertest.js",
+        "assertions.js",
+        "async_gen.js",
         "chromeos/account_manager/account_manager_browsertest.js",
         "chromeos/arc_account_picker/arc_account_picker_browsertest.js",
         "chromeos/ash_common/ash_common_browsertest.js",
@@ -255,25 +245,32 @@
         "chromeos/sys_internals/sys_internals_browsertest.js",
         "cr_components/chromeos/cr_components_chromeos_v3_browsertest.js",
         "js/i18n_process_test.js",
+        "js2gtest_browsertest.js",
         "settings/chromeos/os_settings_browsertest.js",
       ]
-    }
 
-    if (enable_webui_certificate_viewer) {
-      sources += [ "certificate_viewer_dialog_browsertest.js" ]
-    }
-    if (is_cfm) {
-      sources += [
-        "chromeos/chromebox_for_meetings/cfm_network_settings_browsertest.js",
+      gen_include_files = [ "polymer_browser_test_base.js" ]
+
+      deps = [
+        "//build:branding_buildflags",
+        "//build/config/coverage:buildflags",
+        "//chrome/browser/ui",
+        "//crypto:buildflags",
+        "//services/network/public/cpp",
+        "//skia",
       ]
+
+      if (is_cfm) {
+        sources += [
+          "chromeos/chromebox_for_meetings/cfm_network_settings_browsertest.js",
+        ]
+      }
+
+      data = [ "//ui/webui/resources/js/load_time_data_deprecated.js" ]
+
+      defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
     }
 
-    data = [ "//ui/webui/resources/js/load_time_data_deprecated.js" ]
-
-    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
-  }
-
-  if (is_chromeos_ash) {
     js2gtest("browser_tests_js_mojo_lite_webui") {
       test_type = "mojo_lite_webui"
 
diff --git a/chrome/test/data/webui/certificate_viewer_dialog_browsertest.cc b/chrome/test/data/webui/certificate_viewer_dialog_browsertest.cc
new file mode 100644
index 0000000..d7538af
--- /dev/null
+++ b/chrome/test/data/webui/certificate_viewer_dialog_browsertest.cc
@@ -0,0 +1,101 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "chrome/browser/certificate_viewer.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/certificate_viewer_webui.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/base/web_ui_mocha_browser_test.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/cert/x509_util.h"
+#include "net/test/test_certificate_data.h"
+
+// Test framework for
+// chrome/test/data/webui/certificate_viewer_dialog_browsertest.js.
+class CertificateViewerUITest : public WebUIMochaBrowserTest {
+ protected:
+  CertificateViewerUITest() {
+    // Set a loadable URL so that loading the initial tab doesn't fail.
+    // Certificate viewer tests run in a constrained dialog containing the
+    // certificate viewer WebContents that is on top of this initial tab.
+    set_test_loader_host(chrome::kChromeUIDefaultHost);
+  }
+
+  void SubstituteWebContents(content::WebContents** out_new_contents) override {
+    std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs = GetCerts();
+    ASSERT_TRUE(certs.back());
+
+    content::WebContents* dialog_contents =
+        ShowCertificateViewer(std::move(certs));
+    ASSERT_TRUE(dialog_contents);
+    *out_new_contents = dialog_contents;
+  }
+
+  virtual std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> GetCerts() {
+    std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs;
+    certs.push_back(
+        net::x509_util::CreateCryptoBuffer(base::make_span(google_der)));
+    return certs;
+  }
+
+ private:
+  content::WebContents* ShowCertificateViewer(
+      std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs) {
+    if (!browser() || !browser()->window()) {
+      return nullptr;
+    }
+
+    CertificateViewerDialog* dialog = CertificateViewerDialog::ShowConstrained(
+        std::move(certs), /*cert_nicknames=*/{},
+        browser()->tab_strip_model()->GetActiveWebContents(),
+        browser()->window()->GetNativeWindow());
+
+    content::WebContents* webui_webcontents = dialog->webui_->GetWebContents();
+    EXPECT_TRUE(content::WaitForLoadStop(webui_webcontents));
+    webui_webcontents->GetPrimaryMainFrame()->SetWebUIProperty(
+        "expectedUrl", chrome::kChromeUICertificateViewerURL);
+    return webui_webcontents;
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(CertificateViewerUITest, DialogURL) {
+  RunTestWithoutTestLoader("certificate_viewer_dialog_test.js",
+                           "mocha.grep('DialogURL').run()");
+}
+
+IN_PROC_BROWSER_TEST_F(CertificateViewerUITest, CommonName) {
+  RunTestWithoutTestLoader("certificate_viewer_dialog_test.js",
+                           "mocha.grep('CommonName').run()");
+}
+
+IN_PROC_BROWSER_TEST_F(CertificateViewerUITest, Details) {
+  RunTestWithoutTestLoader("certificate_viewer_dialog_test.js",
+                           "mocha.grep('Details').run()");
+}
+
+class CertificateViewerUIInvalidCertTest : public CertificateViewerUITest {
+ protected:
+  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> GetCerts() override {
+    const uint8_t kInvalid[] = {42, 42, 42, 42, 42};
+    std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs;
+    certs.push_back(
+        net::x509_util::CreateCryptoBuffer(base::make_span(kInvalid)));
+    return certs;
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(CertificateViewerUIInvalidCertTest, InvalidCert) {
+  RunTestWithoutTestLoader("certificate_viewer_dialog_test.js",
+                           "mocha.grep('InvalidCert').run()");
+}
diff --git a/chrome/test/data/webui/certificate_viewer_dialog_browsertest.js b/chrome/test/data/webui/certificate_viewer_dialog_browsertest.js
deleted file mode 100644
index 3acea8d..0000000
--- a/chrome/test/data/webui/certificate_viewer_dialog_browsertest.js
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * Test fixture for generated tests.
- * @extends {testing.Test}
- */
-function CertificateViewerUITest() {}
-
-CertificateViewerUITest.prototype = {
-  __proto__: testing.Test.prototype,
-
-  /** @override */
-  isAsync: true,
-
-  /** @override */
-  extraLibraries: [
-    '//third_party/mocha/mocha.js',
-    '//chrome/test/data/webui/mocha_adapter.js',
-  ],
-
-  /**
-   * Define the C++ fixture class and include it.
-   * @type {?string}
-   * @override
-   */
-  typedefCppFixture: 'CertificateViewerUITest',
-
-  /**
-   * Show the certificate viewer dialog.
-   */
-  testGenPreamble: function() {
-    GEN('ShowCertificateViewerGoogleCert();');
-  },
-};
-
-var CertificateViewerUIInvalidCertTest = class extends CertificateViewerUITest {
-  get testGenPreamble() {
-    return () => {
-      GEN('ShowCertificateViewerInvalidCert();');
-    };
-  }
-};
-
-// Helper for loading the Mocha test file as a JS module. Not using
-// test_loader.html, as the test code needs to be loaded in the context of the
-// dialog triggered with the ShowCertificateViewer() C++ call above.
-async function loadTestModule() {
-  const {getTrustedScriptURL} =
-      await import('chrome://resources/js/static_types.js');
-  const s = document.createElement('script');
-  s.type = 'module';
-  s.src =
-      getTrustedScriptURL`chrome://webui-test/certificate_viewer_dialog_test.js`;
-  document.body.appendChild(s);
-  return new Promise(function(resolve, reject) {
-    s.addEventListener('load', () => resolve());
-  });
-}
-
-// Include the bulk of c++ code.
-// Certificate viewer UI tests are disabled on platforms with native certificate
-// viewers.
-GEN('#include "chrome/test/data/webui/certificate_viewer_ui_test-inl.h"');
-GEN('');
-
-// Constructors and destructors must be provided in .cc to prevent clang errors.
-GEN('CertificateViewerUITest::CertificateViewerUITest() {}');
-GEN('CertificateViewerUITest::~CertificateViewerUITest() {}');
-
-TEST_F('CertificateViewerUITest', 'DialogURL', function() {
-  loadTestModule().then(() => {
-    mocha.grep('DialogURL').run();
-  });
-});
-
-TEST_F('CertificateViewerUITest', 'CommonName', function() {
-  loadTestModule().then(() => {
-    mocha.grep('CommonName').run();
-  });
-});
-
-TEST_F('CertificateViewerUITest', 'Details', function() {
-  loadTestModule().then(() => {
-    mocha.grep('Details').run();
-  });
-});
-
-TEST_F('CertificateViewerUIInvalidCertTest', 'InvalidCert', function() {
-  loadTestModule().then(() => {
-    mocha.grep('InvalidCert').run();
-  });
-});
diff --git a/chrome/test/data/webui/certificate_viewer_dialog_test.js b/chrome/test/data/webui/certificate_viewer_dialog_test.js
index 1d9d563..cb14c72 100644
--- a/chrome/test/data/webui/certificate_viewer_dialog_test.js
+++ b/chrome/test/data/webui/certificate_viewer_dialog_test.js
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {assertEquals, assertFalse, assertLT, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
 /**
diff --git a/chrome/test/data/webui/certificate_viewer_ui_test-inl.h b/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
deleted file mode 100644
index 1e1aa7e..0000000
--- a/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2012 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_DATA_WEBUI_CERTIFICATE_VIEWER_UI_TEST_INL_H_
-#define CHROME_TEST_DATA_WEBUI_CERTIFICATE_VIEWER_UI_TEST_INL_H_
-
-#include "chrome/browser/certificate_viewer.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/webui/certificate_viewer_webui.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "chrome/test/base/web_ui_browser_test.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_utils.h"
-#include "net/cert/x509_util.h"
-#include "net/test/test_certificate_data.h"
-
-// Test framework for
-// chrome/test/data/webui/certificate_viewer_dialog_browsertest.js.
-class CertificateViewerUITest : public WebUIBrowserTest {
- public:
-  CertificateViewerUITest();
-  ~CertificateViewerUITest() override;
-
- protected:
-  void ShowCertificateViewerGoogleCert();
-  void ShowCertificateViewerInvalidCert();
-  void ShowCertificateViewer(std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs);
-};
-
-void CertificateViewerUITest::ShowCertificateViewerGoogleCert() {
-  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs;
-  certs.push_back(
-      net::x509_util::CreateCryptoBuffer(base::make_span(google_der)));
-  ASSERT_TRUE(certs.back());
-
-  ShowCertificateViewer(std::move(certs));
-}
-
-void CertificateViewerUITest::ShowCertificateViewerInvalidCert() {
-  const uint8_t kInvalid[] = {42, 42, 42, 42, 42};
-  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs;
-  certs.push_back(
-      net::x509_util::CreateCryptoBuffer(base::make_span(kInvalid)));
-  ASSERT_TRUE(certs.back());
-
-  ShowCertificateViewer(std::move(certs));
-}
-
-void CertificateViewerUITest::ShowCertificateViewer(
-    std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs) {
-  ASSERT_TRUE(browser());
-  ASSERT_TRUE(browser()->window());
-
-  CertificateViewerDialog* dialog = CertificateViewerDialog::ShowConstrained(
-      std::move(certs), /*cert_nicknames=*/{},
-      browser()->tab_strip_model()->GetActiveWebContents(),
-      browser()->window()->GetNativeWindow());
-  content::WebContents* webui_webcontents = dialog->webui_->GetWebContents();
-  EXPECT_TRUE(content::WaitForLoadStop(webui_webcontents));
-  content::WebUI* webui = webui_webcontents->GetWebUI();
-  webui_webcontents->GetPrimaryMainFrame()->SetWebUIProperty(
-      "expectedUrl", chrome::kChromeUICertificateViewerURL);
-  SetWebUIInstance(webui);
-}
-
-#endif  // CHROME_TEST_DATA_WEBUI_CERTIFICATE_VIEWER_UI_TEST_INL_H_
diff --git a/chrome/test/data/webui/chromeos/scanning/test_scanning_browser_proxy.js b/chrome/test/data/webui/chromeos/scanning/test_scanning_browser_proxy.js
index 80f17ff..a9dbf18 100644
--- a/chrome/test/data/webui/chromeos/scanning/test_scanning_browser_proxy.js
+++ b/chrome/test/data/webui/chromeos/scanning/test_scanning_browser_proxy.js
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js';
-import {ScanningBrowserProxy, SelectedPath} from 'chrome://scanning/scanning_browser_proxy.js';
 import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 import {TestBrowserProxy} from 'chrome://webui-test/chromeos/test_browser_proxy.js';
 
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn
index e1fa19d..daab7a4a 100644
--- a/chrome/test/data/webui/settings/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -87,6 +87,7 @@
     "device_page/customize_tablet_buttons_subpage_test.ts",
     "device_page/customize_pen_buttons_subpage_test.ts",
     "device_page/drag_and_drop_manager_test.ts",
+    "device_page/device_page_revamp_test.ts",
     "device_page/device_page_tests.js",
     "device_page/fake_cros_audio_config_test.ts",
     "device_page/fake_input_device_settings_provider_test.ts",
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/device_page_revamp_test.ts b/chrome/test/data/webui/settings/chromeos/device_page/device_page_revamp_test.ts
new file mode 100644
index 0000000..4a225df9
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/device_page/device_page_revamp_test.ts
@@ -0,0 +1,121 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * Browser tests for the Device page, specific to when the
+ * OsSettingsRevampWayfinding feature is enabled.
+ */
+
+import 'chrome://os-settings/os_settings.js';
+
+import {CrSettingsPrefs, DevicePageBrowserProxyImpl, ensureLazyLoaded, OsSettingsRoutes, OsSettingsSubpageElement, resetGlobalScrollTargetForTesting, Route, Router, routes, setGlobalScrollTargetForTesting, SettingsDevicePageElement, SettingsPrefsElement} from 'chrome://os-settings/os_settings.js';
+import {assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
+import {isVisible} from 'chrome://webui-test/test_util.js';
+
+import {FakeLanguageHelper} from '../os_languages_page/fake_language_helper.js';
+
+import {TestDevicePageBrowserProxy} from './test_device_page_browser_proxy.js';
+
+interface SubpageData {
+  routeName: keyof OsSettingsRoutes;
+  elementTagName: string;
+}
+
+suite('<settings-device-page> Revamp', () => {
+  let settingsPrefs: SettingsPrefsElement;
+  let devicePage: SettingsDevicePageElement;
+
+  async function createPage(): Promise<void> {
+    devicePage = document.createElement('settings-device-page');
+    devicePage.languageHelper = new FakeLanguageHelper();
+    devicePage.prefs = settingsPrefs.prefs;
+    document.body.appendChild(devicePage);
+    await flushTasks();
+  }
+
+  async function navigateToSubpage(route: Route): Promise<void> {
+    await ensureLazyLoaded();
+    Router.getInstance().navigateTo(route);
+    await flushTasks();
+  }
+
+  /**
+   * Expects the os-settings-subpage parent element containing the subpage
+   * element with the given tag name to be visible on the page.
+   */
+  function assertSubpageIsVisible(elementTagName: string): void {
+    const subpageElement = devicePage.shadowRoot!.querySelector(elementTagName);
+    assertTrue(!!subpageElement);
+    const subpageParentElement = subpageElement.parentNode as HTMLElement;
+    assertTrue(subpageParentElement instanceof OsSettingsSubpageElement);
+    assertTrue(
+        isVisible(subpageParentElement),
+        `${elementTagName} should be visible.`);
+  }
+
+  suiteSetup(async () => {
+    settingsPrefs = document.createElement('settings-prefs');
+    document.body.appendChild(settingsPrefs);
+    await CrSettingsPrefs.initialized;
+  });
+
+  suiteTeardown(() => {
+    settingsPrefs.remove();
+  });
+
+  teardown(() => {
+    devicePage.remove();
+    Router.getInstance().resetRouteForTesting();
+  });
+
+  setup(() => {
+    Router.getInstance().navigateTo(routes.DEVICE);
+
+    DevicePageBrowserProxyImpl.setInstanceForTesting(
+        new TestDevicePageBrowserProxy());
+  });
+
+  suite('Input subpages', () => {
+    setup(() => {
+      // Necessary for os-settings-edit-dictionary-page which uses
+      // GlobalScrollTargetMixin
+      setGlobalScrollTargetForTesting(document.body);
+    });
+
+    teardown(() => {
+      resetGlobalScrollTargetForTesting();
+    });
+
+    const inputSubpages: SubpageData[] = [
+      {
+        routeName: 'OS_LANGUAGES_INPUT',
+        elementTagName: 'os-settings-input-page',
+      },
+      {
+        routeName: 'OS_LANGUAGES_INPUT_METHOD_OPTIONS',
+        elementTagName: 'settings-input-method-options-page',
+      },
+      {
+        routeName: 'OS_LANGUAGES_EDIT_DICTIONARY',
+        elementTagName: 'os-settings-edit-dictionary-page',
+      },
+      {
+        routeName: 'OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY',
+        elementTagName: 'os-settings-japanese-manage-user-dictionary-page',
+      },
+    ];
+    inputSubpages.forEach(({routeName, elementTagName}) => {
+      test(
+          `${elementTagName} subpage element is visible for route ${routeName}`,
+          async () => {
+            await createPage();
+
+            await navigateToSubpage(routes[routeName]);
+            assertSubpageIsVisible(elementTagName);
+          });
+    });
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.ts b/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.ts
index df0f876a..3b0633c 100644
--- a/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.ts
+++ b/chrome/test/data/webui/settings/chromeos/device_page/per_device_keyboard_test.ts
@@ -173,7 +173,7 @@
 
   test('Navigate to input tab', async () => {
     perDeviceKeyboardPage.shadowRoot!
-        .querySelector<CrLinkRowElement>('#showLanguagesInput')!.click();
+        .querySelector<CrLinkRowElement>('#inputRow')!.click();
     assertEquals(routes.OS_LANGUAGES_INPUT, Router.getInstance().currentRoute);
   });
 
diff --git a/chrome/test/data/webui/settings/chromeos/internet_page/internet_detail_menu_test.ts b/chrome/test/data/webui/settings/chromeos/internet_page/internet_detail_menu_test.ts
index 56a016c..15cf8f2 100644
--- a/chrome/test/data/webui/settings/chromeos/internet_page/internet_detail_menu_test.ts
+++ b/chrome/test/data/webui/settings/chromeos/internet_page/internet_detail_menu_test.ts
@@ -261,6 +261,7 @@
       simInfos: [],
       simAbsent: false,
       managedNetworkAvailable: false,
+      serial: '',
     };
     assertTrue(tripleDot.disabled);
 
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
index df1c6c85..b8993a9 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -373,6 +373,15 @@
    'os_printing_page/printing_settings_card_test.js',
    {enabled: ['ash::features::kOsSettingsRevampWayfinding']},
  ],
+ [
+   'DevicePageRevamp',
+   'device_page/device_page_revamp_test.js',
+   {
+     enabled: [
+       'ash::features::kOsSettingsRevampWayfinding',
+     ],
+   },
+ ],
  ['EsimRemoveProfileDialog', 'esim_remove_profile_dialog_test.js'],
  ['GuestOsSharedPaths', 'guest_os/guest_os_shared_paths_test.js'],
  ['GuestOsSharedUsbDevices', 'guest_os/guest_os_shared_usb_devices_test.js'],
diff --git a/chrome/test/data/webui/settings/chromeos/system_preferences_page/system_preferences_page_test.ts b/chrome/test/data/webui/settings/chromeos/system_preferences_page/system_preferences_page_test.ts
index 69b8dcc..0d95dcef 100644
--- a/chrome/test/data/webui/settings/chromeos/system_preferences_page/system_preferences_page_test.ts
+++ b/chrome/test/data/webui/settings/chromeos/system_preferences_page/system_preferences_page_test.ts
@@ -12,14 +12,13 @@
 
 import 'chrome://os-settings/os_settings.js';
 
-import {createRouterForTesting, CrSettingsPrefs, ensureLazyLoaded, OneDriveBrowserProxy, OsSettingsRoutes, OsSettingsSubpageElement, resetGlobalScrollTargetForTesting, Route, Router, routes, setGlobalScrollTargetForTesting, SettingsPrefsElement, SettingsSystemPreferencesPageElement} from 'chrome://os-settings/os_settings.js';
+import {createRouterForTesting, ensureLazyLoaded, OneDriveBrowserProxy, OsSettingsRoutes, OsSettingsSubpageElement, Route, Router, routes, SettingsSystemPreferencesPageElement} from 'chrome://os-settings/os_settings.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {assertFalse, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 import {isVisible} from 'chrome://webui-test/test_util.js';
 
 import {OneDriveTestBrowserProxy} from '../os_files_page/one_drive_test_browser_proxy.js';
-import {FakeLanguageHelper} from '../os_languages_page/fake_language_helper.js';
 
 interface SubpageData {
   routeName: keyof OsSettingsRoutes;
@@ -27,19 +26,10 @@
 }
 
 suite('<settings-system-preferences-page>', () => {
-  let settingsPrefs: SettingsPrefsElement;
   let page: SettingsSystemPreferencesPageElement;
 
-  async function initializePrefs(): Promise<void> {
-    settingsPrefs = document.createElement('settings-prefs');
-    document.body.appendChild(settingsPrefs);
-    await CrSettingsPrefs.initialized;
-  }
-
   async function createPage() {
     page = document.createElement('settings-system-preferences-page');
-    page.languageHelper = new FakeLanguageHelper();
-    page.prefs = settingsPrefs.prefs;
     document.body.appendChild(page);
     await flushTasks();
   }
@@ -75,14 +65,6 @@
         `${elementTagName} should be visible.`);
   }
 
-  suiteSetup(async () => {
-    await initializePrefs();
-  });
-
-  suiteTeardown(() => {
-    settingsPrefs.remove();
-  });
-
   setup(() => {
     loadTimeData.overrideValues({
       isGuest: false,
@@ -199,16 +181,6 @@
   });
 
   suite('Languages and Input subsection', () => {
-    setup(() => {
-      // Necessary for os-settings-edit-dictionary-page which uses
-      // GlobalScrollTargetMixin
-      setGlobalScrollTargetForTesting(document.body);
-    });
-
-    teardown(() => {
-      resetGlobalScrollTargetForTesting();
-    });
-
     test('Language settings card is visible', async () => {
       await createPage();
 
@@ -224,22 +196,6 @@
         routeName: 'OS_LANGUAGES_LANGUAGES',
         elementTagName: 'os-settings-languages-page-v2',
       },
-      {
-        routeName: 'OS_LANGUAGES_INPUT',
-        elementTagName: 'os-settings-input-page',
-      },
-      {
-        routeName: 'OS_LANGUAGES_INPUT_METHOD_OPTIONS',
-        elementTagName: 'settings-input-method-options-page',
-      },
-      {
-        routeName: 'OS_LANGUAGES_EDIT_DICTIONARY',
-        elementTagName: 'os-settings-edit-dictionary-page',
-      },
-      {
-        routeName: 'OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY',
-        elementTagName: 'os-settings-japanese-manage-user-dictionary-page',
-      },
     ];
     languageSubpages.forEach(({routeName, elementTagName}) => {
       test(
diff --git a/chrome/test/data/webui/side_panel/BUILD.gn b/chrome/test/data/webui/side_panel/BUILD.gn
index 77a51a52..26e819e 100644
--- a/chrome/test/data/webui/side_panel/BUILD.gn
+++ b/chrome/test/data/webui/side_panel/BUILD.gn
@@ -24,6 +24,9 @@
     "bookmarks/commerce/test_shopping_list_api_proxy.ts",
     "commerce/shopping_insights_app_test.ts",
     "commerce/price_tracking_section_test.ts",
+    "performance_controls/app_test.ts",
+    "performance_controls/performance_api_proxy_test.ts",
+    "performance_controls/test_performance_api_proxy.ts",
     "reading_list/reading_list_app_test.ts",
     "reading_list/test_reading_list_api_proxy.ts",
     "user_notes/app_test.ts",
@@ -41,6 +44,9 @@
         rebase_path(
             "$root_gen_dir/chrome/browser/resources/side_panel/shared/tsc/*",
             target_gen_dir),
+    "chrome://performance-side-panel.top-chrome/*|" + rebase_path(
+            "$root_gen_dir/chrome/browser/resources/side_panel/performance_controls/tsc/*",
+            target_gen_dir),
     "chrome://read-later.top-chrome/*|" + rebase_path(
             "$root_gen_dir/chrome/browser/resources/side_panel/reading_list/tsc/*",
             target_gen_dir),
@@ -65,6 +71,7 @@
   ts_deps = [
     "//chrome/browser/resources/side_panel/bookmarks:build_ts",
     "//chrome/browser/resources/side_panel/commerce:build_ts",
+    "//chrome/browser/resources/side_panel/performance_controls:build_ts",
     "//chrome/browser/resources/side_panel/reading_list:build_ts",
     "//chrome/browser/resources/side_panel/shared:build_ts",
     "//chrome/browser/resources/side_panel/user_notes:build_ts",
diff --git a/chrome/test/data/webui/side_panel/performance_controls/app_test.ts b/chrome/test/data/webui/side_panel/performance_controls/app_test.ts
new file mode 100644
index 0000000..9b2ec5f
--- /dev/null
+++ b/chrome/test/data/webui/side_panel/performance_controls/app_test.ts
@@ -0,0 +1,32 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://performance-side-panel.top-chrome/app.js';
+
+import {PerformanceAppElement} from 'chrome://performance-side-panel.top-chrome/app.js';
+import {PerformanceApiProxyImpl} from 'chrome://performance-side-panel.top-chrome/performance_api_proxy.js';
+import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
+
+import {TestPerformanceApiProxy} from './test_performance_api_proxy.js';
+
+suite('PerformanceControlsAppTest', () => {
+  let performanceApp: PerformanceAppElement;
+  let testProxy: TestPerformanceApiProxy;
+
+  setup(async () => {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+
+    testProxy = new TestPerformanceApiProxy();
+    PerformanceApiProxyImpl.setInstance(testProxy);
+
+    performanceApp = document.createElement('performance-app');
+    document.body.appendChild(performanceApp);
+    await flushTasks();
+  });
+
+  test('app is empty', async () => {
+    assertEquals(performanceApp.innerHTML, '');
+  });
+});
diff --git a/chrome/test/data/webui/side_panel/performance_controls/performance_api_proxy_test.ts b/chrome/test/data/webui/side_panel/performance_controls/performance_api_proxy_test.ts
new file mode 100644
index 0000000..7dabf35
--- /dev/null
+++ b/chrome/test/data/webui/side_panel/performance_controls/performance_api_proxy_test.ts
@@ -0,0 +1,20 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://performance-side-panel.top-chrome/app.js';
+
+import {PerformanceApiProxy, PerformanceApiProxyImpl} from 'chrome://performance-side-panel.top-chrome/performance_api_proxy.js';
+import {assertNotEquals} from 'chrome://webui-test/chai_assert.js';
+
+suite('PerformanceApiProxyTest', () => {
+  let apiProxy: PerformanceApiProxy;
+
+  setup(async () => {
+    apiProxy = new PerformanceApiProxyImpl();
+  });
+
+  test('callback router is created', async () => {
+    assertNotEquals(apiProxy.getCallbackRouter(), undefined);
+  });
+});
diff --git a/chrome/test/data/webui/side_panel/performance_controls/performance_controls_browsertest.cc b/chrome/test/data/webui/side_panel/performance_controls/performance_controls_browsertest.cc
new file mode 100644
index 0000000..b0e11fa
--- /dev/null
+++ b/chrome/test/data/webui/side_panel/performance_controls/performance_controls_browsertest.cc
@@ -0,0 +1,29 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/scoped_feature_list.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/web_ui_mocha_browser_test.h"
+#include "components/performance_manager/public/features.h"
+#include "content/public/test/browser_test.h"
+
+class SidePanelPerformanceControlsTest : public WebUIMochaBrowserTest {
+ protected:
+  SidePanelPerformanceControlsTest() {
+    set_test_loader_host(chrome::kChromeUIPerformanceSidePanelHost);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{
+      performance_manager::features::kPerformanceControlsSidePanel};
+};
+
+IN_PROC_BROWSER_TEST_F(SidePanelPerformanceControlsTest, App) {
+  RunTest("side_panel/performance_controls/app_test.js", "mocha.run()");
+}
+
+IN_PROC_BROWSER_TEST_F(SidePanelPerformanceControlsTest, PerformanceApiProxy) {
+  RunTest("side_panel/performance_controls/performance_api_proxy_test.js",
+          "mocha.run()");
+}
diff --git a/chrome/test/data/webui/side_panel/performance_controls/test_performance_api_proxy.ts b/chrome/test/data/webui/side_panel/performance_controls/test_performance_api_proxy.ts
new file mode 100644
index 0000000..bb1565c9
--- /dev/null
+++ b/chrome/test/data/webui/side_panel/performance_controls/test_performance_api_proxy.ts
@@ -0,0 +1,28 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {PerformancePageCallbackRouter} from 'chrome://performance-side-panel.top-chrome/performance.mojom-webui.js';
+import {PerformanceApiProxy} from 'chrome://performance-side-panel.top-chrome/performance_api_proxy';
+import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
+
+
+export class TestPerformanceApiProxy extends TestBrowserProxy implements
+    PerformanceApiProxy {
+  private callbackRouter_: PerformancePageCallbackRouter =
+      new PerformancePageCallbackRouter();
+  private callbackRouterRemote_ =
+      this.callbackRouter_.$.bindNewPipeAndPassRemote();
+
+  constructor() {
+    super([]);
+  }
+
+  getCallbackRouter() {
+    return this.callbackRouter_;
+  }
+
+  getCallbackRouterRemote() {
+    return this.callbackRouterRemote_;
+  }
+}
diff --git a/chrome/test/interaction/feature_engagement_initialized_observer.cc b/chrome/test/interaction/feature_engagement_initialized_observer.cc
index aeaff40d..93b4759 100644
--- a/chrome/test/interaction/feature_engagement_initialized_observer.cc
+++ b/chrome/test/interaction/feature_engagement_initialized_observer.cc
@@ -10,7 +10,8 @@
 #include "components/feature_engagement/public/tracker.h"
 #include "ui/base/interaction/state_observer.h"
 
-DEFINE_STATE_IDENTIFIER_VALUE(kFeatureEngagementInitializedState);
+DEFINE_STATE_IDENTIFIER_VALUE(FeatureEngagementInitializedObserver,
+                              kFeatureEngagementInitializedState);
 
 FeatureEngagementInitializedObserver::FeatureEngagementInitializedObserver(
     Browser* browser)
diff --git a/chromecast/crash/BUILD.gn b/chromecast/crash/BUILD.gn
index ac2644a..fa9edfe 100644
--- a/chromecast/crash/BUILD.gn
+++ b/chromecast/crash/BUILD.gn
@@ -88,6 +88,8 @@
         "linux/synchronized_minidump_manager.cc",
         "linux/synchronized_minidump_manager.h",
       ]
+
+      deps += [ "//base:i18n" ]
     }
 
     deps += [
diff --git a/chromecast/crash/linux/dump_info.cc b/chromecast/crash/linux/dump_info.cc
index 0d2121cf..d6095bce 100644
--- a/chromecast/crash/linux/dump_info.cc
+++ b/chromecast/crash/linux/dump_info.cc
@@ -8,8 +8,8 @@
 #include <stddef.h>
 #include <stdlib.h>
 
+#include "base/i18n/time_formatting.h"
 #include "base/logging.h"
-#include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "base/values.h"
 
@@ -75,13 +75,8 @@
 base::Value DumpInfo::GetAsValue() const {
   base::Value::Dict result;
 
-  // "%Y-%m-%d %H:%M:%S";
-  base::Time::Exploded ex;
-  dump_time_.LocalExplode(&ex);
-  result.Set(
-      kDumpTimeKey,
-      base::StringPrintf("%04d-%02d-%02d %02d:%02d:%02d", ex.year, ex.month,
-                         ex.day_of_month, ex.hour, ex.minute, ex.second));
+  result.Set(kDumpTimeKey, base::UnlocalizedTimeFormatWithPattern(
+                               dump_time_, "yyyy-MM-dd HH:mm:ss"));
 
   result.Set(kDumpKey, crashed_process_dump_);
   std::string uptime = std::to_string(params_.process_uptime);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index de07c1e..5ba46e0 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-15624.0.0
\ No newline at end of file
+15626.0.0
\ No newline at end of file
diff --git a/chromeos/ash/components/network/cellular_esim_profile_handler_impl.cc b/chromeos/ash/components/network/cellular_esim_profile_handler_impl.cc
index 87dce2d2..7b101ef 100644
--- a/chromeos/ash/components/network/cellular_esim_profile_handler_impl.cc
+++ b/chromeos/ash/components/network/cellular_esim_profile_handler_impl.cc
@@ -250,20 +250,15 @@
   // a mechanism for installing a pending profile except through the dedicated
   // dialog which performs a fresh SM-DS scan each time it is opened.
   if (ash::features::IsSmdsSupportEnabled()) {
-    profiles_from_hermes.erase(
-        std::remove_if(
-            profiles_from_hermes.begin(), profiles_from_hermes.end(),
-            [](const CellularESimProfile& profile) {
-              if (profile.state() == CellularESimProfile::State::kPending) {
-                NET_LOG(DEBUG)
-                    << "Removing eSIM profile {iccid: " << profile.iccid()
-                    << ", eid: " << profile.eid()
-                    << "} from list to cache since it is pending";
-                return true;
-              }
-              return false;
-            }),
-        profiles_from_hermes.end());
+    base::EraseIf(profiles_from_hermes, [](const CellularESimProfile& profile) {
+      if (profile.state() == CellularESimProfile::State::kPending) {
+        NET_LOG(DEBUG) << "Removing eSIM profile {iccid: " << profile.iccid()
+                       << ", eid: " << profile.eid()
+                       << "} from list to cache since it is pending";
+        return true;
+      }
+      return false;
+    });
   }
 
   // Skip updating if there are profiles that haven't received ICCID updates
diff --git a/chromeos/ash/components/phonehub/app_stream_launcher_data_model.cc b/chromeos/ash/components/phonehub/app_stream_launcher_data_model.cc
index 7577a889..06cfe64 100644
--- a/chromeos/ash/components/phonehub/app_stream_launcher_data_model.cc
+++ b/chromeos/ash/components/phonehub/app_stream_launcher_data_model.cc
@@ -4,6 +4,7 @@
 
 #include "chromeos/ash/components/phonehub/app_stream_launcher_data_model.h"
 
+#include "base/containers/cxx20_erase.h"
 #include "base/i18n/case_conversion.h"
 #include "chromeos/ash/components/multidevice/logging/logging.h"
 #include "chromeos/ash/components/phonehub/notification.h"
@@ -97,20 +98,15 @@
 
 void AppStreamLauncherDataModel::RemoveAppFromList(
     const proto::App app_to_remove) {
-  apps_list_.erase(
-      std::remove_if(apps_list_.begin(), apps_list_.end(),
-                     [&app_to_remove](const Notification::AppMetadata& app) {
-                       return app.package_name == app_to_remove.package_name();
-                     }),
-      apps_list_.end());
+  base::EraseIf(apps_list_,
+                [&app_to_remove](const Notification::AppMetadata& app) {
+                  return app.package_name == app_to_remove.package_name();
+                });
 
-  apps_list_sorted_by_name_.erase(
-      std::remove_if(apps_list_sorted_by_name_.begin(),
-                     apps_list_sorted_by_name_.end(),
-                     [&app_to_remove](const Notification::AppMetadata& app) {
-                       return app.package_name == app_to_remove.package_name();
-                     }),
-      apps_list_sorted_by_name_.end());
+  base::EraseIf(apps_list_sorted_by_name_,
+                [&app_to_remove](const Notification::AppMetadata& app) {
+                  return app.package_name == app_to_remove.package_name();
+                });
 
   for (auto& observer : observer_list_) {
     observer.OnAppListChanged();
diff --git a/chromeos/ash/components/scalable_iph/scalable_iph.cc b/chromeos/ash/components/scalable_iph/scalable_iph.cc
index 70031c6..ca9ef8c 100644
--- a/chromeos/ash/components/scalable_iph/scalable_iph.cc
+++ b/chromeos/ash/components/scalable_iph/scalable_iph.cc
@@ -72,6 +72,7 @@
            kEventNameShelfItemActivationGooglePhotosAndroid},
           {ScalableIph::Event::kShelfItemActivationGooglePlay,
            kEventNameShelfItemActivationGooglePlay},
+          {ScalableIph::Event::kPrintJobCreated, kEventNamePrintJobCreated},
       });
   return *event_names_map;
 }
@@ -1007,6 +1008,8 @@
       return out << "ShelfItemActivationGooglePhotosAndroid";
     case ScalableIph::Event::kShelfItemActivationGooglePlay:
       return out << "ShelfItemActivationGooglePlay";
+    case ScalableIph::Event::kPrintJobCreated:
+      return out << "PrintJobCreated";
   }
 }
 
diff --git a/chromeos/ash/components/scalable_iph/scalable_iph.h b/chromeos/ash/components/scalable_iph/scalable_iph.h
index 88db356..0c7e419 100644
--- a/chromeos/ash/components/scalable_iph/scalable_iph.h
+++ b/chromeos/ash/components/scalable_iph/scalable_iph.h
@@ -93,6 +93,7 @@
     kShelfItemActivationGooglePhotosWeb,
     kShelfItemActivationGooglePhotosAndroid,
     kShelfItemActivationGooglePlay,
+    kPrintJobCreated,
   };
 
   ScalableIph(feature_engagement::Tracker* tracker,
diff --git a/chromeos/ash/components/scalable_iph/scalable_iph_constants.h b/chromeos/ash/components/scalable_iph/scalable_iph_constants.h
index 5a32f9416..e5161c5f 100644
--- a/chromeos/ash/components/scalable_iph/scalable_iph_constants.h
+++ b/chromeos/ash/components/scalable_iph/scalable_iph_constants.h
@@ -116,6 +116,8 @@
 // Recorded when the personalization hub app is opened.
 inline constexpr char kEventNameOpenPersonalizationApp[] =
     "ScalableIphOpenPersonalizationApp";
+// Recorded when a print job is created.
+constexpr char kEventNamePrintJobCreated[] = "ScalableIphPrintJobCreated";
 
 // `FiveMinTick` event is recorded every five minutes after OOBE completion.
 inline constexpr char kEventNameFiveMinTick[] = "ScalableIphFiveMinTick";
diff --git a/chromeos/ash/services/network_config/BUILD.gn b/chromeos/ash/services/network_config/BUILD.gn
index ca0f800..d94702c3 100644
--- a/chromeos/ash/services/network_config/BUILD.gn
+++ b/chromeos/ash/services/network_config/BUILD.gn
@@ -23,6 +23,7 @@
     "//chromeos/ash/components/dbus/shill",
     "//chromeos/ash/components/login/login_state",
     "//chromeos/ash/components/sync_wifi:network_eligibility_checker",
+    "//chromeos/ash/components/system",
     "//chromeos/services/network_config/public/cpp",
     "//components/captive_portal/core",
     "//components/device_event_log",
@@ -83,6 +84,7 @@
     "//chromeos/ash/components/login/login_state",
     "//chromeos/ash/components/network",
     "//chromeos/ash/components/network:test_support",
+    "//chromeos/ash/components/system",
     "//chromeos/ash/services/network_config/public/cpp:test_support",
     "//chromeos/components/onc",
     "//chromeos/services/network_config/public/mojom",
diff --git a/chromeos/ash/services/network_config/cros_network_config.cc b/chromeos/ash/services/network_config/cros_network_config.cc
index 27a9031f..ca40963 100644
--- a/chromeos/ash/services/network_config/cros_network_config.cc
+++ b/chromeos/ash/services/network_config/cros_network_config.cc
@@ -44,6 +44,7 @@
 #include "chromeos/ash/components/network/technology_state_controller.h"
 #include "chromeos/ash/components/network/text_message_suppression_state.h"
 #include "chromeos/ash/components/sync_wifi/network_eligibility_checker.h"
+#include "chromeos/ash/components/system/statistics_provider.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-shared.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config_mojom_traits.h"
@@ -601,7 +602,8 @@
     const DeviceState* device,
     NetworkStateHandler* network_state_handler,
     CellularInhibitor* cellular_inhibitor,
-    mojom::DeviceStateType technology_state) {
+    mojom::DeviceStateType technology_state,
+    const absl::optional<base::StringPiece> serial_number) {
   mojom::NetworkType type = ShillTypeToMojo(device->type());
   if (type == mojom::NetworkType::kAll) {
     NET_LOG(ERROR) << "Unexpected device type: " << device->type()
@@ -640,6 +642,10 @@
     result->inhibit_reason =
         GetInhibitReason(network_state_handler, cellular_inhibitor);
     result->imei = device->imei();
+    if (features::IsCellularCarrierLockEnabled() && serial_number &&
+        !serial_number->empty()) {
+      result->serial = std::string(serial_number.value());
+    }
   }
   return result;
 }
@@ -2245,6 +2251,12 @@
       network_profile_handler_(network_profile_handler),
       technology_state_controller_(technology_state_controller) {
   CHECK(network_state_handler);
+  if (features::IsCellularCarrierLockEnabled()) {
+    serial_number_ = system::StatisticsProvider::GetInstance()->GetMachineID();
+    if (!serial_number_ || serial_number_->empty()) {
+      LOG(WARNING) << "Serial number not set.";
+    }
+  }
 }
 
 CrosNetworkConfig::~CrosNetworkConfig() {
@@ -2360,8 +2372,9 @@
       NET_LOG(ERROR) << "Device state unavailable: " << device->name();
       continue;
     }
-    mojom::DeviceStatePropertiesPtr mojo_device = DeviceStateToMojo(
-        device, network_state_handler_, cellular_inhibitor_, technology_state);
+    mojom::DeviceStatePropertiesPtr mojo_device =
+        DeviceStateToMojo(device, network_state_handler_, cellular_inhibitor_,
+                          technology_state, serial_number_);
     if (mojo_device)
       result.emplace_back(std::move(mojo_device));
   }
diff --git a/chromeos/ash/services/network_config/cros_network_config.h b/chromeos/ash/services/network_config/cros_network_config.h
index a0af7e4..e516e2a3 100644
--- a/chromeos/ash/services/network_config/cros_network_config.h
+++ b/chromeos/ash/services/network_config/cros_network_config.h
@@ -237,6 +237,8 @@
   mojo::ReceiverSet<chromeos::network_config::mojom::CrosNetworkConfig>
       receivers_;
 
+  absl::optional<base::StringPiece> serial_number_;
+
   int callback_id_ = 1;
   base::flat_map<int, SetPropertiesCallback> set_properties_callbacks_;
   base::flat_map<int, ConfigureNetworkCallback> configure_network_callbacks_;
diff --git a/chromeos/ash/services/network_config/cros_network_config_unittest.cc b/chromeos/ash/services/network_config/cros_network_config_unittest.cc
index f6a506c..033793d6 100644
--- a/chromeos/ash/services/network_config/cros_network_config_unittest.cc
+++ b/chromeos/ash/services/network_config/cros_network_config_unittest.cc
@@ -41,6 +41,7 @@
 #include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h"
 #include "chromeos/ash/components/network/system_token_cert_db_storage.h"
 #include "chromeos/ash/components/network/technology_state_controller.h"
+#include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_observer.h"
 #include "chromeos/ash/services/network_config/test_apn_data.h"
 #include "chromeos/ash/services/network_config/test_network_configuration_observer.h"
@@ -74,6 +75,7 @@
 constexpr char kCellularDevicePath[] = "/device/stub_cellular_device";
 constexpr char kCellularTestIccid[] = "1234567890";
 constexpr char kCellularTestImei[] = "1234567890";
+constexpr char kCellularTestSerial[] = "ABCD";
 
 constexpr char kCellularTestApn1[] = "TEST.APN1";
 constexpr char kCellularTestApnName1[] = "Test Apn 1";
@@ -268,8 +270,26 @@
     PrefProxyConfigTrackerImpl::RegisterPrefs(local_state_.registry());
 
     helper_->InitializePrefs(&user_prefs_, &local_state_);
-
     NetworkHandler* network_handler = NetworkHandler::Get();
+    cros_network_config_test_helper_ =
+        std::make_unique<CrosNetworkConfigTestHelper>(true);
+    SetupNetworkConfig(network_handler);
+  }
+
+  CrosNetworkConfigTest(const CrosNetworkConfigTest&) = delete;
+  CrosNetworkConfigTest& operator=(const CrosNetworkConfigTest&) = delete;
+
+  ~CrosNetworkConfigTest() override {
+    cros_network_config_test_helper_.reset();
+    cros_network_config_.reset();
+    helper_.reset();
+    NetworkCertLoader::Shutdown();
+    scoped_user_manager_.reset();
+    SystemTokenCertDbStorage::Shutdown();
+    LoginState::Shutdown();
+  }
+
+  void SetupNetworkConfig(NetworkHandler* network_handler) {
     cros_network_config_ = std::make_unique<CrosNetworkConfig>(
         network_handler->network_state_handler(),
         network_handler->network_device_handler(),
@@ -284,18 +304,6 @@
     SetupNetworks();
   }
 
-  CrosNetworkConfigTest(const CrosNetworkConfigTest&) = delete;
-  CrosNetworkConfigTest& operator=(const CrosNetworkConfigTest&) = delete;
-
-  ~CrosNetworkConfigTest() override {
-    cros_network_config_.reset();
-    helper_.reset();
-    NetworkCertLoader::Shutdown();
-    scoped_user_manager_.reset();
-    SystemTokenCertDbStorage::Shutdown();
-    LoginState::Shutdown();
-  }
-
   void SetupPolicy() {
     ManagedNetworkConfigurationHandler* managed_network_configuration_handler =
         NetworkHandler::Get()->managed_network_configuration_handler();
@@ -1098,6 +1106,10 @@
     }
   }
 
+  void SetSerialNumber(const std::string& serial_number) {
+    cros_network_config_test_helper_->SetSerialNumber(serial_number);
+  }
+
   NetworkHandlerTestHelper* helper() { return helper_.get(); }
   CrosNetworkConfigTestObserver* observer() { return observer_.get(); }
   CrosNetworkConfig* cros_network_config() {
@@ -1120,6 +1132,7 @@
 
  protected:
   sync_preferences::TestingPrefServiceSyncable user_prefs_;
+  base::test::ScopedFeatureList feature_list;
 
  private:
   base::test::SingleThreadTaskEnvironment task_environment_;
@@ -1128,6 +1141,7 @@
   TestingPrefServiceSimple local_state_;
   std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
   std::unique_ptr<CrosNetworkConfig> cros_network_config_;
+  std::unique_ptr<CrosNetworkConfigTestHelper> cros_network_config_test_helper_;
   std::unique_ptr<CrosNetworkConfigTestObserver> observer_;
   std::string wifi1_path_;
   std::string vpn_path_;
@@ -1455,6 +1469,7 @@
   EXPECT_EQ(shill::kSIMLockPin, cellular->sim_lock_status->lock_type);
   EXPECT_EQ(3, cellular->sim_lock_status->retries_left);
   EXPECT_EQ(kCellularTestImei, cellular->imei);
+  EXPECT_EQ(absl::nullopt, cellular->serial);
 
   mojom::DeviceStateProperties* vpn = devices[3].get();
   EXPECT_EQ(mojom::NetworkType::kVPN, vpn->type);
@@ -1470,6 +1485,46 @@
   EXPECT_EQ(mojom::DeviceStateType::kDisabled, devices[0]->device_state);
 }
 
+TEST_F(CrosNetworkConfigTest, GetDeviceStateListSerial) {
+  feature_list.InitAndEnableFeature(features::kCellularCarrierLock);
+  SetSerialNumber(kCellularTestSerial);
+  NetworkHandler* network_handler = NetworkHandler::Get();
+  SetupNetworkConfig(network_handler);
+
+  std::vector<mojom::DeviceStatePropertiesPtr> devices = GetDeviceStateList();
+  ASSERT_EQ(4u, devices.size());
+  mojom::DeviceStateProperties* cellular = devices[2].get();
+  EXPECT_EQ(mojom::NetworkType::kCellular, cellular->type);
+  EXPECT_EQ(mojom::DeviceStateType::kEnabled, cellular->device_state);
+  EXPECT_FALSE(cellular->sim_absent);
+  ASSERT_TRUE(cellular->sim_lock_status);
+  EXPECT_TRUE(cellular->sim_lock_status->lock_enabled);
+  EXPECT_EQ(shill::kSIMLockPin, cellular->sim_lock_status->lock_type);
+  EXPECT_EQ(3, cellular->sim_lock_status->retries_left);
+  EXPECT_EQ(kCellularTestImei, cellular->imei);
+  EXPECT_EQ(kCellularTestSerial, cellular->serial);
+}
+
+TEST_F(CrosNetworkConfigTest, GetDeviceStateListSerialFeatureDisable) {
+  feature_list.InitAndDisableFeature(features::kCellularCarrierLock);
+  SetSerialNumber(kCellularTestSerial);
+  NetworkHandler* network_handler = NetworkHandler::Get();
+  SetupNetworkConfig(network_handler);
+
+  std::vector<mojom::DeviceStatePropertiesPtr> devices = GetDeviceStateList();
+  ASSERT_EQ(4u, devices.size());
+  mojom::DeviceStateProperties* cellular = devices[2].get();
+  EXPECT_EQ(mojom::NetworkType::kCellular, cellular->type);
+  EXPECT_EQ(mojom::DeviceStateType::kEnabled, cellular->device_state);
+  EXPECT_FALSE(cellular->sim_absent);
+  ASSERT_TRUE(cellular->sim_lock_status);
+  EXPECT_TRUE(cellular->sim_lock_status->lock_enabled);
+  EXPECT_EQ(shill::kSIMLockPin, cellular->sim_lock_status->lock_type);
+  EXPECT_EQ(3, cellular->sim_lock_status->retries_left);
+  EXPECT_EQ(kCellularTestImei, cellular->imei);
+  EXPECT_EQ(absl::nullopt, cellular->serial);
+}
+
 // Tests that no VPN device state is returned by GetDeviceStateList if no VPN
 // services exist and built-in VPN is not prohibited.
 TEST_F(CrosNetworkConfigTest, GetDeviceStateListNoVpnServices) {
diff --git a/chromeos/ash/services/network_config/public/cpp/BUILD.gn b/chromeos/ash/services/network_config/public/cpp/BUILD.gn
index 9fb4a85..78fee2e 100644
--- a/chromeos/ash/services/network_config/public/cpp/BUILD.gn
+++ b/chromeos/ash/services/network_config/public/cpp/BUILD.gn
@@ -22,6 +22,7 @@
     "//mojo/public/cpp/bindings",
   ]
   deps = [
+    "//chromeos/ash/components/system",
     "//chromeos/ash/services/network_config",
     "//chromeos/ash/services/network_config:in_process_instance",
   ]
diff --git a/chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.cc b/chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.cc
index ed8d807..e73e99d4 100644
--- a/chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.cc
+++ b/chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.cc
@@ -7,6 +7,7 @@
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
 #include "chromeos/ash/components/network/network_device_handler.h"
 #include "chromeos/ash/components/network/network_handler.h"
+#include "chromeos/ash/components/system/fake_statistics_provider.h"
 #include "chromeos/ash/services/network_config/cros_network_config.h"
 #include "chromeos/ash/services/network_config/in_process_instance.h"
 
@@ -89,6 +90,7 @@
 
 void CrosNetworkConfigTestHelper::Initialize(
     ManagedNetworkConfigurationHandler* network_configuration_handler) {
+  system::StatisticsProvider::SetTestProvider(&statistics_provider_);
   if (NetworkHandler::IsInitialized()) {
     cros_network_config_impl_ = std::make_unique<CrosNetworkConfig>();
   } else {
@@ -109,4 +111,9 @@
   OverrideInProcessInstanceForTesting(cros_network_config_impl_.get());
 }
 
+void CrosNetworkConfigTestHelper::SetSerialNumber(
+    const std::string& serial_number) {
+  statistics_provider_.SetMachineStatistic("serial_number", serial_number);
+}
+
 }  // namespace ash::network_config
diff --git a/chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h b/chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h
index 1a5287e..83755be0 100644
--- a/chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h
+++ b/chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h
@@ -10,6 +10,7 @@
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
 #include "chromeos/ash/components/network/managed_network_configuration_handler.h"
 #include "chromeos/ash/components/network/network_state_test_helper.h"
+#include "chromeos/ash/components/system/fake_statistics_provider.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h"
 #include "chromeos/services/network_config/public/mojom/network_types.mojom-forward.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -58,6 +59,8 @@
   void Initialize(
       ManagedNetworkConfigurationHandler* network_configuration_handler);
 
+  void SetSerialNumber(const std::string& serial_number);
+
  protected:
   // Called in |~CrosNetworkConfigTestHelper()| to set the global network config
   // to nullptr and destroy cros_network_config_impl_.
@@ -67,6 +70,7 @@
       /*use_default_devices_and_services=*/false};
   std::unique_ptr<CellularInhibitor> cellular_inhibitor_;
   std::unique_ptr<CrosNetworkConfig> cros_network_config_impl_;
+  system::FakeStatisticsProvider statistics_provider_;
 };
 
 }  // namespace network_config
diff --git a/chromeos/services/network_config/public/mojom/cros_network_config.mojom b/chromeos/services/network_config/public/mojom/cros_network_config.mojom
index 204c9697..eb7f273 100644
--- a/chromeos/services/network_config/public/mojom/cros_network_config.mojom
+++ b/chromeos/services/network_config/public/mojom/cros_network_config.mojom
@@ -336,6 +336,10 @@
   NetworkType type;
   // Whether or not any managed networks are available.
   bool managed_network_available = false;
+  // Serial number of the device, reported for cellular devices
+  // to start with. Displayed along with IMEI/EID to help user
+  // unlock carrier locked device.
+  string? serial;
 };
 
 const int32 kNoLimit = 0;
diff --git a/clank b/clank
index 634fe7e..340aed4 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 634fe7e05f59ab1a85a395b539490fe1aa85fef4
+Subproject commit 340aed4c542ac53f950fd007ee452c3f1099739f
diff --git a/components/BUILD.gn b/components/BUILD.gn
index f21d240..df03872 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -649,6 +649,7 @@
       # See comment in components / guest_view / browser / BUILD.gn for why
       # guest_view is currently non - mobile.
       "//components/guest_view/browser:unit_tests",
+      "//components/live_caption:unit_tests",
       "//components/soda:unit_tests",
       "//components/storage_monitor:unit_tests",
       "//components/web_modal:unit_tests",
@@ -685,7 +686,6 @@
       "//components/arc:unit_tests",
       "//components/desks_storage:unit_tests",
       "//components/guest_os:unit_tests",
-      "//components/live_caption:unit_tests",
       "//components/metrics/structured:unit_tests",
       "//components/metrics/structured/mojom:unit_tests",
       "//components/ownership:unit_tests",
diff --git a/components/attribution_reporting/filters.cc b/components/attribution_reporting/filters.cc
index 56f8d66..39da7af 100644
--- a/components/attribution_reporting/filters.cc
+++ b/components/attribution_reporting/filters.cc
@@ -244,13 +244,19 @@
                          const base::Time& trigger_time,
                          const FiltersDisjunction& filters,
                          bool negated) const {
-  CHECK_LE(source_time, trigger_time);
   if (filters.empty()) {
     return true;
   }
 
+  // While contradictory, it is possible for a source to have an assigned time
+  // of T and a trigger that is attributed to it to have a time of T-X e.g. due
+  // to user-initiated clock changes. see: https://crbug.com/1486489
+  //
+  // TODO(https://crbug.com/1486496): Assume `source_time` is smaller than
+  // `trigger_time` once attribution time resolution is implemented in storage.
   const base::TimeDelta duration_since_source_registration =
-      trigger_time - source_time;
+      (source_time < trigger_time) ? trigger_time - source_time
+                                   : base::Microseconds(0);
 
   // A filter_value is considered matched if the filter key is only present
   // either on the source or trigger, or the intersection of the filter values
diff --git a/components/attribution_reporting/filters_unittest.cc b/components/attribution_reporting/filters_unittest.cc
index 65f789b8..8c9b62e0 100644
--- a/components/attribution_reporting/filters_unittest.cc
+++ b/components/attribution_reporting/filters_unittest.cc
@@ -880,5 +880,20 @@
   }
 }
 
+// TODO(https://crbug.com/1486496): remove this test once CHECK is used in the
+// implementation.
+TEST(FilterDataTest,
+     AttributionFilterDataMatch_SourceTimeGreaterThanTriggerTime) {
+  const auto one_filter = FilterValues({{"filter1", {"value1"}}});
+  const auto filter_data = *FilterData::Create(one_filter);
+  const auto filters = FiltersDisjunction({*FilterConfig::Create(
+      {one_filter}, /*lookback_window=*/kTriggerTime - kSourceTime)});
+  EXPECT_TRUE(FilterData(filter_data)
+                  .MatchesForTesting(
+                      SourceType::kEvent, kSourceTime,
+                      /*trigger_time=*/kSourceTime - base::Microseconds(1),
+                      filters, /*negated=*/false));
+}
+
 }  // namespace
 }  // namespace attribution_reporting
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index f02ce05..d9a6540 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -2174,6 +2174,9 @@
   // Constrain the maximum data length to prevent a malicious site from DOS'ing
   // the browser: http://crbug.com/49332
   field->value = std::move(value).substr(0, kMaxStringLength);
+  constexpr auto kMaxLength = static_cast<unsigned>(kMaxStringLength);
+  field->selection_start = std::min(element.SelectionStart(), kMaxLength);
+  field->selection_end = std::min(element.SelectionEnd(), kMaxLength);
 
   // If the field was autofilled or the user typed into it, check the value
   // stored in |field_data_manager| against the value property of the DOM
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc
index 5081507..46be39e 100644
--- a/components/autofill/core/browser/autofill_download_manager.cc
+++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -298,7 +298,7 @@
 std::string FieldTypeToString(uint32_t type) {
   return base::StrCat(
       {base::NumberToString(type), std::string("/"),
-       AutofillType(ToSafeServerFieldType(type, UNKNOWN_TYPE)).ToString()});
+       FieldTypeToStringPiece(ToSafeServerFieldType(type, UNKNOWN_TYPE))});
 }
 
 LogBuffer& operator<<(LogBuffer& out, const AutofillPageQueryRequest& query) {
diff --git a/components/autofill/core/browser/autofill_feedback_data.cc b/components/autofill/core/browser/autofill_feedback_data.cc
index 4c0917d..f7d3a9b5 100644
--- a/components/autofill/core/browser/autofill_feedback_data.cc
+++ b/components/autofill/core/browser/autofill_feedback_data.cc
@@ -45,8 +45,8 @@
   field_data.Set("placeholderAttribute", field->placeholder);
   field_data.Set("fieldType", field->Type().ToString());
   field_data.Set("heuristicType",
-                 AutofillType(field->heuristic_type()).ToString());
-  field_data.Set("serverType", AutofillType(field->server_type()).ToString());
+                 FieldTypeToStringPiece(field->heuristic_type()));
+  field_data.Set("serverType", FieldTypeToStringPiece(field->server_type()));
   field_data.Set("serverTypeIsOverride",
                  field->server_type_prediction_is_override());
   field_data.Set("htmlType", FieldTypeToStringPiece(field->html_type()));
diff --git a/components/autofill/core/browser/autofill_merge_unittest.cc b/components/autofill/core/browser/autofill_merge_unittest.cc
index ea0e80c4..4b16128 100644
--- a/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -97,7 +97,7 @@
     result += "\n";
     for (const ServerFieldType& type : kProfileFieldTypes) {
       std::u16string value = profile->GetRawInfo(type);
-      result += AutofillType::ServerFieldTypeToString(type);
+      result += FieldTypeToStringPiece(type);
       result += kFieldSeparator;
       if (!value.empty()) {
         base::ReplaceFirstSubstringAfterOffset(&value, 0, u"\\n", u"\n");
@@ -140,28 +140,14 @@
   // sequentially, and fills |merged_profiles| with the serialized result.
   void MergeProfiles(const std::string& profiles, std::string* merged_profiles);
 
-  // Deserializes |str| into a field type.
-  ServerFieldType StringToFieldType(const std::string& str);
-
   base::test::TaskEnvironment task_environment_;
   TestAutofillClient autofill_client_;
   TestPersonalDataManager personal_data_;
   std::unique_ptr<FormDataImporter> form_data_importer_;
-
- private:
-  std::map<std::string, ServerFieldType> string_to_field_type_map_;
 };
 
 AutofillMergeTest::AutofillMergeTest()
-    : testing::DataDrivenTest(GetTestDataDir(), kFeatureName, kTestName) {
-  for (size_t i = NO_SERVER_DATA; i < MAX_VALID_FIELD_TYPE; ++i) {
-    ServerFieldType field_type = ToSafeServerFieldType(i, MAX_VALID_FIELD_TYPE);
-    if (field_type == MAX_VALID_FIELD_TYPE)
-      continue;
-    string_to_field_type_map_[AutofillType::ServerFieldTypeToString(
-        field_type)] = field_type;
-  }
-}
+    : testing::DataDrivenTest(GetTestDataDir(), kFeatureName, kTestName) {}
 
 AutofillMergeTest::~AutofillMergeTest() = default;
 
@@ -231,7 +217,7 @@
         AutofillField* field =
             const_cast<AutofillField*>(form_structure.field(j));
         ServerFieldType type =
-            StringToFieldType(base::UTF16ToUTF8(field->name));
+            TypeNameToFieldType(base::UTF16ToUTF8(field->name));
         field->set_heuristic_type(GetActiveHeuristicSource(), type);
       }
 
@@ -262,10 +248,6 @@
   *merged_profiles = SerializeProfiles(imported_profiles);
 }
 
-ServerFieldType AutofillMergeTest::StringToFieldType(const std::string& str) {
-  return string_to_field_type_map_[str];
-}
-
 TEST_P(AutofillMergeTest, DataDrivenMergeProfiles) {
   const bool kIsExpectedToPass = true;
   RunOneDataDrivenTest(GetParam(), GetOutputDirectory(), kIsExpectedToPass);
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index da026c9..94a9de0 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -96,9 +96,8 @@
                            bool ignore_status) {
   for (const auto& value : values) {
     SCOPED_TRACE(testing::Message()
-                 << "Expected for type "
-                 << AutofillType::ServerFieldTypeToString(value.type) << "\n\t"
-                 << value.value << " with status "
+                 << "Expected for type " << FieldTypeToStringPiece(value.type)
+                 << "\n\t" << value.value << " with status "
                  << (ignore_status ? "(ignored)" : "")
                  << value.verification_status << "\nFound:"
                  << "\n\t" << form_group.GetRawInfo(value.type)
diff --git a/components/autofill/core/browser/autofill_type.cc b/components/autofill/core/browser/autofill_type.cc
index a576275..8f00cff 100644
--- a/components/autofill/core/browser/autofill_type.cc
+++ b/components/autofill/core/browser/autofill_type.cc
@@ -71,18 +71,10 @@
 }
 
 std::string AutofillType::ToString() const {
-  if (IsUnknown())
-    return "UNKNOWN_TYPE";
-
-  if (server_type_ != UNKNOWN_TYPE)
-    return ServerFieldTypeToString(server_type_);
-
-  return std::string(FieldTypeToStringPiece(html_type_));
-}
-
-// static
-std::string AutofillType::ServerFieldTypeToString(ServerFieldType type) {
-  return std::string(FieldTypeToStringPiece(type));
+  return std::string(IsUnknown() ? "UNKNOWN_TYPE"
+                     : server_type_ != UNKNOWN_TYPE
+                         ? FieldTypeToStringPiece(server_type_)
+                         : FieldTypeToStringPiece(html_type_));
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_type.h b/components/autofill/core/browser/autofill_type.h
index defac33..2ca602f7 100644
--- a/components/autofill/core/browser/autofill_type.h
+++ b/components/autofill/core/browser/autofill_type.h
@@ -80,12 +80,8 @@
   // map to ADDRESS_HOME_COUNTRY.
   ServerFieldType GetStorableType() const;
 
-  // Serializes `this` type to a string.
   std::string ToString() const;
 
-  // Translates the ServerFieldType values into the corresponding strings.
-  static std::string ServerFieldTypeToString(ServerFieldType type);
-
  private:
   // The server-native field type, or UNKNOWN_TYPE if unset.
   ServerFieldType server_type_ = UNKNOWN_TYPE;
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
index f3d60db..65e5464 100644
--- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -7029,7 +7029,9 @@
   SCOPED_TRACE(base::StringPrintf(
       "Test: input_value='%s', field_type=%s, structured_names=%s ",
       test_case.input_value,
-      AutofillType(*test_case.field_types.begin()).ToString().c_str(), "true"));
+      std::string(FieldTypeToStringPiece(*test_case.field_types.begin()))
+          .c_str(),
+      "true"));
 
   // Take the field types depending on the state of the structured names
   // feature.
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc
index 6eb9b29..5efcba2a 100644
--- a/components/autofill/core/browser/data_model/autofill_profile.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -1209,9 +1209,8 @@
 
   // Lambda to print the value and verification status for |type|.
   auto print_values_lambda = [&os, &profile](ServerFieldType type) {
-    os << AutofillType::ServerFieldTypeToString(type) << ": "
-       << profile.GetRawInfo(type) << "(" << profile.GetVerificationStatus(type)
-       << ")" << std::endl;
+    os << FieldTypeToStringPiece(type) << ": " << profile.GetRawInfo(type)
+       << "(" << profile.GetVerificationStatus(type) << ")" << std::endl;
   };
 
   // Use a helper function to print the values of the stored types.
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_component.cc b/components/autofill/core/browser/data_model/autofill_structured_address_component.cc
index b3b068b..16adff7 100644
--- a/components/autofill/core/browser/data_model/autofill_structured_address_component.cc
+++ b/components/autofill/core/browser/data_model/autofill_structured_address_component.cc
@@ -99,7 +99,7 @@
 }
 
 std::string AddressComponent::GetStorageTypeName() const {
-  return AutofillType::ServerFieldTypeToString(storage_type_);
+  return std::string(FieldTypeToStringPiece(storage_type_));
 }
 
 void AddressComponent::CopyFrom(const AddressComponent& other) {
@@ -271,7 +271,7 @@
   std::vector<std::string> format_pieces;
   for (const auto& subcomponent : subcomponents_) {
     std::string format_piece = GetPlaceholderToken(
-        AutofillType(subcomponent->GetStorageType()).ToString());
+        FieldTypeToStringPiece(subcomponent->GetStorageType()));
     format_pieces.emplace_back(std::move(format_piece));
   }
   return base::ASCIIToUTF16(base::JoinString(format_pieces, " "));
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_test_utils.cc b/components/autofill/core/browser/data_model/autofill_structured_address_test_utils.cc
index 58a4227..6a47f332 100644
--- a/components/autofill/core/browser/data_model/autofill_structured_address_test_utils.cc
+++ b/components/autofill/core/browser/data_model/autofill_structured_address_test_utils.cc
@@ -62,7 +62,7 @@
   for (const auto& test_value : test_values) {
     SCOPED_TRACE(base::StringPrintf(
         "Failed type=%s, value=%s, status=%d",
-        AutofillType(test_value.type).ToString().c_str(),
+        std::string(FieldTypeToStringPiece(test_value.type)).c_str(),
         test_value.value.c_str(), static_cast<int>(test_value.status)));
 
     EXPECT_EQ(base::UTF16ToUTF8(component->GetValueForType(test_value.type)),
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_utils.cc b/components/autofill/core/browser/data_model/autofill_structured_address_utils.cc
index 10b5cc0..1f6c4e8 100644
--- a/components/autofill/core/browser/data_model/autofill_structured_address_utils.cc
+++ b/components/autofill/core/browser/data_model/autofill_structured_address_utils.cc
@@ -213,7 +213,7 @@
   return GetAllPartialMatches(value, "\\${([\\w]+)}");
 }
 
-std::string GetPlaceholderToken(const std::string& value) {
+std::string GetPlaceholderToken(std::string_view value) {
   return base::StrCat({"${", value, "}"});
 }
 
@@ -278,9 +278,9 @@
 
   // By adding an "i" in the first group, the capturing is case insensitive.
   // Allow multiple separators to support the ", " case.
-  return base::StrCat(
-      {"(?i:", prefix, "(?P<", AutofillType::ServerFieldTypeToString(type), ">",
-       pattern, ")", suffix, "(?:", options.separator, ")+)", quantifier});
+  return base::StrCat({"(?i:", prefix, "(?P<", FieldTypeToStringPiece(type),
+                       ">", pattern, ")", suffix, "(?:", options.separator,
+                       ")+)", quantifier});
 }
 
 std::string CaptureTypeWithSuffixedPattern(const ServerFieldType& type,
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_utils.h b/components/autofill/core/browser/data_model/autofill_structured_address_utils.h
index b77f20f3..69ae147 100644
--- a/components/autofill/core/browser/data_model/autofill_structured_address_utils.h
+++ b/components/autofill/core/browser/data_model/autofill_structured_address_utils.h
@@ -8,6 +8,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "base/containers/flat_map.h"
@@ -187,7 +188,7 @@
 std::vector<std::string> ExtractAllPlaceholders(const std::string& value);
 
 // Returns |value| as a placeholder token: ${value}.
-std::string GetPlaceholderToken(const std::string& value);
+std::string GetPlaceholderToken(std::string_view value);
 
 // Returns a named capture group created by the concatenation of the
 // StringPieces in |pattern_span_initializer_list|. The group is named by the
diff --git a/components/autofill/core/browser/data_model/contact_info.cc b/components/autofill/core/browser/data_model/contact_info.cc
index 8ff5dfa..01755576 100644
--- a/components/autofill/core/browser/data_model/contact_info.cc
+++ b/components/autofill/core/browser/data_model/contact_info.cc
@@ -104,7 +104,7 @@
     return;
   }
   bool success = name_->SetValueForType(type, value, status);
-  DCHECK(success) << AutofillType::ServerFieldTypeToString(type);
+  DCHECK(success) << FieldTypeToStringPiece(type);
 }
 
 void NameInfo::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc
index b37d7ae..794a0d8 100644
--- a/components/autofill/core/browser/form_data_importer.cc
+++ b/components/autofill/core/browser/form_data_importer.cc
@@ -78,8 +78,8 @@
        field_type_group != FieldTypeGroup::kPhone)) {
     LOG_AF(import_log_buffer)
         << LogMessage::kImportAddressProfileFromFormFailed
-        << "Multiple fields of type "
-        << AutofillType::ServerFieldTypeToString(field_type) << "." << CTag{};
+        << "Multiple fields of type " << FieldTypeToStringPiece(field_type)
+        << "." << CTag{};
     return false;
   }
   // Abandon the import if an email address value shows up in a field that is
@@ -88,7 +88,7 @@
     LOG_AF(import_log_buffer)
         << LogMessage::kImportAddressProfileFromFormFailed
         << "Email address found in field of different type: "
-        << AutofillType::ServerFieldTypeToString(field_type) << CTag{};
+        << FieldTypeToStringPiece(field_type) << CTag{};
     return false;
   }
 
diff --git a/components/autofill/core/browser/form_parsing/form_field.cc b/components/autofill/core/browser/form_parsing/form_field.cc
index 88932d59..9b1eb7b 100644
--- a/components/autofill/core/browser/form_parsing/form_field.cc
+++ b/components/autofill/core/browser/form_parsing/form_field.cc
@@ -251,8 +251,7 @@
 
       LogBuffer description;
       LOG_AF(description) << "BestHeuristicType: "
-                          << AutofillType::ServerFieldTypeToString(
-                                 f.best_heuristic_type)
+                          << FieldTypeToStringPiece(f.best_heuristic_type)
                           << ", is fillable: "
                           << IsFillableFieldType(f.best_heuristic_type);
 
diff --git a/components/autofill/core/browser/form_parsing/parsing_test_utils.cc b/components/autofill/core/browser/form_parsing/parsing_test_utils.cc
index fb4a5af..d40a1c0c 100644
--- a/components/autofill/core/browser/form_parsing/parsing_test_utils.cc
+++ b/components/autofill/core/browser/form_parsing/parsing_test_utils.cc
@@ -118,10 +118,9 @@
             ? field_candidates_map_[field_id].BestHeuristicType()
             : UNKNOWN_TYPE;
     SCOPED_TRACE(testing::Message()
-                 << "Found type "
-                 << AutofillType::ServerFieldTypeToString(actual_field_type)
+                 << "Found type " << FieldTypeToStringPiece(actual_field_type)
                  << ", expected type "
-                 << AutofillType::ServerFieldTypeToString(expected_field_type));
+                 << FieldTypeToStringPiece(expected_field_type));
     EXPECT_EQ(expected_field_type, actual_field_type);
     num_classifications += expected_field_type != UNKNOWN_TYPE;
   }
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 4adb07fb..f5e16cf5 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -838,9 +838,9 @@
           base::NumberToString(field->host_form_signature.value());
       annotated_field.signature = field->FieldSignatureAsStr();
       annotated_field.heuristic_type =
-          AutofillType(field->heuristic_type()).ToString();
+          FieldTypeToStringPiece(field->heuristic_type());
       annotated_field.server_type =
-          AutofillType(field->server_type()).ToString();
+          FieldTypeToStringPiece(field->server_type());
       annotated_field.overall_type = field->Type().ToString();
       annotated_field.parseable_name =
           base::UTF16ToUTF8(field->parseable_name());
@@ -1853,10 +1853,10 @@
     buffer << "\n  Name: " << field->parseable_name();
 
     auto type = field->Type().ToString();
-    auto heuristic_type = AutofillType(field->heuristic_type()).ToString();
-    auto server_type = AutofillType(field->server_type()).ToString();
-    if (field->server_type_prediction_is_override())
-      server_type += " (manual override)";
+    auto heuristic_type = FieldTypeToStringPiece(field->heuristic_type());
+    auto server_type = FieldTypeToStringPiece(field->server_type());
+    const char* is_override =
+        field->server_type_prediction_is_override() ? " (manual override)" : "";
     auto html_type_description =
         field->html_type() != HtmlFieldType::kUnspecified
             ? base::StrCat(
@@ -1868,8 +1868,9 @@
     }
 
     buffer << "\n  Type: "
-           << base::StrCat({type, " (heuristic: ", heuristic_type, ", server: ",
-                            server_type, html_type_description, ")"});
+           << base::StrCat({type, " (heuristic: ", heuristic_type,
+                            ", server: ", server_type, is_override,
+                            html_type_description, ")"});
     buffer << "\n  Section: " << field->section;
 
     constexpr size_t kMaxLabelSize = 100;
@@ -1928,8 +1929,10 @@
     buffer << Tr{} << "Placeholder:" << field->placeholder;
 
     auto type = field->Type().ToString();
-    auto heuristic_type = AutofillType(field->heuristic_type()).ToString();
-    auto server_type = AutofillType(field->server_type()).ToString();
+    auto heuristic_type =
+        std::string(FieldTypeToStringPiece(field->heuristic_type()));
+    auto server_type =
+        std::string(FieldTypeToStringPiece(field->server_type()));
     if (field->server_type_prediction_is_override())
       server_type += " (manual override)";
     auto html_type_description =
diff --git a/components/autofill/core/browser/form_structure_rationalizer.cc b/components/autofill/core/browser/form_structure_rationalizer.cc
index f63baed..8283be6 100644
--- a/components/autofill/core/browser/form_structure_rationalizer.cc
+++ b/components/autofill/core/browser/form_structure_rationalizer.cc
@@ -429,8 +429,7 @@
               << LoggingScope::kRationalization << LogMessage::kRationalization
               << "Multi-origin Credit Card Rationalization: Converting type of "
               << field->global_id() << " from "
-              << AutofillType::ServerFieldTypeToString(relevant_type)
-              << " to UNKNOWN_TYPE";
+              << FieldTypeToStringPiece(relevant_type) << " to UNKNOWN_TYPE";
         }
       }
     }
@@ -573,9 +572,8 @@
         field.SetTypeTo(AutofillType(new_type));
         LOG_AF(log_manager)
             << LoggingScope::kRationalization << LogMessage::kRationalization
-            << "Converting "
-            << AutofillType::ServerFieldTypeToString(current_type) << " to "
-            << AutofillType::ServerFieldTypeToString(new_type)
+            << "Converting " << FieldTypeToStringPiece(current_type) << " to "
+            << FieldTypeToStringPiece(new_type)
             << " as part of phone number trunk type rationalization";
       };
 
diff --git a/components/autofill/core/browser/heuristic_classification_unittests.cc b/components/autofill/core/browser/heuristic_classification_unittests.cc
index 95a2fe0..ef4da30 100644
--- a/components/autofill/core/browser/heuristic_classification_unittests.cc
+++ b/components/autofill/core/browser/heuristic_classification_unittests.cc
@@ -210,9 +210,8 @@
     }
 
     // Determine the type assigned to the field by the heuristic classification.
-    std::string heuristic_type =
-        AutofillType(form_structure.field(i)->Type().GetStorableType())
-            .ToString();
+    std::string heuristic_type = std::string(FieldTypeToStringPiece(
+        form_structure.field(i)->Type().GetStorableType()));
 
     // Record metrics on the divergence between tester and heuristics.
     if (fields_in_scope_.contains(tester_type)) {
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc
index 83fd409..6550695 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -495,8 +495,7 @@
   if (collapsed_field_types.size() == 1)
     actual_type = *collapsed_field_types.begin();
 
-  DVLOG(2) << "Inferred Type: "
-           << AutofillType::ServerFieldTypeToString(actual_type);
+  DVLOG(2) << "Inferred Type: " << FieldTypeToStringPiece(actual_type);
   return actual_type;
 }
 
@@ -702,9 +701,8 @@
   ServerFieldType actual_type =
       GetActualFieldType(possible_types, predicted_type);
 
-  DVLOG(2) << "Predicted: "
-           << AutofillType::ServerFieldTypeToString(predicted_type) << "; "
-           << "Actual: " << AutofillType::ServerFieldTypeToString(actual_type);
+  DVLOG(2) << "Predicted: " << FieldTypeToStringPiece(predicted_type) << "; "
+           << "Actual: " << FieldTypeToStringPiece(actual_type);
 
   DCHECK_LE(predicted_type, UINT16_MAX);
   DCHECK_LE(actual_type, UINT16_MAX);
diff --git a/components/autofill/core/browser/metrics/quality_metrics_unittest.cc b/components/autofill/core/browser/metrics/quality_metrics_unittest.cc
index cf675d8..012f658dfe 100644
--- a/components/autofill/core/browser/metrics/quality_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/quality_metrics_unittest.cc
@@ -530,9 +530,8 @@
   ServerFieldType predicted_type = GetParam().predicted_field_type;
 
   DVLOG(2) << "Test Case = Predicted: "
-           << AutofillType::ServerFieldTypeToString(predicted_type) << "; "
-           << "Actual: "
-           << AutofillType::ServerFieldTypeToString(actual_field_type);
+           << FieldTypeToStringPiece(predicted_type) << "; "
+           << "Actual: " << FieldTypeToStringPiece(actual_field_type);
 
   FormData form = CreateForm(
       {CreateTestFormField("first", "first", ValueForType(NAME_FIRST), "text"),
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index 14a8541..82efc14 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -254,7 +254,7 @@
 // features disabled but not client-side features.
 BASE_FEATURE(kAutofillUpstreamAuthenticatePreflightCall,
              "AutofillUpstreamAuthenticatePreflightCall",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // When enabled, the secure data type for cards sent during credit card upload
 // save is updated to match newer server requirements.
@@ -281,6 +281,12 @@
 BASE_FEATURE(kAutofillEnablePaymentsMandatoryReauthOnBling,
              "AutofillEnablePaymentsMandatoryReauthOnBling",
              base::FEATURE_DISABLED_BY_DEFAULT);
+
+// When this is enabled, virtual card enrollment and retrieval will be enabled
+// on Bling.
+BASE_FEATURE(kAutofillEnableVirtualCards,
+             "AutofillEnableVirtualCards",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 #endif
 
 #if BUILDFLAG(IS_ANDROID)
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h
index 4ac60d1..dda604c 100644
--- a/components/autofill/core/common/autofill_payments_features.h
+++ b/components/autofill/core/common/autofill_payments_features.h
@@ -58,6 +58,7 @@
 #if BUILDFLAG(IS_IOS)
 BASE_DECLARE_FEATURE(kAutofillUseTwoDotsForLastFourDigits);
 BASE_DECLARE_FEATURE(kAutofillEnablePaymentsMandatoryReauthOnBling);
+BASE_DECLARE_FEATURE(kAutofillEnableVirtualCards);
 #endif
 
 #if BUILDFLAG(IS_ANDROID)
diff --git a/components/autofill/core/common/form_field_data.cc b/components/autofill/core/common/form_field_data.cc
index 5be7a4d8..e90fc8ae 100644
--- a/components/autofill/core/common/form_field_data.cc
+++ b/components/autofill/core/common/form_field_data.cc
@@ -376,6 +376,16 @@
   return properties_mask & kAutofilled;
 }
 
+std::u16string FormFieldData::GetSelection() const {
+  return std::u16string(GetSelectionAsStringView());
+}
+
+std::u16string_view FormFieldData::GetSelectionAsStringView() const {
+  size_t offset = std::min(static_cast<size_t>(selection_start), value.size());
+  size_t length = selection_end - selection_start;
+  return std::u16string_view(value).substr(offset, length);
+}
+
 // static
 bool FormFieldData::DeepEqual(const FormFieldData& a, const FormFieldData& b) {
   return a.unique_renderer_id == b.unique_renderer_id &&
diff --git a/components/autofill/core/common/form_field_data.h b/components/autofill/core/common/form_field_data.h
index 1ade809..903c26c 100644
--- a/components/autofill/core/common/form_field_data.h
+++ b/components/autofill/core/common/form_field_data.h
@@ -239,6 +239,11 @@
   bool HadFocus() const;
   bool WasPasswordAutofilled() const;
 
+  // Returns the currently selected text. Returns the empty string if
+  // `selection_start` and/or `selection_end` are out of bounds.
+  std::u16string GetSelection() const;
+  std::u16string_view GetSelectionAsStringView() const;
+
   // NOTE: Update `SameFieldAs()` and `FormFieldDataAndroid::SimilarFieldAs()`
   // if needed when adding new a member.
 
@@ -253,6 +258,14 @@
   std::u16string name_attribute;
   std::u16string label;
   std::u16string value;
+  // The range within `value` that is selected. `selection_start` points at the
+  // first selected character, `selection_end` points after the last selected
+  // character. That is, if nothing is selected, `selection_start` and
+  // `selection_end` are identical and represent the cursor position.
+  // Use GetSelection() or GetSelectionAsStringView() to safely get the selected
+  // substring of `value`.
+  uint32_t selection_start = 0;
+  uint32_t selection_end = 0;
   std::string form_control_type;
   std::string autocomplete_attribute;
   absl::optional<AutocompleteParsingResult> parsed_autocomplete;
diff --git a/components/autofill/core/common/form_field_data_unittest.cc b/components/autofill/core/common/form_field_data_unittest.cc
index 49a8e947..6c462fa 100644
--- a/components/autofill/core/common/form_field_data_unittest.cc
+++ b/components/autofill/core/common/form_field_data_unittest.cc
@@ -442,4 +442,31 @@
   }
 }
 
+class FormFieldDataGetSelectionTest
+    : public ::testing::TestWithParam<
+          std::tuple<size_t, size_t, const char16_t*>> {
+ public:
+  size_t selection_start() const { return std::get<0>(GetParam()); }
+  size_t selection_end() const { return std::get<1>(GetParam()); }
+  std::u16string expectation() const { return std::get<2>(GetParam()); }
+};
+
+INSTANTIATE_TEST_SUITE_P(FormFieldDataTest,
+                         FormFieldDataGetSelectionTest,
+                         ::testing::Values(std::make_tuple(0u, 0u, u""),
+                                           std::make_tuple(0u, 3u, u"foo"),
+                                           std::make_tuple(3u, 6u, u"bar"),
+                                           std::make_tuple(6u, 6u, u""),
+                                           std::make_tuple(0u, 100, u"foobar"),
+                                           std::make_tuple(100u, 1000u, u"")));
+
+TEST_P(FormFieldDataGetSelectionTest, GetSelection) {
+  FormFieldData field;
+  field.value = u"foobar";
+  field.selection_start = selection_start();
+  field.selection_end = selection_end();
+  EXPECT_EQ(expectation(), field.GetSelection());
+  EXPECT_EQ(expectation(), field.GetSelectionAsStringView());
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/common/mojom/autofill_types.mojom b/components/autofill/core/common/mojom/autofill_types.mojom
index 5e9fddf..5d9f48ac 100644
--- a/components/autofill/core/common/mojom/autofill_types.mojom
+++ b/components/autofill/core/common/mojom/autofill_types.mojom
@@ -328,6 +328,8 @@
   mojo_base.mojom.String16 id_attribute;
   mojo_base.mojom.String16 name_attribute;
   mojo_base.mojom.String16 value;
+  uint32 selection_start;
+  uint32 selection_end;
   string form_control_type;
   string autocomplete_attribute;
   AutocompleteParsingResult? parsed_autocomplete;
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
index 8f162b9..b6b34c96 100644
--- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
+++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
@@ -177,6 +177,10 @@
     return false;
   if (!data.ReadValue(&out->value))
     return false;
+  uint32_t max_length = out->value.length();
+  out->selection_end = std::min(data.selection_end(), max_length);
+  out->selection_start = std::min(data.selection_start(), out->selection_end);
+  DCHECK_LE(out->selection_start, out->selection_end);
 
   if (!data.ReadFormControlType(&out->form_control_type))
     return false;
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
index d116d7c7..0e12cc0 100644
--- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
+++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
@@ -209,6 +209,14 @@
     return r.value;
   }
 
+  static uint32_t selection_start(const autofill::FormFieldData& r) {
+    return r.selection_start;
+  }
+
+  static uint32_t selection_end(const autofill::FormFieldData& r) {
+    return r.selection_end;
+  }
+
   static const std::string& form_control_type(
       const autofill::FormFieldData& r) {
     return r.form_control_type;
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
index b8db481..7c820b3 100644
--- a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
+++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
@@ -182,6 +182,8 @@
   EXPECT_TRUE(FormFieldData::DeepEqual(test::WithoutUnserializedData(expected),
                                        passed));
   EXPECT_EQ(expected.value, passed.value);
+  EXPECT_EQ(expected.selection_start, passed.selection_start);
+  EXPECT_EQ(expected.selection_end, passed.selection_end);
   EXPECT_EQ(expected.user_input, passed.user_input);
   std::move(closure).Run();
 }
@@ -292,9 +294,13 @@
       "TestLabel", "TestName", "TestValue", kOptions, kOptions);
   // Set other attributes to check if they are passed correctly.
   input.host_frame = test::MakeLocalFrameToken();
-  input.unique_renderer_id = FieldRendererId(1234);
+  input.name = u"name";
   input.id_attribute = u"id";
   input.name_attribute = u"name";
+  input.value = u"value";
+  input.selection_start = 1;
+  input.selection_end = 2;
+  input.form_control_type = "text";
   input.autocomplete_attribute = "on";
   input.parsed_autocomplete =
       AutocompleteParsingResult{.section = "autocomplete_section",
@@ -304,6 +310,8 @@
   input.css_classes = u"class1";
   input.aria_label = u"aria label";
   input.aria_description = u"aria description";
+  input.unique_renderer_id = FieldRendererId(1234);
+  input.host_form_id = FormRendererId(123);
   input.max_length = 12345;
   input.is_autofilled = true;
   input.check_status = FormFieldData::CheckStatus::kChecked;
diff --git a/components/browser_ui/accessibility/android/BUILD.gn b/components/browser_ui/accessibility/android/BUILD.gn
index c1c2506..442a71c 100644
--- a/components/browser_ui/accessibility/android/BUILD.gn
+++ b/components/browser_ui/accessibility/android/BUILD.gn
@@ -57,7 +57,6 @@
     "//base:base_java",
     "//base:jni_java",
     "//build/android:build_java",
-    "//chrome/browser/preferences:java",
     "//components/browser_ui/settings/android:java",
     "//components/browser_ui/site_settings/android:java",
     "//components/prefs/android:java",
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java
index d5064ed..df42603 100644
--- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java
+++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java
@@ -12,13 +12,11 @@
 import androidx.preference.PreferenceFragmentCompat;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.components.browser_ui.accessibility.AccessibilitySettingsDelegate.BooleanPreferenceDelegate;
 import org.chromium.components.browser_ui.accessibility.FontSizePrefs.FontSizePrefsObserver;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.browser_ui.settings.CustomDividerFragment;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
-import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.content_public.browser.ContentFeatureList;
 import org.chromium.content_public.browser.ContentFeatureMap;
 
@@ -86,18 +84,17 @@
 
         if (mDelegate.showPageZoomSettingsUI()) {
             mTextScalePref.setVisible(false);
-            // Set the initial values for page zoom and text contrast.
+            // Set the initial values for the page zoom settings, and set change listeners.
             mPageZoomDefaultZoomPref.setInitialValue(PageZoomUtils.getDefaultZoomAsSeekBarValue(
                     mDelegate.getBrowserContextHandle()));
-            mPageZoomDefaultZoomPref.setmBrowserContextHandle(mDelegate.getBrowserContextHandle());
-            if (ContentFeatureMap.isEnabled(ContentFeatureList.SMART_ZOOM)) {
-                mPageZoomDefaultZoomPref.setInitialTextSizeContrastValue(
-                        UserPrefs.get(mDelegate.getBrowserContextHandle())
-                                .getInteger(Pref.ACCESSIBILITY_TEXT_SIZE_CONTRAST_FACTOR));
-            }
             mPageZoomDefaultZoomPref.setOnPreferenceChangeListener(this);
             mPageZoomAlwaysShowPref.setChecked(PageZoomUtils.shouldShowZoomMenuItem());
             mPageZoomAlwaysShowPref.setOnPreferenceChangeListener(this);
+            // When Smart Zoom feature is enabled, set the required delegate.
+            if (ContentFeatureMap.isEnabled(ContentFeatureList.SMART_ZOOM)) {
+                mPageZoomDefaultZoomPref.setTextSizeContrastDelegate(
+                        mDelegate.getTextSizeContrastAccessibilityDelegate());
+            }
         } else {
             mPageZoomDefaultZoomPref.setVisible(false);
             mPageZoomAlwaysShowPref.setVisible(false);
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettingsDelegate.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettingsDelegate.java
index 341ab0e..842c581 100644
--- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettingsDelegate.java
+++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettingsDelegate.java
@@ -29,6 +29,20 @@
         void setEnabled(boolean value);
     }
 
+    /** An interface to control a single integer preference. */
+    interface IntegerPreferenceDelegate {
+        /**
+         * @return int - Current value of the preference of this instance.
+         */
+        int getValue();
+
+        /**
+         * Sets a new value for the preference of this instance.
+         * @param value
+         */
+        void setValue(int value);
+    }
+
     /**
      * @return The BrowserContextHandle that should be used to read and update settings.
      */
@@ -41,6 +55,12 @@
     BooleanPreferenceDelegate getReaderForAccessibilityDelegate();
 
     /**
+     * @return the InterPreferenceDelegate instance that should be used for reading and setting the
+     * text size contrast value for accessibility settings. Return null to omit the preference.
+     */
+    IntegerPreferenceDelegate getTextSizeContrastAccessibilityDelegate();
+
+    /**
      * Allows the embedder to add more preferences to the preference screen.
      *
      * @param fragment the fragment to add the preferences to.
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomPreference.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomPreference.java
index ca0aba3..2a034f6 100644
--- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomPreference.java
+++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomPreference.java
@@ -20,9 +20,7 @@
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
-import org.chromium.chrome.browser.preferences.Pref;
-import org.chromium.components.user_prefs.UserPrefs;
-import org.chromium.content_public.browser.BrowserContextHandle;
+import org.chromium.components.browser_ui.accessibility.AccessibilitySettingsDelegate.IntegerPreferenceDelegate;
 import org.chromium.content_public.browser.ContentFeatureList;
 import org.chromium.content_public.browser.ContentFeatureMap;
 import org.chromium.ui.widget.ChromeImageButton;
@@ -32,17 +30,17 @@
  */
 public class PageZoomPreference extends Preference implements SeekBar.OnSeekBarChangeListener {
     private int mInitialValue;
-    private BrowserContextHandle mBrowserContextHandle;
     private SeekBar mSeekBar;
     private ChromeImageButton mDecreaseButton;
     private ChromeImageButton mIncreaseButton;
     private TextView mCurrentValueText;
 
-    private int mInitialTextSizeContrastLevel;
     private SeekBar mTextSizeContrastSeekBar;
     private ChromeImageButton mTextSizeContrastDecreaseButton;
     private ChromeImageButton mTextSizeContrastIncreaseButton;
     private TextView mTextSizeContrastCurrentLevelText;
+    private IntegerPreferenceDelegate mTextSizeContrastDelegate;
+    private static final int TEXT_SIZE_CONTRAST_BUTTON_INCREMENT = 10;
 
     // Values taken from dimens of text_size_* in //ui/android/java/res/values/dimens.xml
     private static final float DEFAULT_LARGE_TEXT_SIZE_SP = 16.0f;
@@ -66,10 +64,6 @@
         setLayoutResource(R.layout.page_zoom_preference);
     }
 
-    public void setmBrowserContextHandle(BrowserContextHandle browserContextHandle) {
-        mBrowserContextHandle = browserContextHandle;
-    }
-
     @Override
     public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
@@ -113,6 +107,9 @@
 
         // Set up text size contrast slider.
         if (ContentFeatureMap.isEnabled(ContentFeatureList.SMART_ZOOM)) {
+            holder.findViewById(R.id.text_size_contrast_title).setVisibility(View.VISIBLE);
+            holder.findViewById(R.id.text_size_contrast_summary).setVisibility(View.VISIBLE);
+
             mTextSizeContrastCurrentLevelText =
                     (TextView) holder.findViewById(R.id.text_size_contrast_current_value_text);
             mTextSizeContrastCurrentLevelText.setText(
@@ -132,9 +129,9 @@
                     (SeekBar) holder.findViewById(R.id.text_size_contrast_slider);
             mTextSizeContrastSeekBar.setOnSeekBarChangeListener(this);
             mTextSizeContrastSeekBar.setMax(PageZoomUtils.TEXT_SIZE_CONTRAST_MAX_LEVEL);
-            mTextSizeContrastSeekBar.setProgress(mInitialTextSizeContrastLevel);
-            mTextSizeContrastFactor = mInitialTextSizeContrastLevel;
-            updateViewsOnProgressChanged(mInitialTextSizeContrastLevel, mTextSizeContrastSeekBar);
+            mTextSizeContrastFactor = mTextSizeContrastDelegate.getValue();
+            mTextSizeContrastSeekBar.setProgress(mTextSizeContrastFactor);
+            updateViewsOnProgressChanged(mTextSizeContrastFactor, mTextSizeContrastSeekBar);
 
             mTextSizeContrastCurrentLevelText.setVisibility(View.VISIBLE);
             holder.findViewById(R.id.text_size_contrast_current_value_text)
@@ -153,11 +150,11 @@
     }
 
     /**
-     * Initial values to set the progress of seekbars.
-     * @param contrastLevel int - existing user pref value for contrast factor (or default).
+     * Set a delegate for the text size contrast slider functionality.
+     * @param delegate IntegerPreferenceDelegate - embedder's instance of a preference delegate.
      */
-    public void setInitialTextSizeContrastValue(int contrastLevel) {
-        mInitialTextSizeContrastLevel = contrastLevel;
+    public void setTextSizeContrastDelegate(IntegerPreferenceDelegate delegate) {
+        mTextSizeContrastDelegate = delegate;
     }
 
     private void updateViewsOnProgressChanged(int progress, SeekBar seekBar) {
@@ -217,10 +214,9 @@
             mIncreaseButton.setEnabled(
                     newZoomFactor < AVAILABLE_ZOOM_FACTORS[AVAILABLE_ZOOM_FACTORS.length - 1]);
         } else if (seekBar.getId() == R.id.text_size_contrast_slider) {
-            double newContrastLevel = progress;
-            mTextSizeContrastDecreaseButton.setEnabled(newContrastLevel > 0);
+            mTextSizeContrastDecreaseButton.setEnabled(progress > 0);
             mTextSizeContrastIncreaseButton.setEnabled(
-                    newContrastLevel < PageZoomUtils.TEXT_SIZE_CONTRAST_MAX_LEVEL);
+                    progress < PageZoomUtils.TEXT_SIZE_CONTRAST_MAX_LEVEL);
         }
     }
 
@@ -240,10 +236,7 @@
             // When a user stops changing the slider value, record the new value in prefs.
             callChangeListener(seekBar.getProgress());
         } else if (seekBar.getId() == R.id.text_size_contrast_slider) {
-            UserPrefs.get(mBrowserContextHandle)
-                    .setInteger(
-                            Pref.ACCESSIBILITY_TEXT_SIZE_CONTRAST_FACTOR, seekBar.getProgress());
-            // TODO(crbug.com/1459631): Add page refresh functionality
+            saveTextSizeContrastValueToPreferences();
         }
     }
 
@@ -276,20 +269,20 @@
     }
 
     private void onHandleContrastDecreaseClicked() {
-        // Decrease the contrast slider in increments of 10.
-        // TODO(crbug.com/1459631): determine how we want to control contrast levels (range and
-        // decrement increments).
-        mTextSizeContrastSeekBar.setProgress(mTextSizeContrastSeekBar.getProgress() - 10);
-        // TODO(crbug.com/1459631): add functionality to save the new progress variable to a profile
-        // setting, which can access on c++ side.
+        // Decrease the contrast slider by defined increment.
+        mTextSizeContrastSeekBar.setProgress(
+                mTextSizeContrastSeekBar.getProgress() - TEXT_SIZE_CONTRAST_BUTTON_INCREMENT);
+        saveTextSizeContrastValueToPreferences();
     }
 
     private void onHandleContrastIncreaseClicked() {
-        // Increase the contrast slider in increments of 10.
-        // TODO(crbug.com/1459631): determine how we want to control contrast levels (range and
-        // decrement increments).
-        mTextSizeContrastSeekBar.setProgress(mTextSizeContrastSeekBar.getProgress() + 10);
-        // TODO(crbug.com/1459631): add functionality to save the new progress variable to a profile
-        // setting, which can access on c++ side.
+        // Increase the contrast slider by defined increment.
+        mTextSizeContrastSeekBar.setProgress(
+                mTextSizeContrastSeekBar.getProgress() + TEXT_SIZE_CONTRAST_BUTTON_INCREMENT);
+        saveTextSizeContrastValueToPreferences();
+    }
+
+    private void saveTextSizeContrastValueToPreferences() {
+        mTextSizeContrastDelegate.setValue(mTextSizeContrastSeekBar.getProgress());
     }
 }
\ No newline at end of file
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtils.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtils.java
index b5dc3924..d4385fed 100644
--- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtils.java
+++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtils.java
@@ -49,7 +49,8 @@
     // The max value for the seek bar to help with rounding effects (not shown to user).
     public static final int PAGE_ZOOM_MAXIMUM_SEEKBAR_VALUE = 250;
 
-    public static final int TEXT_SIZE_CONTRAST_MAX_LEVEL = 50;
+    // The max value for the text size contrast seek bar, used in Smart Zoom feature.
+    public static final int TEXT_SIZE_CONTRAST_MAX_LEVEL = 100;
 
     // The minimum and maximum zoom values as a percentage (e.g. 50% = 0.50, 300% = 3.0).
     protected static final float PAGE_ZOOM_MINIMUM_ZOOM_LEVEL = 0.50f;
diff --git a/components/browsing_data/content/BUILD.gn b/components/browsing_data/content/BUILD.gn
index 53d35d3b..d8a1736 100644
--- a/components/browsing_data/content/BUILD.gn
+++ b/components/browsing_data/content/BUILD.gn
@@ -54,6 +54,8 @@
     "//content/public/browser",
     "//net",
   ]
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
 source_set("unit_tests") {
diff --git a/components/browsing_data/content/browsing_data_model.cc b/components/browsing_data/content/browsing_data_model.cc
index bac9b3e3..5125bfe 100644
--- a/components/browsing_data/content/browsing_data_model.cc
+++ b/components/browsing_data/content/browsing_data_model.cc
@@ -502,6 +502,44 @@
   std::move(loaded_callback).Run();
 }
 
+// If `data_key` represents a non-1P partition, returns the site on which it
+// is partitioned, absl::nullopt otherwise.
+absl::optional<net::SchemefulSite> GetThirdPartyPartitioningSite(
+    const BrowsingDataModel::DataKey& data_key) {
+  absl::optional<net::SchemefulSite> top_level_site = absl::nullopt;
+  absl::visit(
+      base::Overloaded{
+          [&](const url::Origin&) {},
+          [&](const content::InterestGroupManager::InterestGroupDataKey) {},
+          [&](const content::AttributionDataModel::DataKey) {},
+          [&](const content::PrivateAggregationDataModel::DataKey) {},
+          [&](const blink::StorageKey& storage_key) {
+            if (storage_key.IsThirdPartyContext()) {
+              top_level_site = storage_key.top_level_site();
+            }
+          },
+          [&](const content::SessionStorageUsageInfo& info) {
+            if (info.storage_key.IsThirdPartyContext()) {
+              top_level_site = info.storage_key.top_level_site();
+            }
+          },
+          [&](const browsing_data::SharedWorkerInfo& info) {
+            if (info.storage_key.IsThirdPartyContext()) {
+              top_level_site = info.storage_key.top_level_site();
+            }
+          },
+          [&](const net::SharedDictionaryIsolationKey& key) {
+            if (net::SchemefulSite(key.frame_origin()) !=
+                key.top_frame_site()) {
+              top_level_site = key.top_frame_site();
+            }
+          },
+      },
+      data_key);
+
+  return top_level_site;
+}
+
 }  // namespace
 
 BrowsingDataModel::DataDetails::~DataDetails() = default;
@@ -539,6 +577,13 @@
                      *data_owner);
 }
 
+absl::optional<net::SchemefulSite>
+BrowsingDataModel::BrowsingDataEntryView::GetThirdPartyPartitioningSite()
+    const {
+  // Partition information is only dependent on it's `data_key`.
+  return ::GetThirdPartyPartitioningSite(data_key.get());
+}
+
 BrowsingDataModel::Delegate::DelegateEntry::DelegateEntry(
     DataKey data_key,
     StorageType storage_type,
@@ -721,17 +766,8 @@
   DataKeyEntries affected_data_key_entries;
 
   for (const auto& entry : browsing_data_entries_[data_owner]) {
-    // TODO(crbug/1455899): Consider other data keys that can be partitioned,
-    // probably making use of a visitor pattern.
-    auto* storage_key = absl::get_if<blink::StorageKey>(&entry.first);
-    if (!storage_key) {
+    if (!GetThirdPartyPartitioningSite(entry.first).has_value()) {
       affected_data_key_entries.insert(entry);
-      continue;
-    }
-
-    if (storage_key->IsFirstPartyContext()) {
-      affected_data_key_entries.insert(entry);
-      continue;
     }
   }
 
@@ -868,14 +904,7 @@
         const net::SchemefulSite& top_level_site,
         DataKeyEntries& affected_data_key_entries) {
   for (const auto& entry : browsing_data_entries_[data_owner]) {
-    // TODO(crbug/1455899): Consider other data keys that can be partitioned,
-    // probably making use of a visitor pattern.
-    auto* storage_key = absl::get_if<blink::StorageKey>(&entry.first);
-    if (!storage_key) {
-      continue;
-    }
-
-    if (storage_key->top_level_site() == top_level_site) {
+    if (GetThirdPartyPartitioningSite(entry.first) == top_level_site) {
       affected_data_key_entries.insert(entry);
     }
   }
diff --git a/components/browsing_data/content/browsing_data_model.h b/components/browsing_data/content/browsing_data_model.h
index ffe25c5..b470631 100644
--- a/components/browsing_data/content/browsing_data_model.h
+++ b/components/browsing_data/content/browsing_data_model.h
@@ -106,6 +106,10 @@
     // Returns true if |origin| is within this browsing data's  owning entity.
     bool Matches(const url::Origin& origin) const;
 
+    // Returns the non-1P SchemefulSite this data is partitioned on. Returns
+    // base::nullopt if the data is not partitioned, or is the 1P partition.
+    absl::optional<net::SchemefulSite> GetThirdPartyPartitioningSite() const;
+
     // The logical owner of this browsing data. This is the entity which this
     // information will be most strongly associated with in UX surfaces.
     const raw_ref<const DataOwner, DanglingUntriaged> data_owner;
diff --git a/components/browsing_data/content/browsing_data_model_unittest.cc b/components/browsing_data/content/browsing_data_model_unittest.cc
index bc170a0..3da550c1 100644
--- a/components/browsing_data/content/browsing_data_model_unittest.cc
+++ b/components/browsing_data/content/browsing_data_model_unittest.cc
@@ -583,6 +583,79 @@
               kTestDelegateTypePartitioned)));
 }
 
+TEST_F(BrowsingDataModelTest, HasThirdPartyPartitioningSite_True) {
+  // Check the logic for determining whether data is partitioned.
+  std::unique_ptr<BrowsingDataModel> model = BrowsingDataModel::BuildEmpty(
+      storage_partition(),
+      std::make_unique<browsing_data::TestBrowsingDataModelDelegate>());
+
+  // Create a set of storage keys which all represent partitioned versions of
+  // their data.
+  auto partitioned_storage_key =
+      blink::StorageKey::Create(kSiteOrigin, net::SchemefulSite(kTestOrigin),
+                                blink::mojom::AncestorChainBit::kCrossSite,
+                                /*third_party_partitioning_allowed=*/true);
+  auto partitioned_session_storage_usage =
+      content::SessionStorageUsageInfo{partitioned_storage_key, "example"};
+  auto partitioned_shared_dictionary_key = net::SharedDictionaryIsolationKey{
+      kSiteOrigin, net::SchemefulSite(kTestOrigin)};
+  auto partitioned_shared_worker_info = browsing_data::SharedWorkerInfo(
+      kSiteOrigin.GetURL(), "example", partitioned_storage_key);
+
+  model->AddBrowsingData(partitioned_storage_key,
+                         BrowsingDataModel::StorageType::kQuotaStorage, 0, 0);
+  model->AddBrowsingData(partitioned_session_storage_usage,
+                         BrowsingDataModel::StorageType::kSessionStorage, 0, 0);
+  model->AddBrowsingData(partitioned_shared_dictionary_key,
+                         BrowsingDataModel::StorageType::kSharedDictionary, 0,
+                         0);
+  model->AddBrowsingData(partitioned_shared_worker_info,
+                         BrowsingDataModel::StorageType::kSharedWorker, 0, 0);
+
+  // Check that every model entry is partitioned, and the site matches.
+  for (const auto& entry : *model) {
+    EXPECT_EQ(partitioned_storage_key.top_level_site(),
+              *entry.GetThirdPartyPartitioningSite());
+  }
+}
+
+TEST_F(BrowsingDataModelTest, HasThirdPartyPartitioningSite_False) {
+  // Check the logic for determining whether data is partitioned.
+  std::unique_ptr<BrowsingDataModel> model = BrowsingDataModel::BuildEmpty(
+      storage_partition(),
+      std::make_unique<browsing_data::TestBrowsingDataModelDelegate>());
+
+  // Create a set of storage keys which all represent un-partitioned versions of
+  // their data.
+  auto unpartitioned_storage_key =
+      blink::StorageKey::CreateFirstParty(kSiteOrigin);
+  auto unpartitioned_session_storage_usage =
+      content::SessionStorageUsageInfo{unpartitioned_storage_key, "example"};
+  auto unpartitioned_shared_dictionary_key = net::SharedDictionaryIsolationKey{
+      kSubdomainOrigin, net::SchemefulSite(kSiteOrigin)};
+  auto unpartitioned_shared_worker_info = browsing_data::SharedWorkerInfo(
+      kSiteOrigin.GetURL(), "example", unpartitioned_storage_key);
+  auto non_partition_key = kAnotherTestOrigin;
+
+  model->AddBrowsingData(unpartitioned_storage_key,
+                         BrowsingDataModel::StorageType::kQuotaStorage, 0, 0);
+  model->AddBrowsingData(unpartitioned_session_storage_usage,
+                         BrowsingDataModel::StorageType::kSessionStorage, 0, 0);
+  model->AddBrowsingData(unpartitioned_shared_dictionary_key,
+                         BrowsingDataModel::StorageType::kSharedDictionary, 0,
+                         0);
+  model->AddBrowsingData(unpartitioned_shared_worker_info,
+                         BrowsingDataModel::StorageType::kSharedWorker, 0, 0);
+  model->AddBrowsingData(non_partition_key,
+                         BrowsingDataModel::StorageType::kTrustTokens, 0, 0);
+
+  // Check that every model entry is not partitioned, and so has no
+  // partitioning site.
+  for (const auto& entry : *model) {
+    EXPECT_FALSE(entry.GetThirdPartyPartitioningSite().has_value());
+  }
+}
+
 class BrowsingDataModelSharedDictionaryTest : public BrowsingDataModelTest {
  public:
   BrowsingDataModelSharedDictionaryTest() {
diff --git a/components/browsing_data/core/BUILD.gn b/components/browsing_data/core/BUILD.gn
index 47b02706..b362eca 100644
--- a/components/browsing_data/core/BUILD.gn
+++ b/components/browsing_data/core/BUILD.gn
@@ -47,6 +47,8 @@
     "//components/webdata/common",
     "//ui/base",
   ]
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
 if (is_android) {
diff --git a/components/browsing_data/core/browsing_data_policies_utils.cc b/components/browsing_data/core/browsing_data_policies_utils.cc
index 7cb23695..3086da7 100644
--- a/components/browsing_data/core/browsing_data_policies_utils.cc
+++ b/components/browsing_data/core/browsing_data_policies_utils.cc
@@ -17,21 +17,21 @@
 
 namespace browsing_data {
 
+namespace {
+
 namespace policy_data_types {
 // Data retention policy types that require sync to be disabled.
-const char kBrowsingHistoryName[] = "browsing_history";
-const char kPasswordSigninName[] = "password_signin";
-const char kAutofillName[] = "autofill";
-const char kSiteSettingsName[] = "site_settings";
+constexpr char kBrowsingHistoryName[] = "browsing_history";
+constexpr char kPasswordSigninName[] = "password_signin";
+constexpr char kAutofillName[] = "autofill";
+constexpr char kSiteSettingsName[] = "site_settings";
 // Data retention policy types that do not require sync to be disabled.
-const char kHostedAppDataName[] = "hosted_app_data";
-const char kDownloadHistoryName[] = "download_history";
-const char kCookiesAndOtherSiteDataName[] = "cookies_and_other_site_data";
-const char kCachedImagesAndFilesName[] = "cached_images_and_files";
+constexpr char kHostedAppDataName[] = "hosted_app_data";
+constexpr char kDownloadHistoryName[] = "download_history";
+constexpr char kCookiesAndOtherSiteDataName[] = "cookies_and_other_site_data";
+constexpr char kCachedImagesAndFilesName[] = "cached_images_and_files";
 }  // namespace policy_data_types
 
-namespace {
-
 // The format of the log message shown in chrome://policy/logs when sync types
 // are automatically disabled.
 constexpr char kDisabledSyncTypesLogFormat[] =
@@ -43,23 +43,23 @@
                                syncer::UserSelectableTypeSet* sync_types) {
   // Map of browsing data types to sync types that need to be disabled for
   // them.
-  static const auto kDataToSyncTypesMap =
-      base::MakeFixedFlatMap<std::string, syncer::UserSelectableTypeSet>(
-          {{browsing_data::policy_data_types::kBrowsingHistoryName,
+  static constexpr auto kDataToSyncTypesMap =
+      base::MakeFixedFlatMap<std::string_view, syncer::UserSelectableTypeSet>(
+          {{policy_data_types::kBrowsingHistoryName,
             {syncer::UserSelectableType::kHistory,
              syncer::UserSelectableType::kTabs,
              syncer::UserSelectableType::kSavedTabGroups}},
-           {browsing_data::policy_data_types::kPasswordSigninName,
+           {policy_data_types::kPasswordSigninName,
             {syncer::UserSelectableType::kPasswords}},
-           {browsing_data::policy_data_types::kSiteSettingsName,
+           {policy_data_types::kSiteSettingsName,
             {syncer::UserSelectableType::kPreferences}},
-           {browsing_data::policy_data_types::kAutofillName,
+           {policy_data_types::kAutofillName,
             {syncer::UserSelectableType::kAutofill,
              syncer::UserSelectableType::kPayments}},
-           {browsing_data::policy_data_types::kDownloadHistoryName, {}},
-           {browsing_data::policy_data_types::kCookiesAndOtherSiteDataName, {}},
-           {browsing_data::policy_data_types::kCachedImagesAndFilesName, {}},
-           {browsing_data::policy_data_types::kHostedAppDataName, {}}});
+           {policy_data_types::kDownloadHistoryName, {}},
+           {policy_data_types::kCookiesAndOtherSiteDataName, {}},
+           {policy_data_types::kCachedImagesAndFilesName, {}},
+           {policy_data_types::kHostedAppDataName, {}}});
 
   // When a new sync type or browsing data type is introduced in the code,
   // kDataToSyncTypesMap should be updated if needed to ensure that browsing
@@ -76,7 +76,7 @@
       "added or removed. Please update `kDataToSyncTypesMap` above to include "
       "the new type and the sync types it maps to if this data is synced.");
 
-  auto* it = kDataToSyncTypesMap.find(browsing_data_type.GetString());
+  const auto* it = kDataToSyncTypesMap.find(browsing_data_type.GetString());
   if (it == kDataToSyncTypesMap.end()) {
     return;
   }
@@ -114,24 +114,23 @@
   return sync_types;
 }
 
-void DisableSyncTypes(const syncer::UserSelectableTypeSet& types_set,
-                      PrefValueMap* prefs,
-                      const std::string& policy_name,
-                      std::string& log_message) {
+std::string DisableSyncTypes(const syncer::UserSelectableTypeSet& types_set,
+                             PrefValueMap* prefs,
+                             const std::string& policy_name) {
   for (const syncer::UserSelectableType type : types_set) {
     syncer::SyncPrefs::SetTypeDisabledByPolicy(prefs, type);
   }
-  log_message =
-      types_set.Size() > 0
-          ? base::StringPrintf(kDisabledSyncTypesLogFormat, policy_name.c_str(),
-                               UserSelectableTypeSetToString(types_set).c_str())
-          : std::string();
+  if (types_set.Size() > 0) {
+    return base::StringPrintf(kDisabledSyncTypesLogFormat, policy_name.c_str(),
+                              UserSelectableTypeSetToString(types_set).c_str());
+  }
+  return std::string();
 }
 
 absl::optional<PolicyDataType> NameToPolicyDataType(
     const std::string& type_name) {
-  static const auto kNameToDataType =
-      base::MakeFixedFlatMap<std::string, PolicyDataType>({
+  static constexpr auto kNameToDataType =
+      base::MakeFixedFlatMap<std::string_view, PolicyDataType>({
           {policy_data_types::kBrowsingHistoryName,
            PolicyDataType::kBrowsingHistory},
           {policy_data_types::kPasswordSigninName,
@@ -148,7 +147,7 @@
            PolicyDataType::kCachedImagesAndFiles},
       });
 
-  auto* it = kNameToDataType.find(type_name);
+  const auto* it = kNameToDataType.find(type_name);
   if (it == kNameToDataType.end()) {
     return absl::nullopt;
   }
diff --git a/components/browsing_data/core/browsing_data_policies_utils.h b/components/browsing_data/core/browsing_data_policies_utils.h
index 20c42339..f46ae58 100644
--- a/components/browsing_data/core/browsing_data_policies_utils.h
+++ b/components/browsing_data/core/browsing_data_policies_utils.h
@@ -35,12 +35,12 @@
 syncer::UserSelectableTypeSet GetSyncTypesForClearBrowsingData(
     const base::Value& policy_value);
 
-// Disables all the sync types in `types_set` by disabling their preferences and
-// adds a log for the chrome://policy/logs page.
-void DisableSyncTypes(const syncer::UserSelectableTypeSet& types_set,
-                      PrefValueMap* prefs,
-                      const std::string& policy_name,
-                      std::string& log_message);
+// Disables all the sync types in `types_set` by disabling their preferences.
+// Returns a message with the disabled sync types. The message is suitable for
+// logging to chrome://policy/logs.
+std::string DisableSyncTypes(const syncer::UserSelectableTypeSet& types_set,
+                             PrefValueMap* prefs,
+                             const std::string& policy_name);
 
 // Converts the browsing data type string to its integer value.
 // The conversion is used to ensure that the number of policy data types that
diff --git a/components/commerce/core/commerce_types.h b/components/commerce/core/commerce_types.h
index b82769bf..3ae16fb 100644
--- a/components/commerce/core/commerce_types.h
+++ b/components/commerce/core/commerce_types.h
@@ -138,6 +138,7 @@
 
   ParcelIdentifier::Carrier carrier;
   std::string tracking_id;
+  ParcelStatus::ParcelState state;
   GURL tracking_url;
   base::Time estimated_delivery_time;
 };
diff --git a/components/commerce/core/parcel/BUILD.gn b/components/commerce/core/parcel/BUILD.gn
index 0590870..faea29e 100644
--- a/components/commerce/core/parcel/BUILD.gn
+++ b/components/commerce/core/parcel/BUILD.gn
@@ -34,6 +34,7 @@
   testonly = true
 
   sources = [
+    "parcels_manager_unittest.cc",
     "parcels_server_proxy_unittest.cc",
     "parcels_storage_unittest.cc",
   ]
@@ -43,6 +44,7 @@
     ":parcel",
     "//base/test:test_support",
     "//components/commerce/core:commerce_constants",
+    "//components/commerce/core:commerce_types",
     "//components/commerce/core:parcel_tracking_db_content_proto",
     "//components/commerce/core:proto",
     "//components/endpoint_fetcher:test_support",
diff --git a/components/commerce/core/parcel/parcels_manager.cc b/components/commerce/core/parcel/parcels_manager.cc
index 61371b7..e79981e 100644
--- a/components/commerce/core/parcel/parcels_manager.cc
+++ b/components/commerce/core/parcel/parcels_manager.cc
@@ -13,18 +13,6 @@
 
 namespace {
 
-void OnGetParcelStatusDone(
-    GetParcelStatusCallback callback,
-    ParcelRequestStatus request_status,
-    std::unique_ptr<std::vector<ParcelStatus>> parcel_status) {
-  auto result = std::make_unique<std::vector<ParcelTrackingStatus>>();
-  for (auto& status : *parcel_status) {
-    result->emplace_back(status);
-  }
-  std::move(callback).Run(request_status == ParcelRequestStatus::kSuccess,
-                          std::move(result));
-}
-
 std::vector<ParcelIdentifier> ConvertParcelIdentifier(
     const std::vector<std::pair<ParcelIdentifier::Carrier, std::string>>&
         parcel_identifiers) {
@@ -37,15 +25,7 @@
   return result;
 }
 
-void OnStopTrackingParcelDone(StopParcelTrackingCallback callback,
-                              ParcelRequestStatus status) {
-  std::move(callback).Run(status == ParcelRequestStatus::kSuccess);
-}
-
-void OnStopTrackingAllParcelsDone(StopParcelTrackingCallback callback,
-                                  ParcelRequestStatus status) {
-  std::move(callback).Run(status == ParcelRequestStatus::kSuccess);
-}
+void DoNothing(bool success) {}
 }  // namespace
 
 ParcelsManager::ParcelsManager(
@@ -60,6 +40,12 @@
       parcels_storage_(
           std::make_unique<ParcelsStorage>(parcel_tracking_proto_db)) {}
 
+ParcelsManager::ParcelsManager(
+    std::unique_ptr<ParcelsServerProxy> parcels_server_proxy,
+    std::unique_ptr<ParcelsStorage> parcels_storage)
+    : parcels_server_proxy_(std::move(parcels_server_proxy)),
+      parcels_storage_(std::move(parcels_storage)) {}
+
 ParcelsManager::~ParcelsManager() = default;
 
 void ParcelsManager::StartTrackingParcels(
@@ -67,35 +53,184 @@
         parcel_identifiers,
     const std::string& source_page_domain,
     GetParcelStatusCallback callback) {
-  parcels_server_proxy_->StartTrackingParcels(
-      ConvertParcelIdentifier(parcel_identifiers), source_page_domain,
-      base::BindOnce(&OnGetParcelStatusDone, std::move(callback)));
+  pending_operations_.push(
+      base::BindOnce(&ParcelsManager::StartTrackingParcelsInternal,
+                     weak_ptr_factory_.GetWeakPtr(), parcel_identifiers,
+                     source_page_domain, std::move(callback)));
+  ProcessPendingOperations();
 }
 
 void ParcelsManager::GetAllParcelStatuses(GetParcelStatusCallback callback) {
+  pending_operations_.push(
+      base::BindOnce(&ParcelsManager::GetAllParcelStatusesInternal,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  ProcessPendingOperations();
+}
+
+void ParcelsManager::StopTrackingParcel(const std::string& tracking_id,
+                                        StopParcelTrackingCallback callback) {
+  pending_operations_.push(base::BindOnce(
+      &ParcelsManager::StopTrackingParcelInternal,
+      weak_ptr_factory_.GetWeakPtr(), tracking_id, std::move(callback)));
+  ProcessPendingOperations();
+}
+
+void ParcelsManager::StopTrackingAllParcels(
+    StopParcelTrackingCallback callback) {
+  pending_operations_.push(
+      base::BindOnce(&ParcelsManager::StopTrackingAllParcelsInternal,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  ProcessPendingOperations();
+}
+
+void ParcelsManager::ProcessPendingOperations() {
+  // Initialize parcel storage if it is not initialized,
+  if (storage_status_ == StorageInitializationStatus::kUninitialized) {
+    storage_status_ = StorageInitializationStatus::kInitializing;
+    is_processing_pending_operations_ = true;
+    parcels_storage_->Init(
+        base::BindOnce(&ParcelsManager::OnParcelStorageInitialized,
+                       weak_ptr_factory_.GetWeakPtr()));
+    return;
+  }
+
+  if (is_processing_pending_operations_ || pending_operations_.empty()) {
+    return;
+  }
+
+  is_processing_pending_operations_ = true;
+  base::OnceClosure callback = std::move(pending_operations_.front());
+  pending_operations_.pop();
+  std::move(callback).Run();
+}
+
+void ParcelsManager::OnParcelStorageInitialized(bool success) {
+  // TODO(qinmin): determine if we need to handle storage failure issue.
+  storage_status_ = success ? StorageInitializationStatus::kSuccess
+                            : StorageInitializationStatus::kFailed;
+  OnCurrentOperationFinished();
+}
+
+void ParcelsManager::StartTrackingParcelsInternal(
+    const std::vector<std::pair<ParcelIdentifier::Carrier, std::string>>&
+        parcel_identifiers,
+    const std::string& source_page_domain,
+    GetParcelStatusCallback callback) {
+  parcels_server_proxy_->StartTrackingParcels(
+      ConvertParcelIdentifier(parcel_identifiers), source_page_domain,
+      base::BindOnce(&ParcelsManager::OnGetParcelStatusDone,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     std::make_unique<std::vector<ParcelStatus>>(),
+                     false /*has_stored_status*/, std::move(callback)));
+}
+
+void ParcelsManager::GetAllParcelStatusesInternal(
+    GetParcelStatusCallback callback) {
   auto parcel_status = parcels_storage_->GetAllParcelStatus();
+  if (parcel_status->empty()) {
+    std::move(callback).Run(
+        storage_status_ == StorageInitializationStatus::kSuccess,
+        std::make_unique<std::vector<ParcelTrackingStatus>>());
+    return;
+  }
+  // TODO(qinmin): Check whether the data is fresh and we need to call the
+  // server.
   std::vector<ParcelIdentifier> identifiers;
   for (auto& status : *parcel_status) {
     identifiers.emplace_back(status.parcel_identifier());
   }
   parcels_server_proxy_->GetParcelStatus(
       std::move(identifiers),
-      base::BindOnce(&OnGetParcelStatusDone, std::move(callback)));
+      base::BindOnce(&ParcelsManager::OnGetParcelStatusDone,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(parcel_status),
+                     storage_status_ == StorageInitializationStatus::kSuccess,
+                     std::move(callback)));
 }
 
-void ParcelsManager::StopTrackingParcel(const std::string& tracking_id,
-                                        StopParcelTrackingCallback callback) {
+void ParcelsManager::StopTrackingParcelInternal(
+    const std::string& tracking_id,
+    StopParcelTrackingCallback callback) {
   parcels_server_proxy_->StopTrackingParcel(
-      tracking_id,
-      base::BindOnce(&OnStopTrackingParcelDone, std::move(callback)));
+      tracking_id, base::BindOnce(&ParcelsManager::OnStopTrackingParcelDone,
+                                  weak_ptr_factory_.GetWeakPtr(), tracking_id,
+                                  std::move(callback)));
 }
 
-void ParcelsManager::StopTrackingAllParcels(
+void ParcelsManager::StopTrackingAllParcelsInternal(
     StopParcelTrackingCallback callback) {
   parcels_server_proxy_->StopTrackingAllParcels(
-      base::BindOnce(&OnStopTrackingAllParcelsDone, std::move(callback)));
+      base::BindOnce(&ParcelsManager::OnStopTrackingAllParcelsDone,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-// Called to stop tracking a given parcel.
+void ParcelsManager::OnGetParcelStatusDone(
+    std::unique_ptr<std::vector<ParcelStatus>> stored_parcel_status,
+    bool has_stored_status,
+    GetParcelStatusCallback callback,
+    bool success,
+    std::unique_ptr<std::vector<ParcelStatus>> new_parcel_status) {
+  DCHECK(is_processing_pending_operations_);
+
+  // If network request fails, fallback to stored parcel status.
+  std::vector<ParcelStatus>* status_to_return;
+  if (success) {
+    status_to_return = new_parcel_status.get();
+  } else {
+    status_to_return = stored_parcel_status.get();
+  }
+
+  auto result = std::make_unique<std::vector<ParcelTrackingStatus>>();
+  for (auto& status : *status_to_return) {
+    result->emplace_back(status);
+  }
+
+  // Update the database.
+  if (success) {
+    auto& status_to_update = *new_parcel_status;
+    // TODO(qinmin): Check if we need to handle storage update failure.
+    parcels_storage_->UpdateParcelStatus(status_to_update,
+                                         base::BindOnce(&DoNothing));
+  }
+
+  // If there are stored status, treat the call as successful.
+  std::move(callback).Run(success | has_stored_status, std::move(result));
+  OnCurrentOperationFinished();
+}
+
+void ParcelsManager::OnStopTrackingParcelDone(
+    const std::string& tracking_id,
+    StopParcelTrackingCallback callback,
+    bool success) {
+  DCHECK(is_processing_pending_operations_);
+
+  // Update the database if network request succeeds.
+  if (success) {
+    parcels_storage_->DeleteParcelStatus(tracking_id,
+                                         base::BindOnce(&DoNothing));
+  }
+
+  std::move(callback).Run(success);
+  OnCurrentOperationFinished();
+}
+
+void ParcelsManager::OnStopTrackingAllParcelsDone(
+    StopParcelTrackingCallback callback,
+    bool success) {
+  DCHECK(is_processing_pending_operations_);
+
+  // Update the database if network request succeeds.
+  if (success) {
+    parcels_storage_->DeleteAllParcelStatus(base::BindOnce(&DoNothing));
+  }
+
+  std::move(callback).Run(success);
+  OnCurrentOperationFinished();
+}
+
+void ParcelsManager::OnCurrentOperationFinished() {
+  DCHECK(is_processing_pending_operations_);
+  is_processing_pending_operations_ = false;
+  ProcessPendingOperations();
+}
 
 }  // namespace commerce
diff --git a/components/commerce/core/parcel/parcels_manager.h b/components/commerce/core/parcel/parcels_manager.h
index cfde650..64b5c55 100644
--- a/components/commerce/core/parcel/parcels_manager.h
+++ b/components/commerce/core/parcel/parcels_manager.h
@@ -6,9 +6,11 @@
 #define COMPONENTS_COMMERCE_CORE_PARCEL_PARCELS_MANAGER_H_
 
 #include <memory>
+#include <queue>
 #include <utility>
 
 #include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
 #include "components/commerce/core/commerce_types.h"
 #include "components/commerce/core/proto/parcel.pb.h"
 #include "components/commerce/core/proto/parcel_tracking_db_content.pb.h"
@@ -36,6 +38,9 @@
       SessionProtoStorage<parcel_tracking_db::ParcelTrackingContent>*
           parcel_tracking_proto_db,
       AccountChecker* account_checker);
+  // Ctor used for testing purposes.
+  ParcelsManager(std::unique_ptr<ParcelsServerProxy> parcels_server_proxy,
+                 std::unique_ptr<ParcelsStorage> parcels_storage);
   ~ParcelsManager();
   ParcelsManager(const ParcelsManager&) = delete;
   ParcelsManager& operator=(const ParcelsManager&) = delete;
@@ -58,9 +63,69 @@
   void StopTrackingAllParcels(StopParcelTrackingCallback callback);
 
  private:
+  enum class StorageInitializationStatus {
+    // Storage is not yet initialized.
+    kUninitialized = 0,
+    // Storage is initializing.
+    kInitializing = 1,
+    // Storage is initialized successfully.
+    kSuccess = 2,
+    // Storage failed to initialize.
+    kFailed = 3,
+  };
+
+  // Called to process all pending operations.
+  void ProcessPendingOperations();
+
+  // Called after parcel storage finished initialization.
+  void OnParcelStorageInitialized(bool success);
+
+  // Helper methods that implement the public methods.
+  void StartTrackingParcelsInternal(
+      const std::vector<std::pair<ParcelIdentifier::Carrier, std::string>>&
+          parcel_identifiers,
+      const std::string& source_page_domain,
+      GetParcelStatusCallback callback);
+  void GetAllParcelStatusesInternal(GetParcelStatusCallback callback);
+  void StopTrackingParcelInternal(const std::string& tracking_id,
+                                  StopParcelTrackingCallback callback);
+  void StopTrackingAllParcelsInternal(StopParcelTrackingCallback callback);
+
+  // Called when parcel status is retrieved from the network. If
+  // `has_stored_status` is true, the local stored parcel status could be
+  // returned to the caller.
+  void OnGetParcelStatusDone(
+      std::unique_ptr<std::vector<ParcelStatus>> stored_parcel_status,
+      bool has_stored_status,
+      GetParcelStatusCallback callback,
+      bool success,
+      std::unique_ptr<std::vector<ParcelStatus>> new_parcel_status);
+
+  // Called when stop tracking is completed.
+  void OnStopTrackingParcelDone(const std::string& tracking_id,
+                                StopParcelTrackingCallback callback,
+                                bool success);
+
+  // Called when stop all parcel tracking is completed.
+  void OnStopTrackingAllParcelsDone(StopParcelTrackingCallback callback,
+                                    bool success);
+
+  // Called when one pending operation finishes.
+  void OnCurrentOperationFinished();
+
+  // Parcel storage initialization status.
+  StorageInitializationStatus storage_status_ =
+      StorageInitializationStatus::kUninitialized;
+
+  bool is_processing_pending_operations_ = false;
+
+  std::queue<base::OnceClosure> pending_operations_;
+
   std::unique_ptr<ParcelsServerProxy> parcels_server_proxy_;
 
   std::unique_ptr<ParcelsStorage> parcels_storage_;
+
+  base::WeakPtrFactory<ParcelsManager> weak_ptr_factory_{this};
 };
 
 }  // namespace commerce
diff --git a/components/commerce/core/parcel/parcels_manager_unittest.cc b/components/commerce/core/parcel/parcels_manager_unittest.cc
new file mode 100644
index 0000000..3d652ee
--- /dev/null
+++ b/components/commerce/core/parcel/parcels_manager_unittest.cc
@@ -0,0 +1,390 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <utility>
+
+#include "base/functional/callback.h"
+#include "base/memory/raw_ptr.h"
+#include "base/run_loop.h"
+#include "base/test/gtest_util.h"
+#include "base/test/task_environment.h"
+#include "components/commerce/core/commerce_types.h"
+#include "components/commerce/core/parcel/parcels_manager.h"
+#include "components/commerce/core/parcel/parcels_server_proxy.h"
+#include "components/commerce/core/parcel/parcels_storage.h"
+#include "components/commerce/core/proto/parcel.pb.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::ByMove;
+using testing::InSequence;
+using testing::Return;
+
+namespace commerce {
+namespace {
+
+const std::string kTestTrackingId = "xyz";
+const std::string kSoucePageDomain = "www.foo.com";
+
+std::unique_ptr<std::vector<commerce::ParcelStatus>> BuildParcelStatus(
+    const std::string& tracking_id,
+    commerce::ParcelStatus::ParcelState state) {
+  commerce::ParcelIdentifier identifier;
+  identifier.set_tracking_id(tracking_id);
+  identifier.set_carrier(commerce::ParcelIdentifier::UPS);
+  commerce::ParcelStatus parcel_status;
+  parcel_status.set_parcel_state(state);
+  *parcel_status.mutable_parcel_identifier() = identifier;
+  auto result = std::make_unique<std::vector<commerce::ParcelStatus>>();
+  result->emplace_back(parcel_status);
+  return result;
+}
+
+std::vector<std::pair<commerce::ParcelIdentifier::Carrier, std::string>>
+GetTestIdentifiers(const std::string& tracking_id) {
+  std::vector<std::pair<commerce::ParcelIdentifier::Carrier, std::string>>
+      result;
+  result.emplace_back(commerce::ParcelIdentifier::UPS, tracking_id);
+  return result;
+}
+
+class MockServerProxy : public ParcelsServerProxy {
+ public:
+  MockServerProxy()
+      : ParcelsServerProxy(
+            nullptr,
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)) {}
+  MockServerProxy(const MockServerProxy&) = delete;
+  MockServerProxy operator=(const MockServerProxy&) = delete;
+  ~MockServerProxy() override = default;
+
+  MOCK_METHOD(void,
+              GetParcelStatus,
+              (const std::vector<ParcelIdentifier>& parcel_identifiers,
+               ParcelsServerProxy::GetParcelStatusCallback callback),
+              (override));
+  MOCK_METHOD(void,
+              StartTrackingParcels,
+              (const std::vector<ParcelIdentifier>& parcel_identifiers,
+               const std::string& source_page_domain,
+               ParcelsServerProxy::GetParcelStatusCallback callback),
+              (override));
+  MOCK_METHOD(void,
+              StopTrackingParcel,
+              (const std::string& tracking_id,
+               ParcelsServerProxy::StopParcelTrackingCallback callback),
+              (override));
+  MOCK_METHOD(void,
+              StopTrackingAllParcels,
+              (ParcelsServerProxy::StopParcelTrackingCallback callback),
+              (override));
+
+  // Mocks the GetParcelStatus and StartTrackingParcels response from server.
+  void MockParcelStatusResponses(bool succeeded,
+                                 const std::string& tracking_id,
+                                 ParcelStatus::ParcelState state) {
+    ON_CALL(*this, GetParcelStatus)
+        .WillByDefault(
+            [succeeded, tracking_id, state](
+                const std::vector<ParcelIdentifier>& parcel_identifiers,
+                ParcelsServerProxy::GetParcelStatusCallback callback) {
+              std::move(callback).Run(succeeded,
+                                      BuildParcelStatus(tracking_id, state));
+            });
+    ON_CALL(*this, StartTrackingParcels)
+        .WillByDefault(
+            [succeeded, tracking_id, state](
+                const std::vector<ParcelIdentifier>& parcel_identifiers,
+                const std::string& source_page_domain,
+                ParcelsServerProxy::GetParcelStatusCallback callback) {
+              std::move(callback).Run(succeeded,
+                                      BuildParcelStatus(tracking_id, state));
+            });
+  }
+
+  // Mock the server response for stop tracking requests.
+  void MockStopTrackingResponses(bool succeeded) {
+    ON_CALL(*this, StopTrackingParcel)
+        .WillByDefault([succeeded](const std::string& tracking_id,
+                                   StopParcelTrackingCallback callback) {
+          std::move(callback).Run(succeeded);
+        });
+    ON_CALL(*this, StopTrackingAllParcels)
+        .WillByDefault([succeeded](StopParcelTrackingCallback callback) {
+          std::move(callback).Run(succeeded);
+        });
+  }
+
+ private:
+  network::TestURLLoaderFactory test_url_loader_factory_;
+};
+
+class MockParcelsStorage : public ParcelsStorage {
+ public:
+  MockParcelsStorage() : ParcelsStorage(nullptr) {}
+  MockParcelsStorage(const MockParcelsStorage&) = delete;
+  MockParcelsStorage operator=(const MockParcelsStorage&) = delete;
+  ~MockParcelsStorage() override = default;
+
+  MOCK_METHOD(void, Init, (OnInitializedCallback callback), (override));
+  MOCK_METHOD(std::unique_ptr<std::vector<ParcelStatus>>,
+              GetAllParcelStatus,
+              (),
+              (override));
+  MOCK_METHOD(void,
+              UpdateParcelStatus,
+              (const std::vector<ParcelStatus>& parcel_status,
+               StorageUpdateCallback callback),
+              (override));
+  MOCK_METHOD(void,
+              DeleteParcelStatus,
+              (const std::string& tracking_id, StorageUpdateCallback callback),
+              (override));
+  MOCK_METHOD(void,
+              DeleteAllParcelStatus,
+              (StorageUpdateCallback callback),
+              (override));
+
+  void MockInitCallback(bool succeeded) {
+    ON_CALL(*this, Init)
+        .WillByDefault(
+            [succeeded](ParcelsStorage::OnInitializedCallback callback) {
+              std::move(callback).Run(succeeded);
+            });
+  }
+
+  void MockGetAllParcelStatus(const std::string& tracking_id,
+                              ParcelStatus::ParcelState state) {
+    ON_CALL(*this, GetAllParcelStatus).WillByDefault([tracking_id, state]() {
+      return BuildParcelStatus(tracking_id, state);
+    });
+  }
+};
+
+class ParcelsManagerTest : public testing::Test {
+ public:
+  ParcelsManagerTest() = default;
+  ~ParcelsManagerTest() override = default;
+
+  void SetUp() override {
+    auto mock_server_proxy = std::make_unique<MockServerProxy>();
+    auto mock_storage = std::make_unique<MockParcelsStorage>();
+    mock_server_proxy_ = mock_server_proxy.get();
+    mock_storage_ = mock_storage.get();
+
+    parcels_manager_ = std::make_unique<ParcelsManager>(
+        std::move(mock_server_proxy), std::move(mock_storage));
+
+    ON_CALL(*mock_storage_, UpdateParcelStatus)
+        .WillByDefault([](const std::vector<ParcelStatus>& parcel_status,
+                          ParcelsStorage::StorageUpdateCallback callback) {
+          std::move(callback).Run(true);
+        });
+  }
+
+  void TearDown() override {
+    mock_server_proxy_ = nullptr;
+    mock_storage_ = nullptr;
+  }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  raw_ptr<MockServerProxy> mock_server_proxy_;
+  raw_ptr<MockParcelsStorage> mock_storage_;
+  std::unique_ptr<ParcelsManager> parcels_manager_;
+};
+
+TEST_F(ParcelsManagerTest, TestStartTrackingParcels) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  mock_server_proxy_->MockParcelStatusResponses(true, kTestTrackingId,
+                                                ParcelStatus::NEW);
+  mock_storage_->MockInitCallback(true);
+
+  EXPECT_CALL(*mock_server_proxy_, StartTrackingParcels(_, _, _)).Times(1);
+  EXPECT_CALL(*mock_storage_, UpdateParcelStatus(_, _)).Times(1);
+  base::RunLoop run_loop;
+  parcels_manager_->StartTrackingParcels(
+      GetTestIdentifiers(kTestTrackingId), kSoucePageDomain,
+      base::BindOnce(
+          [](base::RunLoop* run_loop, bool success,
+             std::unique_ptr<std::vector<ParcelTrackingStatus>> parcel_status) {
+            ASSERT_TRUE(success);
+            ASSERT_EQ(1, static_cast<int>(parcel_status->size()));
+            auto status = (*parcel_status)[0];
+            ASSERT_EQ(kTestTrackingId, status.tracking_id);
+            ASSERT_EQ(commerce::ParcelIdentifier::UPS, status.carrier);
+            ASSERT_EQ(ParcelStatus::NEW, status.state);
+            run_loop->Quit();
+          },
+          &run_loop));
+  run_loop.Run();
+}
+
+TEST_F(ParcelsManagerTest, TestStartTrackingParcels_ServerError) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  mock_server_proxy_->MockParcelStatusResponses(false, kTestTrackingId,
+                                                ParcelStatus::NEW);
+  mock_storage_->MockInitCallback(true);
+
+  EXPECT_CALL(*mock_server_proxy_, StartTrackingParcels(_, _, _)).Times(1);
+  EXPECT_CALL(*mock_storage_, UpdateParcelStatus(_, _)).Times(0);
+  base::RunLoop run_loop;
+  parcels_manager_->StartTrackingParcels(
+      GetTestIdentifiers(kTestTrackingId), kSoucePageDomain,
+      base::BindOnce(
+          [](base::RunLoop* run_loop, bool success,
+             std::unique_ptr<std::vector<ParcelTrackingStatus>> parcel_status) {
+            ASSERT_FALSE(success);
+            run_loop->Quit();
+          },
+          &run_loop));
+  run_loop.Run();
+}
+
+TEST_F(ParcelsManagerTest, TestGetAllParcelStatuses_ServerHasFreshStatus) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  mock_storage_->MockGetAllParcelStatus(kTestTrackingId, ParcelStatus::NEW);
+  mock_server_proxy_->MockParcelStatusResponses(true, kTestTrackingId,
+                                                ParcelStatus::PICKED_UP);
+  mock_storage_->MockInitCallback(true);
+
+  EXPECT_CALL(*mock_server_proxy_, GetParcelStatus(_, _)).Times(1);
+  EXPECT_CALL(*mock_storage_, GetAllParcelStatus()).Times(1);
+  EXPECT_CALL(*mock_storage_, UpdateParcelStatus(_, _)).Times(1);
+  base::RunLoop run_loop;
+  parcels_manager_->GetAllParcelStatuses(base::BindOnce(
+      [](base::RunLoop* run_loop, bool success,
+         std::unique_ptr<std::vector<ParcelTrackingStatus>> parcel_status) {
+        ASSERT_TRUE(success);
+        ASSERT_EQ(1, static_cast<int>(parcel_status->size()));
+        auto status = (*parcel_status)[0];
+        ASSERT_EQ(kTestTrackingId, status.tracking_id);
+        ASSERT_EQ(commerce::ParcelIdentifier::UPS, status.carrier);
+        ASSERT_EQ(ParcelStatus::PICKED_UP, status.state);
+        run_loop->Quit();
+      },
+      &run_loop));
+  run_loop.Run();
+}
+
+TEST_F(ParcelsManagerTest, TestGetAllParcelStatuses_ServerError) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  mock_storage_->MockGetAllParcelStatus(kTestTrackingId, ParcelStatus::NEW);
+  mock_server_proxy_->MockParcelStatusResponses(false, kTestTrackingId,
+                                                ParcelStatus::PICKED_UP);
+  mock_storage_->MockInitCallback(true);
+
+  EXPECT_CALL(*mock_server_proxy_, GetParcelStatus(_, _)).Times(1);
+  EXPECT_CALL(*mock_storage_, GetAllParcelStatus()).Times(1);
+  EXPECT_CALL(*mock_storage_, UpdateParcelStatus(_, _)).Times(0);
+  base::RunLoop run_loop;
+  parcels_manager_->GetAllParcelStatuses(base::BindOnce(
+      [](base::RunLoop* run_loop, bool success,
+         std::unique_ptr<std::vector<ParcelTrackingStatus>> parcel_status) {
+        ASSERT_TRUE(success);
+        ASSERT_EQ(1, static_cast<int>(parcel_status->size()));
+        auto status = (*parcel_status)[0];
+        ASSERT_EQ(kTestTrackingId, status.tracking_id);
+        ASSERT_EQ(commerce::ParcelIdentifier::UPS, status.carrier);
+        ASSERT_EQ(ParcelStatus::NEW, status.state);
+        run_loop->Quit();
+      },
+      &run_loop));
+  run_loop.Run();
+}
+
+TEST_F(ParcelsManagerTest, TestGetAllParcelStatuses_StorageError) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  EXPECT_CALL(*mock_storage_, GetAllParcelStatus)
+      .WillOnce(Return(ByMove(std::make_unique<std::vector<ParcelStatus>>())));
+  mock_storage_->MockInitCallback(false);
+
+  base::RunLoop run_loop;
+  parcels_manager_->GetAllParcelStatuses(base::BindOnce(
+      [](base::RunLoop* run_loop, bool success,
+         std::unique_ptr<std::vector<ParcelTrackingStatus>> parcel_status) {
+        ASSERT_FALSE(success);
+        ASSERT_EQ(0, static_cast<int>(parcel_status->size()));
+        run_loop->Quit();
+      },
+      &run_loop));
+  run_loop.Run();
+}
+
+TEST_F(ParcelsManagerTest, TestStopTrackingAllParcels) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  mock_storage_->MockInitCallback(true);
+  mock_server_proxy_->MockStopTrackingResponses(true);
+
+  EXPECT_CALL(*mock_server_proxy_, StopTrackingAllParcels(_)).Times(1);
+  EXPECT_CALL(*mock_storage_, DeleteAllParcelStatus(_)).Times(1);
+  base::RunLoop run_loop;
+  parcels_manager_->StopTrackingAllParcels(base::BindOnce(
+      [](base::RunLoop* run_loop, bool success) {
+        ASSERT_TRUE(success);
+        run_loop->Quit();
+      },
+      &run_loop));
+  run_loop.Run();
+}
+
+TEST_F(ParcelsManagerTest, TestStopTrackingAllParcels_ServerError) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  mock_storage_->MockInitCallback(true);
+  mock_server_proxy_->MockStopTrackingResponses(false);
+
+  EXPECT_CALL(*mock_server_proxy_, StopTrackingAllParcels(_)).Times(1);
+  EXPECT_CALL(*mock_storage_, DeleteAllParcelStatus(_)).Times(0);
+  base::RunLoop run_loop;
+  parcels_manager_->StopTrackingAllParcels(base::BindOnce(
+      [](base::RunLoop* run_loop, bool success) {
+        ASSERT_FALSE(success);
+        run_loop->Quit();
+      },
+      &run_loop));
+  run_loop.Run();
+}
+
+TEST_F(ParcelsManagerTest, TestStopTrackingParcel) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  mock_storage_->MockInitCallback(true);
+  mock_server_proxy_->MockStopTrackingResponses(true);
+
+  EXPECT_CALL(*mock_server_proxy_, StopTrackingParcel(_, _)).Times(1);
+  EXPECT_CALL(*mock_storage_, DeleteParcelStatus(_, _)).Times(1);
+  base::RunLoop run_loop;
+  parcels_manager_->StopTrackingParcel(
+      kTestTrackingId, base::BindOnce(
+                           [](base::RunLoop* run_loop, bool success) {
+                             ASSERT_TRUE(success);
+                             run_loop->Quit();
+                           },
+                           &run_loop));
+  run_loop.Run();
+}
+
+TEST_F(ParcelsManagerTest, TestStopTrackingParcel_ServerError) {
+  EXPECT_CALL(*mock_storage_, Init(_)).Times(1);
+  mock_storage_->MockInitCallback(true);
+  mock_server_proxy_->MockStopTrackingResponses(false);
+
+  EXPECT_CALL(*mock_server_proxy_, StopTrackingParcel(_, _)).Times(1);
+  EXPECT_CALL(*mock_storage_, DeleteParcelStatus(_, _)).Times(0);
+  base::RunLoop run_loop;
+  parcels_manager_->StopTrackingParcel(
+      kTestTrackingId, base::BindOnce(
+                           [](base::RunLoop* run_loop, bool success) {
+                             ASSERT_FALSE(success);
+                             run_loop->Quit();
+                           },
+                           &run_loop));
+  run_loop.Run();
+}
+}  // namespace
+}  // namespace commerce
diff --git a/components/commerce/core/parcel/parcels_server_proxy.cc b/components/commerce/core/parcel/parcels_server_proxy.cc
index 0bd59c0e..0d94311b 100644
--- a/components/commerce/core/parcel/parcels_server_proxy.cc
+++ b/components/commerce/core/parcel/parcels_server_proxy.cc
@@ -266,8 +266,7 @@
 void OnInvalidParcelIdentifierError(
     ParcelsServerProxy::GetParcelStatusCallback callback) {
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback),
-                                ParcelRequestStatus::kInvalidParcelIdentifiers,
+      FROM_HERE, base::BindOnce(std::move(callback), false,
                                 std::make_unique<std::vector<ParcelStatus>>()));
 }
 
@@ -285,12 +284,12 @@
     const std::vector<ParcelIdentifier>& parcel_identifiers,
     GetParcelStatusCallback callback) {
   CHECK_GT(parcel_identifiers.size(), 0u);
-
   base::Value::List parcel_list = Serialize(parcel_identifiers);
   if (parcel_list.empty()) {
     OnInvalidParcelIdentifierError(std::move(callback));
     return;
   }
+
   base::Value::Dict request_json;
   request_json.Set(kParcelIdsKey, std::move(parcel_list));
   SendJsonRequestToServer(
@@ -351,7 +350,7 @@
     GetParcelStatusCallback callback,
     std::unique_ptr<EndpointResponse> response) {
   if (response->http_status_code != net::HTTP_OK || response->error_type) {
-    std::move(callback).Run(ParcelRequestStatus::kServerError,
+    std::move(callback).Run(false,
                             std::make_unique<std::vector<ParcelStatus>>());
     return;
   }
@@ -373,13 +372,11 @@
           parcel_status->push_back(*status);
         }
       }
-      std::move(callback).Run(ParcelRequestStatus::kSuccess,
-                              std::move(parcel_status));
+      std::move(callback).Run(true, std::move(parcel_status));
       return;
     }
   }
-  std::move(callback).Run(ParcelRequestStatus::kServerReponseParsingError,
-                          std::make_unique<std::vector<ParcelStatus>>());
+  std::move(callback).Run(false, std::make_unique<std::vector<ParcelStatus>>());
 }
 
 void ParcelsServerProxy::OnStopTrackingResponse(
@@ -387,9 +384,9 @@
     std::unique_ptr<EndpointFetcher> endpoint_fetcher,
     std::unique_ptr<EndpointResponse> response) {
   if (response->http_status_code != net::HTTP_OK || response->error_type) {
-    std::move(callback).Run(ParcelRequestStatus::kServerError);
+    std::move(callback).Run(false);
   } else {
-    std::move(callback).Run(ParcelRequestStatus::kSuccess);
+    std::move(callback).Run(true);
   }
 }
 
@@ -409,7 +406,6 @@
   base::JSONWriter::Write(request_json, &post_data);
   auto fetcher = CreateEndpointFetcher(GURL(server_url), kPostHttpMethod,
                                        post_data, network_traffic_annotation);
-
   auto* const fetcher_ptr = fetcher.get();
   fetcher_ptr->Fetch(base::BindOnce(&ParcelsServerProxy::OnServerResponse,
                                     weak_ptr_factory_.GetWeakPtr(),
diff --git a/components/commerce/core/parcel/parcels_server_proxy.h b/components/commerce/core/parcel/parcels_server_proxy.h
index c07ed3f..f1343f6 100644
--- a/components/commerce/core/parcel/parcels_server_proxy.h
+++ b/components/commerce/core/parcel/parcels_server_proxy.h
@@ -49,10 +49,9 @@
 class ParcelsServerProxy {
  public:
   using GetParcelStatusCallback =
-      base::OnceCallback<void(ParcelRequestStatus,
+      base::OnceCallback<void(bool /*success*/,
                               std::unique_ptr<std::vector<ParcelStatus>>)>;
-  using StopParcelTrackingCallback =
-      base::OnceCallback<void(ParcelRequestStatus)>;
+  using StopParcelTrackingCallback = base::OnceCallback<void(bool /*success*/)>;
 
   ParcelsServerProxy(
       signin::IdentityManager* identity_manager,
@@ -62,21 +61,22 @@
   ParcelsServerProxy& operator=(const ParcelsServerProxy& other) = delete;
 
   // Get parcel status.
-  void GetParcelStatus(const std::vector<ParcelIdentifier>& parcel_identifiers,
-                       GetParcelStatusCallback callback);
+  virtual void GetParcelStatus(
+      const std::vector<ParcelIdentifier>& parcel_identifiers,
+      GetParcelStatusCallback callback);
 
   // Start tracking parcel status.
-  void StartTrackingParcels(
+  virtual void StartTrackingParcels(
       const std::vector<ParcelIdentifier>& parcel_identifiers,
       const std::string& source_page_domain,
       GetParcelStatusCallback callback);
 
   // Called to stop tracking a given parcel.
-  void StopTrackingParcel(const std::string& tracking_id,
-                          StopParcelTrackingCallback callback);
+  virtual void StopTrackingParcel(const std::string& tracking_id,
+                                  StopParcelTrackingCallback callback);
 
   // Called to stop tracking all parcels.
-  void StopTrackingAllParcels(StopParcelTrackingCallback callback);
+  virtual void StopTrackingAllParcels(StopParcelTrackingCallback callback);
 
  protected:
   // This method could be overridden in tests.
diff --git a/components/commerce/core/parcel/parcels_server_proxy_unittest.cc b/components/commerce/core/parcel/parcels_server_proxy_unittest.cc
index a4587ef8..f69adb6 100644
--- a/components/commerce/core/parcel/parcels_server_proxy_unittest.cc
+++ b/components/commerce/core/parcel/parcels_server_proxy_unittest.cc
@@ -110,14 +110,13 @@
               CreateEndpointFetcher(GURL(kParcelsStatusUrl), kPostHttpMethod,
                                     kExpectedGetParcelStatusPostData, _))
       .Times(1);
-
   base::RunLoop run_loop;
   server_proxy_->GetParcelStatus(
       GetTestParcelIdentifiers(),
       base::BindOnce(
-          [](base::RunLoop* run_loop, ParcelRequestStatus request_status,
+          [](base::RunLoop* run_loop, bool success,
              std::unique_ptr<std::vector<ParcelStatus>> parcel_status) {
-            ASSERT_EQ(ParcelRequestStatus::kSuccess, request_status);
+            ASSERT_TRUE(success);
             ASSERT_EQ(1, static_cast<int>(parcel_status->size()));
             auto status = (*parcel_status)[0];
             ASSERT_EQ(ParcelStatus::PICKED_UP, status.parcel_state());
@@ -143,10 +142,9 @@
   server_proxy_->GetParcelStatus(
       GetTestParcelIdentifiers(),
       base::BindOnce(
-          [](base::RunLoop* run_loop, ParcelRequestStatus request_status,
+          [](base::RunLoop* run_loop, bool success,
              std::unique_ptr<std::vector<ParcelStatus>> parcel_status) {
-            ASSERT_EQ(ParcelRequestStatus::kServerReponseParsingError,
-                      request_status);
+            ASSERT_FALSE(success);
             ASSERT_EQ(0, static_cast<int>(parcel_status->size()));
             run_loop->Quit();
           },
@@ -159,10 +157,9 @@
   server_proxy_->GetParcelStatus(
       std::vector<ParcelIdentifier>{ParcelIdentifier()},
       base::BindOnce(
-          [](base::RunLoop* run_loop, ParcelRequestStatus request_status,
+          [](base::RunLoop* run_loop, bool success,
              std::unique_ptr<std::vector<ParcelStatus>> parcel_status) {
-            ASSERT_EQ(ParcelRequestStatus::kInvalidParcelIdentifiers,
-                      request_status);
+            ASSERT_FALSE(success);
             ASSERT_EQ(0, static_cast<int>(parcel_status->size()));
             run_loop->Quit();
           },
@@ -180,9 +177,9 @@
   server_proxy_->GetParcelStatus(
       GetTestParcelIdentifiers(),
       base::BindOnce(
-          [](base::RunLoop* run_loop, ParcelRequestStatus request_status,
+          [](base::RunLoop* run_loop, bool success,
              std::unique_ptr<std::vector<ParcelStatus>> parcel_status) {
-            ASSERT_EQ(ParcelRequestStatus::kServerError, request_status);
+            ASSERT_FALSE(success);
             ASSERT_EQ(0, static_cast<int>(parcel_status->size()));
             run_loop->Quit();
           },
@@ -200,9 +197,9 @@
   server_proxy_->StartTrackingParcels(
       GetTestParcelIdentifiers(), kTestSourcePageDomain,
       base::BindOnce(
-          [](base::RunLoop* run_loop, ParcelRequestStatus request_status,
+          [](base::RunLoop* run_loop, bool success,
              std::unique_ptr<std::vector<ParcelStatus>> parcel_status) {
-            ASSERT_EQ(ParcelRequestStatus::kServerError, request_status);
+            ASSERT_FALSE(success);
             ASSERT_EQ(0, static_cast<int>(parcel_status->size()));
             run_loop->Quit();
           },
@@ -220,9 +217,9 @@
   server_proxy_->StartTrackingParcels(
       GetTestParcelIdentifiers(), kTestSourcePageDomain,
       base::BindOnce(
-          [](base::RunLoop* run_loop, ParcelRequestStatus request_status,
+          [](base::RunLoop* run_loop, bool success,
              std::unique_ptr<std::vector<ParcelStatus>> parcel_status) {
-            ASSERT_EQ(ParcelRequestStatus::kSuccess, request_status);
+            ASSERT_TRUE(success);
             ASSERT_EQ(1, static_cast<int>(parcel_status->size()));
             auto status = (*parcel_status)[0];
             ASSERT_EQ(ParcelStatus::PICKED_UP, status.parcel_state());
@@ -247,13 +244,12 @@
       .Times(1);
   base::RunLoop run_loop;
   server_proxy_->StopTrackingParcel(
-      kTestTrackingId,
-      base::BindOnce(
-          [](base::RunLoop* run_loop, ParcelRequestStatus request_status) {
-            ASSERT_EQ(ParcelRequestStatus::kSuccess, request_status);
-            run_loop->Quit();
-          },
-          &run_loop));
+      kTestTrackingId, base::BindOnce(
+                           [](base::RunLoop* run_loop, bool success) {
+                             ASSERT_TRUE(success);
+                             run_loop->Quit();
+                           },
+                           &run_loop));
   run_loop.Run();
 }
 
@@ -265,8 +261,8 @@
       .Times(1);
   base::RunLoop run_loop;
   server_proxy_->StopTrackingAllParcels(base::BindOnce(
-      [](base::RunLoop* run_loop, ParcelRequestStatus request_status) {
-        ASSERT_EQ(ParcelRequestStatus::kSuccess, request_status);
+      [](base::RunLoop* run_loop, bool success) {
+        ASSERT_TRUE(success);
         run_loop->Quit();
       },
       &run_loop));
@@ -281,8 +277,8 @@
       .Times(1);
   base::RunLoop run_loop;
   server_proxy_->StopTrackingAllParcels(base::BindOnce(
-      [](base::RunLoop* run_loop, ParcelRequestStatus request_status) {
-        ASSERT_EQ(ParcelRequestStatus::kServerError, request_status);
+      [](base::RunLoop* run_loop, bool success) {
+        ASSERT_FALSE(success);
         run_loop->Quit();
       },
       &run_loop));
diff --git a/components/commerce/core/parcel/parcels_storage.cc b/components/commerce/core/parcel/parcels_storage.cc
index 5ad98c9..aaece46 100644
--- a/components/commerce/core/parcel/parcels_storage.cc
+++ b/components/commerce/core/parcel/parcels_storage.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "components/session_proto_db/session_proto_storage.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace commerce {
 
@@ -62,13 +63,23 @@
   proto_db_->UpdateEntries(std::move(content_to_insert), std::move(callback));
 }
 
-void ParcelsStorage::DeleteParcelStatus(
-    const ParcelIdentifier& parcel_identifier,
-    StorageUpdateCallback callback) {
+void ParcelsStorage::DeleteParcelStatus(const std::string& tracking_id,
+                                        StorageUpdateCallback callback) {
   DCHECK(is_initialized_);
-  std::string key = GetDbKeyFromParcelStatus(parcel_identifier);
-  parcels_cache_.erase(key);
-  proto_db_->DeleteOneEntry(key, base::BindOnce(std::move(callback)));
+
+  absl::optional<ParcelIdentifier> parcel_identifier;
+  for (auto& kv : parcels_cache_) {
+    auto& identifier = kv.second.parcel_identifier();
+    if (identifier.tracking_id() == tracking_id) {
+      parcel_identifier = identifier;
+      break;
+    }
+  }
+  if (parcel_identifier.has_value()) {
+    std::string key = GetDbKeyFromParcelStatus(parcel_identifier.value());
+    parcels_cache_.erase(key);
+    proto_db_->DeleteOneEntry(key, base::BindOnce(std::move(callback)));
+  }
 }
 
 void ParcelsStorage::DeleteAllParcelStatus(StorageUpdateCallback callback) {
diff --git a/components/commerce/core/parcel/parcels_storage.h b/components/commerce/core/parcel/parcels_storage.h
index 295c309..16c5c1ce 100644
--- a/components/commerce/core/parcel/parcels_storage.h
+++ b/components/commerce/core/parcel/parcels_storage.h
@@ -34,21 +34,22 @@
   virtual ~ParcelsStorage();
 
   // Initialize the storage, populate the cache entries.
-  void Init(OnInitializedCallback callback);
+  virtual void Init(OnInitializedCallback callback);
 
   // Gets all parcel status.
-  std::unique_ptr<std::vector<ParcelStatus>> GetAllParcelStatus();
+  virtual std::unique_ptr<std::vector<ParcelStatus>> GetAllParcelStatus();
 
   // Updates the status for a list of parcels.
-  void UpdateParcelStatus(const std::vector<ParcelStatus>& parcel_status,
-                          StorageUpdateCallback callback);
+  virtual void UpdateParcelStatus(
+      const std::vector<ParcelStatus>& parcel_status,
+      StorageUpdateCallback callback);
 
   // Deletes a parcel status from db.
-  void DeleteParcelStatus(const ParcelIdentifier& parcel_identifier,
-                          StorageUpdateCallback callback);
+  virtual void DeleteParcelStatus(const std::string& tracking_id,
+                                  StorageUpdateCallback callback);
 
   // Deletes all the parcel status from db.
-  void DeleteAllParcelStatus(StorageUpdateCallback callback);
+  virtual void DeleteAllParcelStatus(StorageUpdateCallback callback);
 
  private:
   void OnAllParcelsLoaded(OnInitializedCallback callback,
diff --git a/components/commerce/core/parcel/parcels_storage_unittest.cc b/components/commerce/core/parcel/parcels_storage_unittest.cc
index 8e57f52..f0d3a19 100644
--- a/components/commerce/core/parcel/parcels_storage_unittest.cc
+++ b/components/commerce/core/parcel/parcels_storage_unittest.cc
@@ -214,22 +214,17 @@
 }
 
 TEST_F(ParcelsStorageTest, TestDeleteParcelStatus) {
-  EXPECT_CALL(*proto_db_, DeleteOneEntry(_, _)).Times(2);
+  EXPECT_CALL(*proto_db_, DeleteOneEntry(_, _)).Times(1);
 
-  // Delete an invalid parcel identifier
-  ParcelIdentifier identifier;
-  identifier.set_carrier(commerce::ParcelIdentifier::FEDEX);
-  identifier.set_tracking_id("xyz");
-  storage_->DeleteParcelStatus(identifier, base::BindOnce(&DoNothing));
+  // Delete an invalid parcel tracking id.
+  storage_->DeleteParcelStatus("xyz", base::BindOnce(&DoNothing));
   task_environment_.RunUntilIdle();
 
   auto all_parcels = storage_->GetAllParcelStatus();
   ASSERT_EQ(1u, all_parcels->size());
 
-  // Delete the parcel identifier in storage.
-  identifier.set_carrier(kCarrier1);
-  identifier.set_tracking_id(kTrackingId1);
-  storage_->DeleteParcelStatus(identifier, base::BindOnce(&DoNothing));
+  // Delete the tracking id in storage.
+  storage_->DeleteParcelStatus(kTrackingId1, base::BindOnce(&DoNothing));
   task_environment_.RunUntilIdle();
 
   all_parcels = storage_->GetAllParcelStatus();
diff --git a/components/commerce/core/shopping_service.cc b/components/commerce/core/shopping_service.cc
index 57556940..605ba36 100644
--- a/components/commerce/core/shopping_service.cc
+++ b/components/commerce/core/shopping_service.cc
@@ -115,11 +115,11 @@
     const ParcelTrackingStatus&) = default;
 ParcelTrackingStatus::~ParcelTrackingStatus() = default;
 ParcelTrackingStatus::ParcelTrackingStatus(const ParcelStatus& parcel_status) {
-  ParcelTrackingStatus status;
-  status.carrier = parcel_status.parcel_identifier().carrier();
-  status.tracking_id = parcel_status.parcel_identifier().tracking_id();
-  status.tracking_url = GURL(parcel_status.tracking_url());
-  status.estimated_delivery_time = base::Time::FromDeltaSinceWindowsEpoch(
+  carrier = parcel_status.parcel_identifier().carrier();
+  tracking_id = parcel_status.parcel_identifier().tracking_id();
+  state = parcel_status.parcel_state();
+  tracking_url = GURL(parcel_status.tracking_url());
+  estimated_delivery_time = base::Time::FromDeltaSinceWindowsEpoch(
       base::Microseconds(parcel_status.estimated_delivery_time_usec()));
 }
 
diff --git a/components/content_settings/core/browser/BUILD.gn b/components/content_settings/core/browser/BUILD.gn
index e774418..570c894e 100644
--- a/components/content_settings/core/browser/BUILD.gn
+++ b/components/content_settings/core/browser/BUILD.gn
@@ -56,6 +56,7 @@
     "//components/keyed_service/core",
     "//components/pref_registry:pref_registry",
     "//components/prefs",
+    "//components/privacy_sandbox:tracking_protection_prefs",
     "//components/url_formatter",
     "//extensions/buildflags",
     "//net",
@@ -112,6 +113,8 @@
     "//components/pref_registry:pref_registry",
     "//components/prefs",
     "//components/prefs:test_support",
+    "//components/privacy_sandbox:features",
+    "//components/privacy_sandbox:privacy_sandbox_prefs",
     "//components/sync_preferences:test_support",
     "//extensions/buildflags",
     "//net",
@@ -131,8 +134,6 @@
     deps += [
       "//components/policy:generated",
       "//components/policy/core/browser:test_support",
-      "//components/privacy_sandbox:features",
-      "//components/privacy_sandbox:privacy_sandbox_prefs",
       "//third_party/blink/public/common:headers",
     ]
   }
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc
index 096b962..6dcf101f 100644
--- a/components/content_settings/core/browser/cookie_settings.cc
+++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -21,6 +21,7 @@
 #include "components/permissions/features.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
+#include "components/privacy_sandbox/tracking_protection_prefs.h"
 #include "extensions/buildflags/buildflags.h"
 #include "net/cookies/cookie_setting_override.h"
 #include "net/cookies/cookie_util.h"
@@ -50,6 +51,10 @@
       prefs::kCookieControlsMode,
       base::BindRepeating(&CookieSettings::OnCookiePreferencesChanged,
                           base::Unretained(this)));
+  pref_change_registrar_.Add(
+      prefs::kTrackingProtection3pcdEnabled,
+      base::BindRepeating(&CookieSettings::OnCookiePreferencesChanged,
+                          base::Unretained(this)));
   OnCookiePreferencesChanged();
 }
 
@@ -290,6 +295,16 @@
     return true;
   }
 
+  // Cookies should always be blocked in 3PCD experiment or if debug flag is on.
+  // Note: TrackingProtectionSettings will set kTrackingProtection3pcd to false
+  // if kCookieControlsMode is enterprise controlled.
+  if (base::FeatureList::IsEnabled(
+          content_settings::features::kTrackingProtection3pcd) ||
+      pref_change_registrar_.prefs()->GetBoolean(
+          prefs::kTrackingProtection3pcdEnabled)) {
+    return true;
+  }
+
   CookieControlsMode mode = static_cast<CookieControlsMode>(
       pref_change_registrar_.prefs()->GetInteger(prefs::kCookieControlsMode));
 
diff --git a/components/content_settings/core/browser/cookie_settings_unittest.cc b/components/content_settings/core/browser/cookie_settings_unittest.cc
index 8ccfe07..65200f1 100644
--- a/components/content_settings/core/browser/cookie_settings_unittest.cc
+++ b/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -23,6 +23,7 @@
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/content_settings/core/test/content_settings_mock_provider.h"
 #include "components/content_settings/core/test/content_settings_test_utils.h"
+#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "extensions/buildflags/buildflags.h"
 #include "net/base/features.h"
@@ -184,6 +185,7 @@
     ContentSettingsRegistry::GetInstance()->ResetForTest();
     CookieSettings::RegisterProfilePrefs(prefs_.registry());
     HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
+    privacy_sandbox::RegisterProfilePrefs(prefs_.registry());
     settings_map_ = new HostContentSettingsMap(
         &prefs_, false /* is_off_the_record */, false /* store_last_modified */,
         false /* restore_session */, false /* should_record_metrics */);
diff --git a/components/content_settings/core/common/BUILD.gn b/components/content_settings/core/common/BUILD.gn
index 6940cf8..0099baf8 100644
--- a/components/content_settings/core/common/BUILD.gn
+++ b/components/content_settings/core/common/BUILD.gn
@@ -42,16 +42,13 @@
 
   deps = [
     "//build:blink_buildflags",
+    "//components/privacy_sandbox:features",
     "//ipc",
     "//mojo/public/cpp/base",
     "//mojo/public/cpp/bindings:struct_traits",
     "//net",
     "//url",
   ]
-
-  if (use_blink) {
-    deps += [ "//components/privacy_sandbox:features" ]
-  }
 }
 
 source_set("unit_tests") {
diff --git a/components/enterprise/idle/idle_timeout_policy_handler.cc b/components/enterprise/idle/idle_timeout_policy_handler.cc
index f840847..42161dd 100644
--- a/components/enterprise/idle/idle_timeout_policy_handler.cc
+++ b/components/enterprise/idle/idle_timeout_policy_handler.cc
@@ -119,10 +119,9 @@
                   base::Value(std::move(converted_actions)));
 
   if (browsing_data::IsPolicyDependencyEnabled()) {
-    std::string log_message;
-    browsing_data::DisableSyncTypes(forced_disabled_sync_types_, prefs,
-                                    policy_name(), log_message);
-    if (log_message != std::string()) {
+    std::string log_message = browsing_data::DisableSyncTypes(
+        forced_disabled_sync_types_, prefs, policy_name());
+    if (!log_message.empty()) {
       LOG_POLICY(INFO, POLICY_PROCESSING) << log_message;
     }
   }
diff --git a/components/feed/core/v2/BUILD.gn b/components/feed/core/v2/BUILD.gn
index cb95f39..5f35b1a6 100644
--- a/components/feed/core/v2/BUILD.gn
+++ b/components/feed/core/v2/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//components/supervised_user/buildflags.gni")
 import("//testing/test.gni")
 
 if (is_android) {
@@ -259,6 +260,7 @@
       "//components/signin/public/identity_manager",
       "//components/signin/public/identity_manager:test_support",
       "//components/sync/base",
+      "//components/sync_preferences:test_support",
       "//components/variations:test_support",
       "//components/version_info:channel",
       "//net:test_support",
@@ -268,6 +270,15 @@
       "//testing/gtest",
       "//third_party/zlib/google:compression_utils",
     ]
+
+    if (enable_supervised_users) {
+      sources += [ "api_test/feed_api_supervised_feed_unittest.cc" ]
+      deps += [
+        "//components/supervised_user/core/browser",
+        "//components/supervised_user/core/browser:supervised_user_preferences",
+        "//components/supervised_user/core/common:features",
+      ]
+    }
   }
 
   source_set("feed_core_stubs") {
diff --git a/components/feed/core/v2/DEPS b/components/feed/core/v2/DEPS
index 833d0912..4403069c 100644
--- a/components/feed/core/v2/DEPS
+++ b/components/feed/core/v2/DEPS
@@ -4,6 +4,8 @@
   "-components/feed/core/v2/web_feed_subscriptions",
   "+components/reading_list/features",
   "+components/search_engines",
+  "+components/supervised_user",
+  "+components/sync_preferences",
  ]
 
 specific_include_rules = {
diff --git a/components/feed/core/v2/api_test/feed_api_supervised_feed_unittest.cc b/components/feed/core/v2/api_test/feed_api_supervised_feed_unittest.cc
new file mode 100644
index 0000000..b734448
--- /dev/null
+++ b/components/feed/core/v2/api_test/feed_api_supervised_feed_unittest.cc
@@ -0,0 +1,86 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/feed/core/proto/v2/wire/feed_entry_point_source.pb.h"
+#include "components/feed/core/proto/v2/wire/feed_query.pb.h"
+
+#include "components/feed/core/v2/api_test/feed_api_test.h"
+#include "components/feed/core/v2/feed_network.h"
+#include "components/feed/core/v2/public/stream_type.h"
+#include "components/feed/core/v2/public/types.h"
+#include "components/supervised_user/core/browser/child_account_service.h"
+#include "components/supervised_user/core/browser/supervised_user_preferences.h"
+#include "components/supervised_user/core/browser/supervised_user_service.h"
+#include "components/supervised_user/core/common/features.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// This file is for testing the Supervised Feed content.
+
+namespace feed::test {
+namespace {
+
+class FeedApiSupervisedUserTest : public FeedApiTest {
+ public:
+  void SetUp() override {
+    supervised_user::SupervisedUserService::RegisterProfilePrefs(
+        profile_prefs_.registry());
+    supervised_user::ChildAccountService::RegisterProfilePrefs(
+        profile_prefs_.registry());
+    supervised_user::EnableParentalControls(profile_prefs_);
+
+    feature_list_.InitAndEnableFeature(
+        supervised_user::kKidFriendlyContentFeed);
+    FeedApiTest::SetUp();
+  }
+
+ protected:
+  // Returns model state for `StreamKind::kSupervisedUser`.
+  std::unique_ptr<StreamModelUpdateRequest>
+  MakeTypicalInitialModelStateForSupervisedUser() {
+    return MakeTypicalInitialModelState(
+        0, kTestTimeEpoch, /*signed_in=*/true, /*logging_enabled=*/true,
+        /*privacy_notice_fulfilled=*/false,
+        feedstore::StreamKey(StreamType(StreamKind::kSupervisedUser)));
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// Shows feed content for supervised users.
+TEST_F(FeedApiSupervisedUserTest, LoadSupervisedFeed) {
+  response_translator_.InjectResponse(
+      MakeTypicalInitialModelStateForSupervisedUser());
+  TestSupervisedFeedSurface surface(stream_.get());
+  WaitForIdleTaskQueue();
+
+  StreamType stream_type(StreamKind::kSupervisedUser);
+  // Verify the model is filled correctly.
+  ASSERT_EQ(stream_->GetModel(stream_type)->DumpStateForTesting(),
+            ModelStateFor(stream_type, store_.get()));
+  // Verify the data is written to the store.
+  EXPECT_STRINGS_EQUAL(
+      ModelStateFor(MakeTypicalInitialModelStateForSupervisedUser()),
+      ModelStateFor(stream_type, store_.get()));
+  EXPECT_EQ("loading -> [user@foo] 2 slices", surface.DescribeUpdates());
+}
+
+// Supervised feed is deleted after surface is detached.
+TEST_F(FeedApiSupervisedUserTest, DeleteSupervisedFeedOnDetachedSurface) {
+  response_translator_.InjectResponse(
+      MakeTypicalInitialModelStateForSupervisedUser());
+  TestSupervisedFeedSurface surface(stream_.get());
+  WaitForIdleTaskQueue();
+
+  surface.Detach();
+
+  WaitForModelToAutoUnload();
+  WaitForIdleTaskQueue();
+
+  StreamType stream_type(StreamKind::kSupervisedUser);
+  EXPECT_FALSE(stream_->GetModel(stream_type));
+}
+
+}  // namespace
+}  // namespace feed::test
diff --git a/components/feed/core/v2/api_test/feed_api_test.cc b/components/feed/core/v2/api_test/feed_api_test.cc
index 0ef6e8c..641f997 100644
--- a/components/feed/core/v2/api_test/feed_api_test.cc
+++ b/components/feed/core/v2/api_test/feed_api_test.cc
@@ -368,6 +368,8 @@
           StreamType(StreamKind::kSingleWebFeed, web_feed_id, entry_point),
           stream,
           entry_point) {}
+TestSupervisedFeedSurface::TestSupervisedFeedSurface(FeedStream* stream)
+    : TestSurfaceBase(StreamType(StreamKind::kSupervisedUser), stream) {}
 
 TestReliabilityLoggingBridge::TestReliabilityLoggingBridge() = default;
 TestReliabilityLoggingBridge::~TestReliabilityLoggingBridge() = default;
diff --git a/components/feed/core/v2/api_test/feed_api_test.h b/components/feed/core/v2/api_test/feed_api_test.h
index 17794a1..14f359b 100644
--- a/components/feed/core/v2/api_test/feed_api_test.h
+++ b/components/feed/core/v2/api_test/feed_api_test.h
@@ -41,6 +41,7 @@
 #include "components/prefs/testing_pref_service.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/signin/public/base/signin_pref_names.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "net/http/http_status_code.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -218,6 +219,10 @@
       std::string = "",
       SingleWebFeedEntryPoint entry_point = SingleWebFeedEntryPoint::kOther);
 };
+class TestSupervisedFeedSurface : public TestSurfaceBase {
+ public:
+  explicit TestSupervisedFeedSurface(FeedStream* stream = nullptr);
+};
 
 class TestImageFetcher : public ImageFetcher {
  public:
@@ -550,7 +555,7 @@
  protected:
   base::test::TaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
-  TestingPrefServiceSimple profile_prefs_;
+  sync_preferences::TestingPrefServiceSyncable profile_prefs_;
   std::unique_ptr<TestMetricsReporter> metrics_reporter_;
   TestFeedNetwork network_;
   TestWireResponseTranslator response_translator_;
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc
index 41f391c09..5b8ec50 100644
--- a/components/feed/core/v2/feed_stream.cc
+++ b/components/feed/core/v2/feed_stream.cc
@@ -1103,6 +1103,8 @@
     case StreamKind::kUnknown:
       DLOG(ERROR) << "Unknown stream kind";
       [[fallthrough]];
+    // TODO(b/300455747): Add network request type for kids content.
+    case StreamKind::kSupervisedUser:
     case StreamKind::kForYou:
       request_type = (load_type != LoadType::kLoadMore)
                          ? NetworkRequestType::kFeedQuery
diff --git a/components/feed/core/v2/feedstore_util.cc b/components/feed/core/v2/feedstore_util.cc
index 80223ea..aba2a4e3 100644
--- a/components/feed/core/v2/feedstore_util.cc
+++ b/components/feed/core/v2/feedstore_util.cc
@@ -24,6 +24,9 @@
     return kForYouStreamKey;
   if (stream_type.IsWebFeed())
     return kFollowStreamKey;
+  if (stream_type.IsForSupervisedUser()) {
+    return kSupervisedUserStreamKey;
+  }
   DCHECK(stream_type.IsSingleWebFeed());
   std::string encoding;
   base::Base64UrlEncode(stream_type.GetWebFeedId(),
@@ -41,12 +44,19 @@
 }
 
 base::StringPiece StreamPrefix(feed::StreamKind stream_kind) {
-  if (stream_kind == feed::StreamKind::kForYou)
-    return kForYouStreamKey;
-  if (stream_kind == feed::StreamKind::kFollowing)
-    return kFollowStreamKey;
-  DCHECK(stream_kind == feed::StreamKind::kSingleWebFeed);
-  return kSingleWebFeedStreamKeyPrefix;
+  switch (stream_kind) {
+    case feed::StreamKind::kForYou:
+      return kForYouStreamKey;
+    case feed::StreamKind::kFollowing:
+      return kFollowStreamKey;
+    case feed::StreamKind::kSupervisedUser:
+      return kSupervisedUserStreamKey;
+    case feed::StreamKind::kSingleWebFeed:
+      return kSingleWebFeedStreamKeyPrefix;
+    case feed::StreamKind::kUnknown:
+      NOTREACHED();
+      return kSingleWebFeedStreamKeyPrefix;
+  }
 }
 
 StreamType DecodeSingleWebFeedKeySuffix(
@@ -71,6 +81,9 @@
     return StreamType(feed::StreamKind::kForYou);
   if (id == kFollowStreamKey)
     return StreamType(feed::StreamKind::kFollowing);
+  if (id == kSupervisedUserStreamKey) {
+    return StreamType(feed::StreamKind::kSupervisedUser);
+  }
   if (base::StartsWith(id, kSingleWebFeedStreamKeyPrefix,
                        base::CompareCase::SENSITIVE)) {
     if ((id.size() < (kSingleWebFeedStreamKeyPrefix.size() +
diff --git a/components/feed/core/v2/feedstore_util.h b/components/feed/core/v2/feedstore_util.h
index 3cc7a741..87ae691 100644
--- a/components/feed/core/v2/feedstore_util.h
+++ b/components/feed/core/v2/feedstore_util.h
@@ -23,6 +23,7 @@
 
 const char kForYouStreamKey[] = "i";
 const char kFollowStreamKey[] = "w";
+const char kSupervisedUserStreamKey[] = "s";
 constexpr base::StringPiece kSingleWebFeedStreamKeyPrefix = "c";
 constexpr base::StringPiece kSingleWebFeedMenuStreamKeyPrefix = "m/";
 constexpr base::StringPiece kSingleWebFeedOtherStreamKeyPrefix = "o/";
diff --git a/components/feed/core/v2/feedstore_util_unittest.cc b/components/feed/core/v2/feedstore_util_unittest.cc
index 68208bbd..0bfdcc5 100644
--- a/components/feed/core/v2/feedstore_util_unittest.cc
+++ b/components/feed/core/v2/feedstore_util_unittest.cc
@@ -80,11 +80,13 @@
       StreamKind::kSingleWebFeed, "A", feed::SingleWebFeedEntryPoint::kMenu);
   StreamType single_web_feed_other = StreamType(
       StreamKind::kSingleWebFeed, "A", feed::SingleWebFeedEntryPoint::kOther);
+  StreamType supervised_feed = StreamType(StreamKind::kSupervisedUser);
 
   StreamType unknown = StreamType();
 
   EXPECT_EQ(StreamKey(for_you), kForYouStreamKey);
   EXPECT_EQ(StreamKey(following), kFollowStreamKey);
+  EXPECT_EQ(StreamKey(supervised_feed), kSupervisedUserStreamKey);
   EXPECT_DCHECK_DEATH(StreamKey(unknown));
 
   EXPECT_TRUE(StreamTypeFromKey(StreamKey(single_web_feed)).IsSingleWebFeed());
@@ -100,6 +102,8 @@
 
   EXPECT_TRUE(StreamTypeFromKey(StreamKey(following)).IsWebFeed());
   EXPECT_TRUE(StreamTypeFromKey(StreamKey(for_you)).IsForYou());
+  EXPECT_TRUE(
+      StreamTypeFromKey(StreamKey(supervised_feed)).IsForSupervisedUser());
   EXPECT_EQ(StreamTypeFromKey("z"), StreamType());
 }
 
diff --git a/components/feed/core/v2/metrics_reporter.cc b/components/feed/core/v2/metrics_reporter.cc
index 57605fd..cdfd5f58 100644
--- a/components/feed/core/v2/metrics_reporter.cc
+++ b/components/feed/core/v2/metrics_reporter.cc
@@ -39,7 +39,8 @@
 
 namespace feed {
 namespace {
-StreamKind kStreamKinds[] = {StreamKind::kForYou, StreamKind::kFollowing,
+StreamKind kStreamKinds[] = {StreamKind::kForYou, StreamKind::kSupervisedUser,
+                             StreamKind::kFollowing,
                              StreamKind::kSingleWebFeed};
 // TODO(crbug.com/1369777) Add kSingleWebFeed streams to metrics reporting below
 using feed::FeedEngagementType;
@@ -78,6 +79,8 @@
 
 base::StringPiece HistogramReplacement(const StreamType& stream_type) {
   switch (stream_type.GetKind()) {
+    case StreamKind::kSupervisedUser:
+      return "Feed.SupervisedFeed.";
     case StreamKind::kForYou:
       return "Feed.";
     case StreamKind::kFollowing:
@@ -119,6 +122,11 @@
           "ContentSuggestions.Feed.SingleWebFeed.Opened", index_in_stream,
           kMaxSuggestionsTotal);
       break;
+    case StreamKind::kSupervisedUser:
+      base::UmaHistogramExactLinear(
+          "ContentSuggestions.Feed.SupervisedFeed.Opened", index_in_stream,
+          kMaxSuggestionsTotal);
+      break;
     case StreamKind::kUnknown:
       DCHECK(false) << "unknown feed kind";
       break;
@@ -541,6 +549,11 @@
           "ContentSuggestions.Feed.SingleWebFeed.Shown", index_in_stream,
           kMaxSuggestionsTotal);
       break;
+    case StreamKind::kSupervisedUser:
+      base::UmaHistogramExactLinear(
+          "ContentSuggestions.Feed.SupervisedFeed.Shown", index_in_stream,
+          kMaxSuggestionsTotal);
+      break;
     case StreamKind::kUnknown:
       DCHECK(false) << "unknown feed kind";
       break;
@@ -1137,6 +1150,8 @@
   switch (stream_type.GetKind()) {
     case StreamKind::kForYou:
       return for_you_stats_;
+    case StreamKind::kSupervisedUser:
+      return supervised_feed_stats_;
     case StreamKind::kFollowing:
     case StreamKind::kSingleWebFeed:
       return web_feed_stats_;
diff --git a/components/feed/core/v2/metrics_reporter.h b/components/feed/core/v2/metrics_reporter.h
index d016b36..a7bb8ee 100644
--- a/components/feed/core/v2/metrics_reporter.h
+++ b/components/feed/core/v2/metrics_reporter.h
@@ -222,6 +222,7 @@
   raw_ptr<Delegate, DanglingUntriaged> delegate_ = nullptr;
 
   StreamStats for_you_stats_;
+  StreamStats supervised_feed_stats_;
   StreamStats web_feed_stats_;
   StreamStats combined_stats_;
 
diff --git a/components/feed/core/v2/metrics_reporter_unittest.cc b/components/feed/core/v2/metrics_reporter_unittest.cc
index 5f081d8..21e73bd 100644
--- a/components/feed/core/v2/metrics_reporter_unittest.cc
+++ b/components/feed/core/v2/metrics_reporter_unittest.cc
@@ -96,6 +96,10 @@
       case StreamKind::kSingleWebFeed:
         histogram_name = "ContentSuggestions.Feed.SingleWebFeed.EngagementType";
         break;
+      case StreamKind::kSupervisedUser:
+        histogram_name =
+            "ContentSuggestions.Feed.SupervisedFeed.EngagementType";
+        break;
     }
     for (const auto& bucket : histogram_.GetAllSamples(histogram_name)) {
       result[static_cast<FeedEngagementType>(bucket.min)] += bucket.count;
diff --git a/components/feed/core/v2/public/stream_type.cc b/components/feed/core/v2/public/stream_type.cc
index 94e82de..51eb936 100644
--- a/components/feed/core/v2/public/stream_type.cc
+++ b/components/feed/core/v2/public/stream_type.cc
@@ -14,6 +14,8 @@
       return "ForYou";
     case StreamKind::kFollowing:
       return "WebFeed";
+    case StreamKind::kSupervisedUser:
+      return "SupervisedUserFeed";
     case StreamKind::kSingleWebFeed:
       return "SingleWebFeed_" + web_feed_id_;
   }
@@ -38,6 +40,7 @@
       return true;
     case StreamKind::kFollowing:
     case StreamKind::kSingleWebFeed:
+    case StreamKind::kSupervisedUser:
       return false;
   }
 }
diff --git a/components/feed/core/v2/public/stream_type.h b/components/feed/core/v2/public/stream_type.h
index adafbe85..c796c31 100644
--- a/components/feed/core/v2/public/stream_type.h
+++ b/components/feed/core/v2/public/stream_type.h
@@ -44,6 +44,9 @@
            (single_web_feed_entry_point_menu_ ==
             rhs.single_web_feed_entry_point_menu_);
   }
+  bool IsForSupervisedUser() const {
+    return kind_ == StreamKind::kSupervisedUser;
+  }
   bool IsForYou() const { return kind_ == StreamKind::kForYou; }
   bool IsWebFeed() const { return kind_ == StreamKind::kFollowing; }
   bool IsSingleWebFeed() const { return kind_ == StreamKind::kSingleWebFeed; }
diff --git a/components/feed/core/v2/public/types.h b/components/feed/core/v2/public/types.h
index ed2b116..5d16268 100644
--- a/components/feed/core/v2/public/types.h
+++ b/components/feed/core/v2/public/types.h
@@ -271,8 +271,10 @@
   kFollowing = 2,
   // Single Web Feed (Cormorant) stream.
   kSingleWebFeed = 3,
+  // Kid-friendly content stream.
+  kSupervisedUser = 4,
 
-  kMaxValue = kSingleWebFeed,
+  kMaxValue = kSupervisedUser,
 };
 
 // Singe Web entry points
diff --git a/components/feed/core/v2/tasks/load_stream_task.cc b/components/feed/core/v2/tasks/load_stream_task.cc
index cdd20c2..99d18e2 100644
--- a/components/feed/core/v2/tasks/load_stream_task.cc
+++ b/components/feed/core/v2/tasks/load_stream_task.cc
@@ -329,7 +329,12 @@
 
   FeedNetwork& network = stream_->GetNetwork();
   const bool force_feed_query = GetFeedConfig().use_feed_query_requests;
-  if (!force_feed_query && options_.stream_type.IsWebFeed()) {
+  if (options_.stream_type.IsForSupervisedUser()) {
+    // TODO(b/295472540): Send request to GWS plugin for kids content.
+    network.SendApiRequest<QueryInteractiveFeedDiscoverApi>(
+        request, account_info, std::move(request_metadata),
+        base::BindOnce(&LoadStreamTask::QueryApiRequestComplete, GetWeakPtr()));
+  } else if (!force_feed_query && options_.stream_type.IsWebFeed()) {
     // Special case: web feed that is not using Feed Query requests go to
     // WebFeedListContentsDiscoverApi.
     network.SendApiRequest<WebFeedListContentsDiscoverApi>(
diff --git a/components/live_caption/BUILD.gn b/components/live_caption/BUILD.gn
index 17480f4..38694ae 100644
--- a/components/live_caption/BUILD.gn
+++ b/components/live_caption/BUILD.gn
@@ -70,6 +70,8 @@
 
   static_library("live_translate") {
     sources = [
+      "greedy_text_stabilizer.cc",
+      "greedy_text_stabilizer.h",
       "live_translate_controller.cc",
       "live_translate_controller.h",
     ]
@@ -99,10 +101,15 @@
   source_set("unit_tests") {
     testonly = true
 
-    sources = [ "caption_bubble_context_remote_unittest.cc" ]
+    sources = [ "greedy_text_stabilizer_unittest.cc" ]
+
+    if (is_chromeos_ash) {
+      sources += [ "caption_bubble_context_remote_unittest.cc" ]
+    }
 
     deps = [
       ":live_caption",
+      ":live_translate",
       "//base",
       "//base/test:test_support",
       "//media/mojo/mojom:speech_recognition",
diff --git a/components/live_caption/greedy_text_stabilizer.cc b/components/live_caption/greedy_text_stabilizer.cc
new file mode 100644
index 0000000..39d41ed
--- /dev/null
+++ b/components/live_caption/greedy_text_stabilizer.cc
@@ -0,0 +1,146 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/live_caption/greedy_text_stabilizer.h"
+
+#include <regex>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "base/strings/string_tokenizer.h"
+
+namespace {
+std::string RemoveTrailingSpace(const std::string& input) {
+  if (input.length() > 0 && std::isspace(input.back())) {
+    return input.substr(0, input.length() - 1);
+  } else {
+    return input;
+  }
+}
+}  // namespace
+
+namespace captions {
+
+GreedyTextStabilizer::GreedyTextStabilizer(int min_token_frequency)
+    : min_token_frequency_(min_token_frequency < 0 ? 0 : min_token_frequency) {}
+
+GreedyTextStabilizer::~GreedyTextStabilizer() = default;
+
+std::string GreedyTextStabilizer::UpdateText(const std::string& input_text,
+                                             const bool is_final) {
+  // For final recognition results, we use all tokens even if they are unstable.
+  // Reset the stabilizer in preparation for receiving new partial recognition
+  // results.
+  if (is_final) {
+    Reset();
+    return input_text;
+  }
+
+  const std::vector<std::string> tokens = Tokenize(input_text);
+
+  // When min_token_frequency_ is 0, we define the output to be the input.
+  // Therefore, we can exit early.
+  if (min_token_frequency_ == 0) {
+    stable_text_ = input_text;
+    stable_token_count_ = tokens.size();
+    return input_text;
+  }
+
+  // Add each token to the correct position in the tokens dictionary.
+  for (unsigned long i = 0; i < tokens.size(); ++i) {
+    const std::string token = RemoveTrailingSpace(tokens[i]);
+    // If this location in the sentence does not yet exist, we need to extend
+    // the vector to include this location.
+    if (i >= tokens_histograms_.size()) {
+      std::unordered_map<std::string, int> token_histogram = {{token, 1}};
+      tokens_histograms_.push_back(token_histogram);
+    } else {
+      // Increment the count of the token in the dictionary at this location.
+      tokens_histograms_[i][token]++;
+    }
+  }
+
+  // Now compare the input tokens to those in the distributions.
+  // As we consider the token at each location, we determine it to be stable if
+  // it is the mode in the token dictionary for that location and its token
+  // frequency is high enough. Otherwise, it is considered unstable, and we exit
+  // early.
+  stable_token_count_ = 0;
+  int stable_character_count = 0;
+  for (unsigned long i = 0; i < tokens.size(); i++) {
+    const std::string token = RemoveTrailingSpace(tokens[i]);
+    if (i < tokens_histograms_.size() &&
+        tokens_histograms_[i][token] >= min_token_frequency_ &&
+        IsMode(token, tokens_histograms_[i])) {
+      // Use the size of the unstripped token.
+      stable_character_count += tokens[i].size();
+      stable_token_count_++;
+    } else {
+      break;
+    }
+  }
+
+  // Only use the new text if it has more tokens than the previous stable text.
+  // This prevents shrinkage of the text.
+  if (stable_token_count_ >= max_stable_token_count_) {
+    max_stable_token_count_ = stable_token_count_;
+
+    // Update the stable text.
+    if (stable_token_count_ <= 0) {
+      stable_text_ = std::string();
+    } else {
+      stable_text_ = input_text.substr(0, stable_character_count);
+    }
+  }
+
+  return stable_text_;
+}
+
+void GreedyTextStabilizer::Reset() {
+  max_stable_token_count_ = 0;
+  stable_token_count_ = 0;
+  stable_text_ = std::string();
+  tokens_histograms_.clear();
+}
+
+std::vector<std::string> GreedyTextStabilizer::Tokenize(
+    const std::string& input_text) {
+  std::vector<std::string> tokens;
+
+  base::StringTokenizer t(input_text, " ");
+  t.set_options(base::StringTokenizer::RETURN_DELIMS);
+  while (t.GetNext()) {
+    // Trailing punctuation should be treated as a separate token so that
+    // flickering punctuation can be handled appropriately.
+    if (t.token().size() > 0 && std::ispunct(t.token().back())) {
+      tokens.push_back(t.token().substr(0, t.token().size() - 1));
+      tokens.push_back(t.token().substr(t.token().size() - 1, 1));
+    } else {
+      tokens.push_back(t.token());
+    }
+  }
+
+  return tokens;
+}
+
+bool GreedyTextStabilizer::IsMode(
+    const std::string& token,
+    const std::unordered_map<std::string, int>& token_histogram) {
+  const int token_count = token_histogram.at(token);
+
+  // There could be multiple modes in the histogram, and we only need to ensure
+  // that the given token is one of the modes.  Thus, the given token is a mode
+  // only if no other token has a higher count than the given token.
+  for (const auto& element : token_histogram) {
+    if (element.second > token_count) {
+      // If we have found a token with a higher count, we exit early and
+      // indicate that the given token is not a mode.
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace captions
diff --git a/components/live_caption/greedy_text_stabilizer.h b/components/live_caption/greedy_text_stabilizer.h
new file mode 100644
index 0000000..294eb71
--- /dev/null
+++ b/components/live_caption/greedy_text_stabilizer.h
@@ -0,0 +1,54 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_LIVE_CAPTION_GREEDY_TEXT_STABILIZER_H_
+#define COMPONENTS_LIVE_CAPTION_GREEDY_TEXT_STABILIZER_H_
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace captions {
+
+// Predicts the stable count of streaming token sequences.
+// This class has no knowledge of future partial results.  It simply
+// receives one partial at a time and is forced to make a prediction on
+// the number of stable tokens using only the past partial results.
+// Implementation based off of https://goto.google.com/w2t.
+class GreedyTextStabilizer {
+ public:
+  // Initializes min_token_frequency and sets it to 0 if it is non-negative.
+  explicit GreedyTextStabilizer(int min_token_frequency);
+  ~GreedyTextStabilizer();
+
+  // Updates the internal structure that determines the number of stable tokens
+  // and returns the stable text.
+  std::string UpdateText(const std::string& input_text, bool is_final = false);
+
+  // Used by unit test only.
+  int GetStableTokenCount() const { return stable_token_count_; }
+
+ private:
+  // Minimum number of times a token must appear to be counted.
+  const int min_token_frequency_ = 0;
+
+  // List of token counts at different locations in the sequence.
+  std::vector<std::unordered_map<std::string, int>> tokens_histograms_;
+  std::string stable_text_ = "";
+  int max_stable_token_count_ = 0;
+  int stable_token_count_ = 0;
+
+  void Reset();
+
+  // Divides a string of text into individual tokens independent of language.
+  std::vector<std::string> Tokenize(const std::string& input_text);
+
+  // Checks whether the input token is a mode of the token histogram.
+  bool IsMode(const std::string& token,
+              const std::unordered_map<std::string, int>& token_histogram);
+};
+
+}  // namespace captions
+
+#endif  // COMPONENTS_LIVE_CAPTION_GREEDY_TEXT_STABILIZER_H_
diff --git a/components/live_caption/greedy_text_stabilizer_unittest.cc b/components/live_caption/greedy_text_stabilizer_unittest.cc
new file mode 100644
index 0000000..92d95e0
--- /dev/null
+++ b/components/live_caption/greedy_text_stabilizer_unittest.cc
@@ -0,0 +1,262 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/live_caption/greedy_text_stabilizer.h"
+
+#include <string>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace captions {
+
+class GreedyTextStabilizerTest : public testing::Test {
+ public:
+  GreedyTextStabilizerTest() = default;
+  ~GreedyTextStabilizerTest() override = default;
+};
+
+// Ensures that invalid min token frequency gets set to 0.
+TEST_F(GreedyTextStabilizerTest, NegativeMinTokenFrequencySetToZero) {
+  GreedyTextStabilizer stabilizer(-10);
+
+  // When min_token_frequency is 0, the output is set to the input.
+  EXPECT_EQ(stabilizer.UpdateText("Hello world"), "Hello world");
+}
+
+// Tests that empty sentences are handled correctly.
+TEST_F(GreedyTextStabilizerTest, EmptySentencesHaveZeroStableTokens) {
+  std::vector<std::string> partials = {"", "", ""};
+  GreedyTextStabilizer stabilizer(1);
+  for (const auto& partial : partials) {
+    stabilizer.UpdateText(partial);
+
+    // stable_count should be 0 for all results.
+    EXPECT_EQ(stabilizer.GetStableTokenCount(), 0);
+  }
+}
+
+// Tests that complete sentences are handled correctly.
+TEST_F(GreedyTextStabilizerTest, CompleteSentencesOutputFullText) {
+  GreedyTextStabilizer stabilizer(2);
+  // With min_token_frequency=2 the output will be empty for the first partial.
+  EXPECT_EQ(stabilizer.UpdateText("Hello world", /*is_final=*/false), "");
+  EXPECT_EQ(stabilizer.GetStableTokenCount(), 0);
+
+  // Since the tokens changed, the stabilization will still be empty.
+  EXPECT_EQ(stabilizer.UpdateText("Once upon a time", /*is_final=*/false), "");
+  EXPECT_EQ(stabilizer.GetStableTokenCount(), 0);
+
+  // But when the sentence is complete, the output should be equal to the input.
+  EXPECT_EQ(stabilizer.UpdateText("I don't care if Monday's blue",
+                                  /*is_final=*/true),
+            "I don't care if Monday's blue");
+  // But the number of stable tokens should still be 0.
+  EXPECT_EQ(stabilizer.GetStableTokenCount(), 0);
+}
+
+// Use the same phrase and only change the punctuation.
+// The punctuation will change if it is seen more often than others (the mode).
+TEST_F(GreedyTextStabilizerTest, PunctuationFlickerIsStabilized) {
+  const int min_token_frequency = 2;
+  GreedyTextStabilizer stabilizer(min_token_frequency);
+
+  // Partials with flickering punctuation and first letter.
+  const std::vector<std::string> partials = {
+      "He retired in 2008",  "He retired in 2008.", "He retired in 2008.",
+      "he retired in 2008,", "he retired in 2008",  "He retired in 2008.",
+      "he retired in 2008",  "He retired in 2008,", "he retired in 2008.",
+      "He retired in 2008,", "he retired in 2008"};
+
+  // Here, the first letter and punctuation are stabilized.
+  // No output is written at first because the tokens must be seen twice when
+  // min_token_frequency = 2.
+  const std::vector<std::string> stable_partials = {"",
+                                                    "He retired in 2008",
+                                                    "He retired in 2008.",
+                                                    "He retired in 2008.",
+                                                    "He retired in 2008.",
+                                                    "He retired in 2008.",
+                                                    "He retired in 2008.",
+                                                    "He retired in 2008.",
+                                                    "He retired in 2008.",
+                                                    "He retired in 2008.",
+                                                    "He retired in 2008."};
+
+  EXPECT_EQ(partials.size(), stable_partials.size());
+
+  for (unsigned long i = 0; i < partials.size(); ++i) {
+    EXPECT_EQ(stabilizer.UpdateText(partials[i]), stable_partials[i]);
+  }
+}
+
+// Tests the behavior for varying values of the min_token_frequency.
+TEST_F(GreedyTextStabilizerTest, MultipleFormsOfFlickerAreStabilized) {
+  // Here the capitalization of the first token flickers, the punctuation
+  // changes from nothing, to periods, to commas, and some tokens change.
+  // These should be stabilized by the algorithm.
+  const std::vector<std::string> partials = {
+      "After work",
+      "After working,",  // The second token got longer.
+      "After work,",
+      "after work, he",  // Here the "A" was changed to "a".
+      "after work. he",  // Here the "," was changed to ".".
+      "After work, he wood",
+      "After work. he would run.",  // We changed to a "." here.
+      "After work, he would run.",
+      "After work, he would run",  // The "." was removed here.
+      "After work, he would run. It is",
+  };
+
+  // When min frequency is 1, tokens are accepted as soon as they are seen.
+  // But, by nature of the algorithm, the result at a location can still
+  // change if a different token gets more votes over time.
+  const std::vector<std::string> stable_partials_1 = {
+      "After work",
+      "After working,",  // The second token is allowed because the frequency=1.
+      "After work,",
+      "After work,",          // Here the "A" remains but nothing is added.
+      "After work,",          // Here the "," remains, but nothing is added.
+      "After work, he wood",  // We allowed "wood" here.
+      "After work, he wood",  // The punctuation changed, so keep old prefix.
+      "After work, he would run.",
+      "After work, he would run.",  // The last entry with more tokens is used.
+      "After work, he would run. It is",
+  };
+
+  // When min frequency is 2, tokens are accepted after being seen at least
+  // twice. But, by nature of the algorithm, the result at a location can still
+  // change if a different token gets more votes over time.
+  const std::vector<std::string> stable_partials_2 = {
+      "",        // We haven't seen the tokens often enough to output anything.
+      "After ",  // The second token is ignored because it changed.
+      "After work,",
+      "After work,",
+      "After work,",  // We keep the previous prefix to retain the length.
+      "After work, he",
+      "After work, he",  // We keep the previous prefix to retain the length.
+      "After work, he would run.",
+      "After work, he would run.",  // We keep the previous prefix.
+      "After work, he would run.",
+  };
+
+  EXPECT_EQ(partials.size(), stable_partials_1.size());
+  EXPECT_EQ(partials.size(), stable_partials_2.size());
+  GreedyTextStabilizer stabilizer(0);
+  for (auto partial : partials) {
+    EXPECT_EQ(stabilizer.UpdateText(partial), partial);
+  }
+
+  GreedyTextStabilizer stabilizer_1(1);
+  for (unsigned long i = 0; i < partials.size(); ++i) {
+    EXPECT_EQ(stabilizer_1.UpdateText(partials[i]), stable_partials_1[i]);
+  }
+
+  GreedyTextStabilizer stabilizer_2(2);
+  for (unsigned long i = 0; i < partials.size(); ++i) {
+    EXPECT_EQ(stabilizer_2.UpdateText(partials[i]), stable_partials_2[i]);
+  }
+}
+
+// Test that greedy text stabilization works for long text sequences.
+TEST_F(GreedyTextStabilizerTest, FlickerInLongFormTextIsStabilized) {
+  const std::vector<std::string> partials = {
+      "soy",
+      "yo no",
+      "no soy vidente",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho es",
+      "no soy divisores de cajones videntes con decir es el",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy un divisor de cajones videntes al decir su defensa yo",
+      "no soy vidente divisores de cajones con decir su defensa i",
+      "no soy un divisor de cajones videntes al decir su defensa yo "
+      "simplemente",
+      "no soy divisor de cajones videntes con decir su defensa simplemente",
+      "no soy un divisor de cajones videntes al decir su defensa yo "
+      "simplemente",
+      "no soy un divisor de cajones videntes al decir su defensa simplemente "
+      "hago conjeturas",
+      "no soy un divisor de cajones videntes al decir su defensa simplemente "
+      "hago conjeturas en el sótano",
+      "no soy un divisor de cajones videntes al decir su defensa simplemente "
+      "hago conjeturas en los países del sótano",
+      "no soy un divisor de cajones videntes al decir su defensa simplemente "
+      "hago conjeturas en los países del sótano que",
+      "no soy un divisor de cajones videntes al decir su defensa simplemente "
+      "hago conjeturas de los países del sótano que yo"};
+
+  const std::vector<std::string> stable_partials = {
+      "",
+      "",
+      "",
+      "no soy vidente",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy vidente divisores de cajones con dicho",
+      "no soy un divisor de cajones videntes al decir su defensa simplemente "
+      "hago conjeturas en ",
+      "no soy un divisor de cajones videntes al decir su defensa simplemente "
+      "hago conjeturas en los países del sótano",
+      "no soy un divisor de cajones videntes al decir su defensa simplemente "
+      "hago conjeturas en los países del sótano"};
+
+  EXPECT_EQ(partials.size(), stable_partials.size());
+
+  GreedyTextStabilizer stabilizer(2);
+  for (unsigned long i = 0; i < partials.size(); ++i) {
+    EXPECT_EQ(stabilizer.UpdateText(partials[i]), stable_partials[i]);
+  }
+}
+
+TEST_F(GreedyTextStabilizerTest, KoreanTokensAreStabilized) {
+  const int min_token_frequency = 1;
+  GreedyTextStabilizer stabilizer(min_token_frequency);
+
+  const std::vector<std::string> partials = {
+      "나는",
+      "난 아니야",
+      "난 선견자가 아니야",
+      "내가 말하는 서랍 서랍 분배기가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "내가 말하는 서랍 서랍 분배기가 아니야",
+      "나는 그의 방어를 말하는 씨 서랍 서랍이 아닙니다 나는",
+      "나는 그의 방어를 말하는 시어 서랍 칸막이가 아니야",
+      "나는 그의 방어를 말하는 씨 서랍 서랍이 아닙니다 나는 단순히",
+      "나는 단순히 자신의 방어를 말하는 시어 서랍 디바이더가 아닙니다",
+      "나는 그의 방어를 말하는 씨 서랍 서랍이 아닙니다 나는 단순히",
+      "나는 그의 방어를 말하는 씨 서랍 서랍이 아닙니다 나는 단순히 추측을한다"};
+
+  // Stable partials when min_token_frequency=1.
+  const std::vector<std::string> stable_partials = {
+      "나는",
+      "난 아니야",
+      "난 선견자가 아니야",
+      "난 선견자가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "나는 서랍 서랍 분배기가 아니야",
+      "나는 그의 방어를 말하는 씨 서랍 서랍이 아닙니다 나는 단순히",
+      "나는 그의 방어를 말하는 씨 서랍 서랍이 아닙니다 나는 단순히 추측을한다"};
+
+  EXPECT_EQ(partials.size(), stable_partials.size());
+
+  for (unsigned long i = 0; i < partials.size(); ++i) {
+    EXPECT_EQ(stabilizer.UpdateText(partials[i]), stable_partials[i]);
+  }
+}
+
+}  // namespace captions
diff --git a/components/media_effects/BUILD.gn b/components/media_effects/BUILD.gn
index c7f2a0e..659f96c 100644
--- a/components/media_effects/BUILD.gn
+++ b/components/media_effects/BUILD.gn
@@ -8,6 +8,8 @@
     "//third_party/abseil-cpp:absl",
   ]
   sources = [
+    "media_effects_manager_binder.cc",
+    "media_effects_manager_binder.h",
     "media_effects_service.cc",
     "media_effects_service.h",
     "media_effects_service_factory.cc",
@@ -28,6 +30,7 @@
     "//testing/gtest",
   ]
   sources = [
+    "media_effects_manager_binder_unittest.cc",
     "media_effects_service_factory_unittest.cc",
     "media_effects_service_unittest.cc",
     "video_effects_manager_impl_unittest.cc",
diff --git a/components/media_effects/media_effects_manager_binder.cc b/components/media_effects/media_effects_manager_binder.cc
new file mode 100644
index 0000000..efe1ec5e
--- /dev/null
+++ b/components/media_effects/media_effects_manager_binder.cc
@@ -0,0 +1,47 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/media_effects/media_effects_manager_binder.h"
+#include "components/media_effects/media_effects_service_factory.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+void BindVideoEffectsManagerOnUIThread(
+    const std::string& device_id,
+    content::BrowserContext* browser_context,
+    mojo::PendingReceiver<video_capture::mojom::VideoEffectsManager>
+        video_effects_manager) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  auto* media_effects_service =
+      MediaEffectsServiceFactory::GetForBrowserContext(browser_context);
+  if (!media_effects_service) {
+    LOG(WARNING) << "Video device not registered because no service was "
+                    "returned for the current BrowserContext";
+    return;
+  }
+
+  media_effects_service->BindVideoEffectsManager(
+      device_id, std::move(video_effects_manager));
+}
+}  // namespace
+
+namespace media_effects {
+
+void BindVideoEffectsManager(
+    const std::string& device_id,
+    content::BrowserContext* browser_context,
+    mojo::PendingReceiver<video_capture::mojom::VideoEffectsManager>
+        video_effects_manager) {
+  if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
+    BindVideoEffectsManagerOnUIThread(device_id, browser_context,
+                                      std::move(video_effects_manager));
+    return;
+  }
+  // The function wasn't called from the UI thread, so post a task.
+  content::GetUIThreadTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&BindVideoEffectsManagerOnUIThread, device_id,
+                     browser_context, std::move(video_effects_manager)));
+}
+}  // namespace media_effects
diff --git a/components/media_effects/media_effects_manager_binder.h b/components/media_effects/media_effects_manager_binder.h
new file mode 100644
index 0000000..28bf5764
--- /dev/null
+++ b/components/media_effects/media_effects_manager_binder.h
@@ -0,0 +1,22 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MEDIA_EFFECTS_MEDIA_EFFECTS_MANAGER_BINDER_H_
+#define COMPONENTS_MEDIA_EFFECTS_MEDIA_EFFECTS_MANAGER_BINDER_H_
+
+#include "content/public/browser/browser_context.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "services/video_capture/public/mojom/video_effects_manager.mojom.h"
+
+namespace media_effects {
+
+void BindVideoEffectsManager(
+    const std::string& device_id,
+    content::BrowserContext* browser_context,
+    mojo::PendingReceiver<video_capture::mojom::VideoEffectsManager>
+        video_effects_manager);
+
+}  // namespace media_effects
+
+#endif  // COMPONENTS_MEDIA_EFFECTS_MEDIA_EFFECTS_MANAGER_BINDER_H_
diff --git a/components/media_effects/media_effects_manager_binder_unittest.cc b/components/media_effects/media_effects_manager_binder_unittest.cc
new file mode 100644
index 0000000..cbd0a63
--- /dev/null
+++ b/components/media_effects/media_effects_manager_binder_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/media_effects/media_effects_manager_binder.h"
+#include "base/test/test_future.h"
+#include "components/user_prefs/test/test_browser_context_with_prefs.h"
+#include "content/public/test/browser_task_environment.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/video_capture/public/mojom/video_effects_manager.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/insets_f.h"
+
+namespace {
+video_capture::mojom::VideoEffectsConfigurationPtr GetConfigurationSync(
+    mojo::Remote<video_capture::mojom::VideoEffectsManager>& effect_manager) {
+  base::test::TestFuture<video_capture::mojom::VideoEffectsConfigurationPtr>
+      output_configuration;
+  effect_manager->GetConfiguration(output_configuration.GetCallback());
+  return output_configuration.Take();
+}
+}  // namespace
+
+class MediaEffectsManagerBinderTest : public testing::Test {
+ protected:
+  content::BrowserTaskEnvironment task_environment_;
+  user_prefs::TestBrowserContextWithPrefs browser_context_;
+};
+
+TEST_F(MediaEffectsManagerBinderTest, BindVideoEffectsManager) {
+  const char* kDeviceId = "device_id";
+
+  mojo::Remote<video_capture::mojom::VideoEffectsManager> video_effects_manager;
+  media_effects::BindVideoEffectsManager(
+      kDeviceId, &browser_context_,
+      video_effects_manager.BindNewPipeAndPassReceiver());
+
+  // Allow queued device registration to complete.
+  base::RunLoop().RunUntilIdle();
+
+  const float kPaddingRatio = 0.383;
+  base::test::TestFuture<video_capture::mojom::SetConfigurationResult>
+      result_future;
+  video_effects_manager->SetConfiguration(
+      video_capture::mojom::VideoEffectsConfiguration::New(
+          nullptr, nullptr,
+          video_capture::mojom::Framing::New(gfx::InsetsF{kPaddingRatio})),
+      result_future.GetCallback());
+  EXPECT_EQ(video_capture::mojom::SetConfigurationResult::kOk,
+            result_future.Get());
+
+  EXPECT_EQ(kPaddingRatio, GetConfigurationSync(video_effects_manager)
+                               ->framing->padding_ratios.top());
+}
diff --git a/components/metrics/metrics_features.cc b/components/metrics/metrics_features.cc
index 0067e327..6a83d0e9 100644
--- a/components/metrics/metrics_features.cc
+++ b/components/metrics/metrics_features.cc
@@ -10,10 +10,6 @@
              "MetricsServiceAllowEarlyLogClose",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kMetricsClearLogsOnClonedInstall,
-             "MetricsClearLogsOnClonedInstall",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 BASE_FEATURE(kStructuredMetrics,
              "EnableStructuredMetrics",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/metrics/metrics_features.h b/components/metrics/metrics_features.h
index 5c558c9..da80eee6 100644
--- a/components/metrics/metrics_features.h
+++ b/components/metrics/metrics_features.h
@@ -17,10 +17,6 @@
 // service can close a log starting from when the first log is opened.
 BASE_DECLARE_FEATURE(kMetricsServiceAllowEarlyLogClose);
 
-// Determines whether logs stored in Local State are cleared when the Chrome
-// install is detected as cloned.
-BASE_DECLARE_FEATURE(kMetricsClearLogsOnClonedInstall);
-
 // This can be used to disable structured metrics as a whole.
 BASE_DECLARE_FEATURE(kStructuredMetrics);
 
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc
index 34c55d4a..dca9c9d 100644
--- a/components/metrics/metrics_service.cc
+++ b/components/metrics/metrics_service.cc
@@ -369,13 +369,10 @@
     logs_event_manager_.AddObserver(logs_event_observer_.get());
   }
 
-  if (base::FeatureList::IsEnabled(
-          features::kMetricsClearLogsOnClonedInstall)) {
-    cloned_install_subscription_ =
-        state_manager->AddOnClonedInstallDetectedCallback(
-            base::BindOnce(&MetricsService::OnClonedInstallDetected,
-                           self_ptr_factory_.GetWeakPtr()));
-  }
+  cloned_install_subscription_ =
+      state_manager->AddOnClonedInstallDetectedCallback(
+          base::BindOnce(&MetricsService::OnClonedInstallDetected,
+                         self_ptr_factory_.GetWeakPtr()));
 
   RegisterMetricsProvider(
       std::make_unique<StabilityMetricsProvider>(local_state_));
diff --git a/components/metrics/metrics_service_unittest.cc b/components/metrics/metrics_service_unittest.cc
index 9cc1635b..c211c5f 100644
--- a/components/metrics/metrics_service_unittest.cc
+++ b/components/metrics/metrics_service_unittest.cc
@@ -345,28 +345,18 @@
 
 class MetricsServiceTestWithFeatures
     : public MetricsServiceTest,
-      public ::testing::WithParamInterface<std::tuple<bool, bool>> {
+      public ::testing::WithParamInterface<std::tuple<bool>> {
  public:
   MetricsServiceTestWithFeatures() = default;
   ~MetricsServiceTestWithFeatures() override = default;
 
-  bool ShouldClearLogsOnClonedInstall() { return std::get<0>(GetParam()); }
-
-  bool ShouldSnapshotInBg() { return std::get<1>(GetParam()); }
+  bool ShouldSnapshotInBg() { return std::get<0>(GetParam()); }
 
   void SetUp() override {
     MetricsServiceTest::SetUp();
     std::vector<base::test::FeatureRefAndParams> enabled_features;
     std::vector<base::test::FeatureRef> disabled_features;
 
-    if (ShouldClearLogsOnClonedInstall()) {
-      enabled_features.emplace_back(features::kMetricsClearLogsOnClonedInstall,
-                                    base::FieldTrialParams());
-    } else {
-      disabled_features.emplace_back(
-          features::kMetricsClearLogsOnClonedInstall);
-    }
-
     if (ShouldSnapshotInBg()) {
       enabled_features.emplace_back(features::kMetricsServiceDeltaSnapshotInBg,
                                     base::FieldTrialParams());
@@ -391,28 +381,18 @@
 class MetricsServiceTestWithStartupVisibility
     : public MetricsServiceTest,
       public ::testing::WithParamInterface<
-          std::tuple<StartupVisibilityTestParams, bool, bool>> {
+          std::tuple<StartupVisibilityTestParams, bool>> {
  public:
   MetricsServiceTestWithStartupVisibility() = default;
   ~MetricsServiceTestWithStartupVisibility() override = default;
 
-  bool ShouldClearLogsOnClonedInstall() { return std::get<1>(GetParam()); }
-
-  bool ShouldSnapshotInBg() { return std::get<2>(GetParam()); }
+  bool ShouldSnapshotInBg() { return std::get<1>(GetParam()); }
 
   void SetUp() override {
     MetricsServiceTest::SetUp();
     std::vector<base::test::FeatureRefAndParams> enabled_features;
     std::vector<base::test::FeatureRef> disabled_features;
 
-    if (ShouldClearLogsOnClonedInstall()) {
-      enabled_features.emplace_back(features::kMetricsClearLogsOnClonedInstall,
-                                    base::FieldTrialParams());
-    } else {
-      disabled_features.emplace_back(
-          features::kMetricsClearLogsOnClonedInstall);
-    }
-
     if (ShouldSnapshotInBg()) {
       enabled_features.emplace_back(features::kMetricsServiceDeltaSnapshotInBg,
                                     base::FieldTrialParams());
@@ -470,8 +450,7 @@
 
 INSTANTIATE_TEST_SUITE_P(All,
                          MetricsServiceTestWithFeatures,
-                         ::testing::Combine(::testing::Bool(),
-                                            ::testing::Bool()));
+                         ::testing::Combine(::testing::Bool()));
 
 TEST_P(MetricsServiceTestWithFeatures, RecordId) {
   EnableMetricsReporting();
@@ -792,7 +771,6 @@
             StartupVisibilityTestParams{
                 .startup_visibility = StartupVisibility::kForeground,
                 .expected_beacon_value = false}),
-        ::testing::Bool(),
         ::testing::Bool()));
 
 TEST_P(MetricsServiceTestWithStartupVisibility, InitialStabilityLogAfterCrash) {
@@ -1499,15 +1477,9 @@
   // Save a machine id that will cause a clone to be detected.
   GetLocalState()->SetInteger(prefs::kMetricsMachineId, kTestHashedId + 1);
   cloned_install_detector->SaveMachineId(GetLocalState(), kTestRawId);
-  // Verify that the logs were purged if the |kMetricsClearLogsOnClonedInstall|
-  // feature is enabled.
-  if (ShouldClearLogsOnClonedInstall()) {
-    EXPECT_FALSE(test_log_store->has_staged_log());
-    EXPECT_FALSE(test_log_store->has_unsent_logs());
-  } else {
-    EXPECT_TRUE(test_log_store->has_staged_log());
-    EXPECT_TRUE(test_log_store->has_unsent_logs());
-  }
+  // Verify that the logs were purged.
+  EXPECT_FALSE(test_log_store->has_staged_log());
+  EXPECT_FALSE(test_log_store->has_unsent_logs());
 }
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/components/omnibox/browser/actions/omnibox_action_factory_android.cc b/components/omnibox/browser/actions/omnibox_action_factory_android.cc
index cd52c5d8..a98b3bf 100644
--- a/components/omnibox/browser/actions/omnibox_action_factory_android.cc
+++ b/components/omnibox/browser/actions/omnibox_action_factory_android.cc
@@ -109,7 +109,6 @@
     return {};
   }
 
-  return base::android::ToTypedJavaArrayOfObjects(
-      env, jactions_vec,
-      base::android::ScopedJavaLocalRef<jclass>(g_java_omnibox_action.Get()));
+  return base::android::ToTypedJavaArrayOfObjects(env, jactions_vec,
+                                                  g_java_omnibox_action.Get());
 }
diff --git a/components/omnibox/browser/history_quick_provider_unittest.cc b/components/omnibox/browser/history_quick_provider_unittest.cc
index 484bc498..153f3a1 100644
--- a/components/omnibox/browser/history_quick_provider_unittest.cc
+++ b/components/omnibox/browser/history_quick_provider_unittest.cc
@@ -584,8 +584,8 @@
   // Verify that contents_class divides the string in the right places.
   // [22, 24) is the "第二".  All the other pairs are the "e3".
   ACMatchClassifications contents_class(ac_matches()[0].contents_class);
-  size_t expected_offsets[] = {0,  22, 24, 31, 33, 40, 42, 49,
-                               51, 58, 60, 67, 69, 76, 78};
+  size_t expected_offsets[] = {0,  22, 24, 31, 33, 40, 42, 49, 51, 58,
+                               60, 67, 69, 76, 78, 85, 86, 94, 95};
   // ScoredHistoryMatch may not highlight all the occurrences of these terms
   // because it only highlights terms at word breaks, and it only stores word
   // breaks up to some specified number of characters (50 at the time of this
diff --git a/components/omnibox/browser/in_memory_url_index_types.cc b/components/omnibox/browser/in_memory_url_index_types.cc
index 44e34554..f5aa7e4 100644
--- a/components/omnibox/browser/in_memory_url_index_types.cc
+++ b/components/omnibox/browser/in_memory_url_index_types.cc
@@ -9,7 +9,6 @@
 #include <numeric>
 #include <set>
 
-#include "base/i18n/break_iterator.h"
 #include "base/i18n/case_conversion.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/escape.h"
@@ -142,8 +141,7 @@
     word_starts->clear();
 
   String16Vector words;
-  TailoredWordBreakIterator iter(cleaned_uni_string,
-                                 base::i18n::BreakIterator::BREAK_WORD);
+  TailoredWordBreakIterator iter(cleaned_uni_string);
   if (!iter.Init())
     return words;
   while (iter.Advance()) {
diff --git a/components/omnibox/browser/in_memory_url_index_types_unittest.cc b/components/omnibox/browser/in_memory_url_index_types_unittest.cc
index c3b4f206..c39dd8440 100644
--- a/components/omnibox/browser/in_memory_url_index_types_unittest.cc
+++ b/components/omnibox/browser/in_memory_url_index_types_unittest.cc
@@ -28,8 +28,7 @@
   return true;
 }
 
-class InMemoryURLIndexTypesTest : public testing::Test {
-};
+class InMemoryURLIndexTypesTest : public testing::Test {};
 
 TEST_F(InMemoryURLIndexTypesTest, StaticFunctions) {
   // Test String16VectorFromString16
@@ -55,9 +54,9 @@
       u" funky%20string-with=@strange   sequences, intended(to exceed)");
   WordStarts actual_starts_b;
   string_vec = String16VectorFromString16(string_b, &actual_starts_b);
-  ASSERT_EQ(8U, string_vec.size());
+  ASSERT_EQ(9U, string_vec.size());
   // Note that we stop collecting words and word starts at kMaxSignificantChars.
-  size_t expected_starts_b[] = {1, 7, 16, 22, 32, 43, 52, 55};
+  size_t expected_starts_b[] = {1, 7, 9, 16, 22, 32, 43, 52, 55};
   EXPECT_TRUE(IntArraysEqual(expected_starts_b, std::size(expected_starts_b),
                              actual_starts_b));
 
@@ -133,7 +132,7 @@
   // Test MatchTermInString
   TermMatches matches_g =
       MatchTermInString(u"x", u"axbxcxdxex fxgx/hxixjx.kx", 123);
-  const size_t expected_offsets[] = { 1, 3, 5, 7, 9, 12, 14, 17, 19, 21, 24 };
+  const size_t expected_offsets[] = {1, 3, 5, 7, 9, 12, 14, 17, 19, 21, 24};
   ASSERT_EQ(std::size(expected_offsets), matches_g.size());
   for (size_t i = 0; i < std::size(expected_offsets); ++i)
     EXPECT_EQ(expected_offsets[i], matches_g[i].offset);
diff --git a/components/omnibox/browser/in_memory_url_index_unittest.cc b/components/omnibox/browser/in_memory_url_index_unittest.cc
index 871162c8..33457fe 100644
--- a/components/omnibox/browser/in_memory_url_index_unittest.cc
+++ b/components/omnibox/browser/in_memory_url_index_unittest.cc
@@ -427,7 +427,7 @@
   // history_info_map_ should have the same number of items as were filtered.
   EXPECT_EQ(1U, private_data.history_info_map_.size());
   EXPECT_EQ(35U, private_data.char_word_map_.size());
-  EXPECT_EQ(17U, private_data.word_map_.size());
+  EXPECT_EQ(19U, private_data.word_map_.size());
 }
 
 TEST_F(InMemoryURLIndexTest, HiddenURLRowsAreIgnored) {
diff --git a/components/omnibox/browser/shortcuts_backend.cc b/components/omnibox/browser/shortcuts_backend.cc
index 9951e0a..290f4aec 100644
--- a/components/omnibox/browser/shortcuts_backend.cc
+++ b/components/omnibox/browser/shortcuts_backend.cc
@@ -13,7 +13,6 @@
 #include <utility>
 
 #include "base/functional/bind.h"
-#include "base/i18n/break_iterator.h"
 #include "base/i18n/case_conversion.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/ranges/algorithm.h"
@@ -147,8 +146,7 @@
     // Cut off the common prefix.
     const auto cut_match_text = match_text.substr(trimmed_lower_text.length());
     // Find the 1st word of the cut `match_text`.
-    TailoredWordBreakIterator iter(cut_match_text,
-                                   base::i18n::BreakIterator::BREAK_WORD);
+    TailoredWordBreakIterator iter(cut_match_text);
     // Append that word to the text.
     if (iter.Init() && iter.Advance() && iter.IsWord())
       return base::StrCat({trimmed_text, iter.GetString()});
diff --git a/components/omnibox/browser/shortcuts_backend_unittest.cc b/components/omnibox/browser/shortcuts_backend_unittest.cc
index d6cfd6c..2d0043c 100644
--- a/components/omnibox/browser/shortcuts_backend_unittest.cc
+++ b/components/omnibox/browser/shortcuts_backend_unittest.cc
@@ -447,9 +447,9 @@
   InitBackend();
 
   AutocompleteMatch match;
-  match.destination_url = GURL("https://www.host-shared2.com/path");
+  match.destination_url = GURL("https://www.host-sharedB.com/path");
   match.description = u"https://www.description.com";
-  match.contents = u"a an app apple i it word ZaZaaZZ symbols(╯°□°)╯ shared1";
+  match.contents = u"a an app apple i it word ZaZaaZZ symbols(╯°□°)╯ sharedA";
   match.contents_class.emplace_back(0, 0);
   match.description_class.emplace_back(0, 0);
 
@@ -499,7 +499,7 @@
 
   // Should prefer expanding to words in the `contents`.
   backend()->AddOrUpdateShortcut(u"shar", match);
-  EXPECT_THAT(ShortcutsMapTexts(), testing::ElementsAre(u"shared1"));
+  EXPECT_THAT(ShortcutsMapTexts(), testing::ElementsAre(u"sharedA"));
   ClearShortcutsMap();
 
   // When updating, should expand the last word after appending up to 3 chars.
@@ -608,28 +608,28 @@
 
   // When `text` does prefix `match_text`, should expand to the next word in
   // `match_text` instead of the 1st matching word.
-  test("x", "x1 x2", "x1");
-  test("x1 x", "x1 x2", "x1 x2");
+  test("x", "xA xB", "xA");
+  test("xA x", "xA xB", "xA xB");
 
   // When `text` doesn't prefix `match_text`, should expand to the 1st matching
   // word in `match_text`.
-  test("x2 x", "x1 x2", "x2 x1");
+  test("xB x", "xA xB", "xB xA");
   // Even if that produces repeated words. (It'd be too complicated to avoid
   // this without introducing even greater edge cases).
-  test("x1 x", "x1 y x2", "x1 x1");
+  test("xA x", "xA y xB", "xA xA");
 
   // When prefix matching, should use the next word even if its short.
-  test("x1 x", "x1 y x2 xyz", "x1 xyz");
+  test("xA x", "xA y xB xyz", "xA xyz");
   // When not prefix matching, should use the 1st word at least 3 chars long if
   // available.
-  test("x1 x", "x1 x2 xyz", "x1 x2");
+  test("xA x", "xA xB xyz", "xA xB");
 
   // Both prefix and non prefix matching should handle trailing whitespace.
   // Trailing whitespace should not prompt expansion to the next `match_text`.
-  test("x1 ", "x1 x2", "x1");
+  test("xA ", "xA xB", "xA");
   // Trailing whitespace should not prevent expansion of the last `text` word.
-  test("x1 xy ", "x1 xyz", "x1 xyz");
-  test("x1 xyz ", "x1 xyz", "x1 xyz");
+  test("xA xy ", "xA xyz", "xA xyz");
+  test("xA xyz ", "xA xyz", "xA xyz");
 }
 
 TEST_F(ShortcutsBackendTest, AddOrUpdateShortcut_Expanding_Case) {
diff --git a/components/omnibox/browser/tailored_word_break_iterator.cc b/components/omnibox/browser/tailored_word_break_iterator.cc
index 7430b6f..fc8854a 100644
--- a/components/omnibox/browser/tailored_word_break_iterator.cc
+++ b/components/omnibox/browser/tailored_word_break_iterator.cc
@@ -4,54 +4,55 @@
 
 #include "components/omnibox/browser/tailored_word_break_iterator.h"
 
-#include "base/strings/string_piece.h"
+#include <string>
 
-namespace {
-constexpr char16_t kUnderscore = '_';
-}  // namespace
+#include "base/i18n/break_iterator.h"
+#include "base/strings/string_piece.h"
 
 using base::i18n::BreakIterator;
 
 TailoredWordBreakIterator::TailoredWordBreakIterator(
-    const base::StringPiece16& str,
-    BreakIterator::BreakType break_type)
-    : BreakIterator(str, break_type), prev_(0), pos_(0) {
-  DCHECK_EQ(BreakIterator::BREAK_WORD, break_type);
-}
+    const base::StringPiece16& str)
+    : BreakIterator(str, BreakIterator::BREAK_WORD),
+      prev_(0),
+      pos_(0),
+      word_breaks_{u"0123456789"},
+      non_word_breaks_{u"_"},
+      all_breaks_{word_breaks_ + non_word_breaks_} {};
 
 TailoredWordBreakIterator::~TailoredWordBreakIterator() {}
 
 bool TailoredWordBreakIterator::Advance() {
-  if (HasUnderscoreWord() && AdvanceInUnderscoreWord()) {
+  if (HasSpecialWord() && AdvanceInSpecialWord()) {
     return true;
   }
   if (!BreakIterator::Advance())
     return false;
   prev_ = 0;
   pos_ = 0;
-  underscore_word_ = base::StringPiece16();
+  special_word_ = base::StringPiece16();
   if (!IsWord())
     return true;
   base::StringPiece16 word = BreakIterator::GetStringPiece();
-  if (word.find(kUnderscore) != base::StringPiece16::npos) {
-    underscore_word_ = word;
-    AdvanceInUnderscoreWord();
+  if (word.find_first_of(all_breaks_) != base::StringPiece16::npos) {
+    special_word_ = word;
+    AdvanceInSpecialWord();
   }
   return true;
 }
 
 bool TailoredWordBreakIterator::IsWord() const {
-  if (HasUnderscoreWord()) {
+  if (HasSpecialWord()) {
     base::StringPiece16 word = GetStringPiece();
     if (!word.empty())
-      return word[0] != kUnderscore;
+      return non_word_breaks_.find(word[0]) == std::u16string::npos;
   }
   return BreakIterator::IsWord();
 }
 
 base::StringPiece16 TailoredWordBreakIterator::GetStringPiece() const {
-  if (!underscore_word_.empty())
-    return underscore_word_.substr(prev_, pos_ - prev_);
+  if (!special_word_.empty())
+    return special_word_.substr(prev_, pos_ - prev_);
   return BreakIterator::GetStringPiece();
 }
 
@@ -67,33 +68,40 @@
   return BreakIterator::pos() + pos_;
 }
 
-bool TailoredWordBreakIterator::HasUnderscoreWord() const {
-  return !underscore_word_.empty();
+bool TailoredWordBreakIterator::HasSpecialWord() const {
+  return !special_word_.empty();
 }
 
-bool TailoredWordBreakIterator::AdvanceInUnderscoreWord() {
-  DCHECK(HasUnderscoreWord());
-  // If we've finished with the underscore word we're processing, return false
-  // and let the caller call advance on the outer BreakIterator.
-  if (pos_ == underscore_word_.size()) {
+bool TailoredWordBreakIterator::AdvanceInSpecialWord() {
+  DCHECK(HasSpecialWord());
+  // If we've finished with the special word we're processing, return false
+  // and let the caller call advance on the outer `BreakIterator`.
+  if (pos_ == special_word_.size()) {
     prev_ = 0;
     pos_ = 0;
-    underscore_word_ = base::StringPiece16();
+    special_word_ = base::StringPiece16();
     return false;
   }
 
-  std::size_t next_pos = underscore_word_.find(kUnderscore, pos_);
   prev_ = pos_;
-  if (next_pos == base::StringPiece16::npos) {
-    pos_ = underscore_word_.size();
-    return true;
-  }
-  // If an underscore is found at the current position, index moves to next
-  // char.
-  if (pos_ == next_pos)
-    pos_ += 1;
-  else
-    pos_ = next_pos;
+  auto c = special_word_[pos_];
 
+  if (non_word_breaks_.find(c) != std::u16string::npos) {
+    // If at a non-word word-break (e.g. '_'), advance 1 char. Don't advance to
+    // the end of the word-break series to be consistent with how
+    // `BreakIterator` handles other symbols.
+    pos_++;
+
+  } else if (word_breaks_.find(c) != std::u16string::npos) {
+    // If at a word word-break (e.g. numbers), advance to the end of the series.
+    pos_ = special_word_.find_first_not_of(word_breaks_, pos_ + 1);
+
+  } else {
+    // Otherwise, at a non-word-break, advance to the next word-break.
+    pos_ = special_word_.find_first_of(all_breaks_, pos_ + 1);
+  }
+
+  if (pos_ == std::u16string::npos)
+    pos_ = special_word_.size();
   return true;
 }
diff --git a/components/omnibox/browser/tailored_word_break_iterator.h b/components/omnibox/browser/tailored_word_break_iterator.h
index 6257942..b0a44b0 100644
--- a/components/omnibox/browser/tailored_word_break_iterator.h
+++ b/components/omnibox/browser/tailored_word_break_iterator.h
@@ -5,14 +5,19 @@
 #ifndef COMPONENTS_OMNIBOX_BROWSER_TAILORED_WORD_BREAK_ITERATOR_H_
 #define COMPONENTS_OMNIBOX_BROWSER_TAILORED_WORD_BREAK_ITERATOR_H_
 
-#include "base/i18n/break_iterator.h"
+#include <string>
 
-// Breaks on an underscore. Otherwise, it behaves like its parent class with
-// BreakIterator::BREAK_WORD.
+#include "base/i18n/break_iterator.h"
+#include "base/strings/string_piece_forward.h"
+
+// Breaks on an underscore and numbers. Otherwise, it behaves like its parent
+// class with `BreakIterator::BREAK_WORD`.
+// E.g. 'Viktor Ambartsumian_is__anAwesome99_99Astrophysicist!!' is broken into:
+// [Viktor, <space>, Ambartsumian, _, is, _, _, anAwesome, 99, _, 99,
+//  Astrophysicist, !, !].
 class TailoredWordBreakIterator : public base::i18n::BreakIterator {
  public:
-  TailoredWordBreakIterator(const base::StringPiece16& str,
-                            base::i18n::BreakIterator::BreakType break_type);
+  explicit TailoredWordBreakIterator(const base::StringPiece16& str);
 
   ~TailoredWordBreakIterator();
   TailoredWordBreakIterator(const TailoredWordBreakIterator&) = delete;
@@ -21,26 +26,39 @@
 
   bool Advance();
   bool IsWord() const;
-  // Returns characters between |prev_| and |pos_| if |underscore_word_| is not
-  // empty. Otherwise returns the normal BreakIterator-determined current word.
+  // Returns characters between `prev_` and `pos_` if `special_word_` is not
+  // empty. Otherwise returns the normal `BreakIterator`-determined current
+  // word.
   base::StringPiece16 GetStringPiece() const;
   std::u16string GetString() const;
   size_t prev() const;
   size_t pos() const;
 
  private:
-  // Returns true if we processing a word with underscores (i.e., |pos| points
-  // to a valid position in |underscore_word_|).
-  bool HasUnderscoreWord() const;
-  // Updates |prev_| and |pos_| considering underscore. Returns true if we
-  // successfully advanced within the underscore word, and returns false if
-  // we've exhausted the underscore word, and we should resume the main word
-  // traversal. This is similar to the semantics of `BreakIterator::Advance()`.
-  bool AdvanceInUnderscoreWord();
-  // |prev_| and |pos_| are indices to |underscore_word_|.
+  // Returns true if processing a word with underscores or numbers (i.e., `pos`
+  // points to a valid position in `special_word_`).
+  bool HasSpecialWord() const;
+
+  // Updates `prev_` and `pos_` considering underscores and numbers. Returns
+  // true if it successfully advanced within `special_word_`; returns false if
+  // it exhausts the word and should resume the main word traversal. This is
+  // similar to the semantics of `BreakIterator::Advance()`.
+  bool AdvanceInSpecialWord();
+
+  // `prev_` and `pos_` are indices to `special_word_`.
   size_t prev_, pos_;
-  // Set if BreakIterator::GetStringPiece() contains '_', otherwise it's empty.
-  base::StringPiece16 underscore_word_;
+  // Set if `BreakIterator::GetStringPiece()` contains '_' or numbers, otherwise
+  // it's empty.
+  base::StringPiece16 special_word_;
+
+  // The additional chars to break on that aren't broken on by `BreakIterator`.
+  // Subset of `all_breaks_` that return true from `IsWord()` (e.g. numbers).
+  const std::u16string word_breaks_;
+  // Subset of `all_breaks_` that return false from `IsWord()` (e.g.
+  // underscore).
+  const std::u16string non_word_breaks_;
+  // Union of `word_breaks_` & `word_breaks_` (e.g. numbers & underscore).
+  const std::u16string all_breaks_;
 };
 
 #endif  // COMPONENTS_OMNIBOX_BROWSER_TAILORED_WORD_BREAK_ITERATOR_H_
diff --git a/components/omnibox/browser/tailored_word_break_iterator_unittest.cc b/components/omnibox/browser/tailored_word_break_iterator_unittest.cc
index 57b42b2f..f226d1b 100644
--- a/components/omnibox/browser/tailored_word_break_iterator_unittest.cc
+++ b/components/omnibox/browser/tailored_word_break_iterator_unittest.cc
@@ -4,72 +4,153 @@
 
 #include <stddef.h>
 
+#include <string>
+#include <vector>
+
 #include "base/i18n/break_iterator.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/omnibox/browser/tailored_word_break_iterator.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-TEST(TailoredWordBreakIterator, BreakWord) {
-  std::u16string str(u"_foo_bar!_\npouet_boom");
-  TailoredWordBreakIterator iter(str, TailoredWordBreakIterator::BREAK_WORD);
+namespace {
+struct Piece {
+  std::u16string string;
+  bool is_word;
+};
+
+void VerifyBreaks(std::u16string str, std::vector<Piece> expected_pieces) {
+  TailoredWordBreakIterator iter(str);
   ASSERT_TRUE(iter.Init());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"_", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_TRUE(iter.IsWord());
-  EXPECT_EQ(u"foo", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"_", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_TRUE(iter.IsWord());
-  EXPECT_EQ(u"bar", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"!", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"_", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"\n", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_TRUE(iter.IsWord());
-  EXPECT_EQ(u"pouet", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"_", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_TRUE(iter.IsWord());
-  EXPECT_EQ(u"boom", iter.GetString());
-  EXPECT_FALSE(iter.Advance());
+
+  for (size_t i = 0; i < expected_pieces.size(); ++i) {
+    ASSERT_TRUE(iter.Advance()) << base::StringPrintf(
+        "Expected %zu pieces; found %zu pieces.\n", expected_pieces.size(), i);
+    EXPECT_TRUE(iter.IsWord() == expected_pieces[i].is_word &&
+                iter.GetString() == expected_pieces[i].string)
+        << base::StringPrintf(
+               "Expected {%s, %d}; found {%s, %d}.\n",
+               base::UTF16ToUTF8(expected_pieces[i].string).c_str(),
+               expected_pieces[i].is_word,
+               base::UTF16ToUTF8(iter.GetString()).c_str(), iter.IsWord());
+  }
+
+  iter.Advance();
+  ASSERT_EQ(iter.pos(), base::i18n::BreakIterator::npos) << base::StringPrintf(
+      "Expected %zu pieces; found more pieces; found {%s, %d}.\n",
+      expected_pieces.size(), base::UTF16ToUTF8(iter.GetString()).c_str(),
+      iter.IsWord());
   EXPECT_FALSE(iter.IsWord());
   EXPECT_FALSE(iter.Advance());
   EXPECT_FALSE(iter.IsWord());
 }
+}  // namespace
+
+TEST(TailoredWordBreakIterator, BreakWord) {
+  VerifyBreaks(u"_foo_bar!_\npouet_boom", {
+                                              {u"_", false},
+                                              {u"foo", true},
+                                              {u"_", false},
+                                              {u"bar", true},
+                                              {u"!", false},
+                                              {u"_", false},
+                                              {u"\n", false},
+                                              {u"pouet", true},
+                                              {u"_", false},
+                                              {u"boom", true},
+                                          });
+}
 
 TEST(TailoredWordBreakIterator, TrailingUnderscore) {
-  std::u16string str(u"_foo_bar_");
-  TailoredWordBreakIterator iter(str, TailoredWordBreakIterator::BREAK_WORD);
-  ASSERT_TRUE(iter.Init());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"_", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_TRUE(iter.IsWord());
-  EXPECT_EQ(u"foo", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"_", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_TRUE(iter.IsWord());
-  EXPECT_EQ(u"bar", iter.GetString());
-  EXPECT_TRUE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_EQ(u"_", iter.GetString());
-  EXPECT_FALSE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
-  EXPECT_FALSE(iter.Advance());
-  EXPECT_FALSE(iter.IsWord());
+  VerifyBreaks(u"_foo_bar_", {
+                                 {u"_", false},
+                                 {u"foo", true},
+                                 {u"_", false},
+                                 {u"bar", true},
+                                 {u"_", false},
+                             });
+}
+
+TEST(TailoredWordBreakIterator, RepeatingUnderscore) {
+  VerifyBreaks(u"Viktor...Ambartsumian", {
+                                             {u"Viktor", true},
+                                             {u".", false},
+                                             {u".", false},
+                                             {u".", false},
+                                             {u"Ambartsumian", true},
+                                         });
+
+  VerifyBreaks(u"Viktor___Ambartsumian", {
+                                             {u"Viktor", true},
+                                             {u"_", false},
+                                             {u"_", false},
+                                             {u"_", false},
+                                             {u"Ambartsumian", true},
+                                         });
+
+  VerifyBreaks(u"Viktor_..///.__Ambartsumian", {
+                                                   {u"Viktor", true},
+                                                   {u"_", false},
+                                                   {u".", false},
+                                                   {u".", false},
+                                                   {u"/", false},
+                                                   {u"/", false},
+                                                   {u"/", false},
+                                                   {u".", false},
+                                                   {u"_", false},
+                                                   {u"_", false},
+                                                   {u"Ambartsumian", true},
+                                               });
+}
+
+TEST(TailoredWordBreakIterator, Numerics) {
+  VerifyBreaks(u"chr0m3 15 aw350m3", {
+                                         {u"chr", true},
+                                         {u"0", true},
+                                         {u"m", true},
+                                         {u"3", true},
+                                         {u" ", false},
+                                         {u"15", true},
+                                         {u" ", false},
+                                         {u"aw", true},
+                                         {u"350", true},
+                                         {u"m", true},
+                                         {u"3", true},
+                                     });
+}
+
+TEST(TailoredWordBreakIterator, NumericsAndUnderscores) {
+  VerifyBreaks(u"chr0m3__15__aw350m3", {
+                                           {u"chr", true},
+                                           {u"0", true},
+                                           {u"m", true},
+                                           {u"3", true},
+                                           {u"_", false},
+                                           {u"_", false},
+                                           {u"15", true},
+                                           {u"_", false},
+                                           {u"_", false},
+                                           {u"aw", true},
+                                           {u"350", true},
+                                           {u"m", true},
+                                           {u"3", true},
+                                       });
+
+  VerifyBreaks(u"Viktor Ambartsumian_is__anAwesome99_99Astrophysicist!!",
+               {
+                   {u"Viktor", true},
+                   {u" ", false},
+                   {u"Ambartsumian", true},
+                   {u"_", false},
+                   {u"is", true},
+                   {u"_", false},
+                   {u"_", false},
+                   {u"anAwesome", true},
+                   {u"99", true},
+                   {u"_", false},
+                   {u"99", true},
+                   {u"Astrophysicist", true},
+                   {u"!", false},
+                   {u"!", false},
+               });
 }
diff --git a/components/omnibox/browser/url_index_private_data.cc b/components/omnibox/browser/url_index_private_data.cc
index 62440f3..2c49bcb7 100644
--- a/components/omnibox/browser/url_index_private_data.cc
+++ b/components/omnibox/browser/url_index_private_data.cc
@@ -18,7 +18,6 @@
 #include "base/containers/flat_set.h"
 #include "base/containers/stack.h"
 #include "base/feature_list.h"
-#include "base/i18n/break_iterator.h"
 #include "base/i18n/case_conversion.h"
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/histogram_macros.h"
@@ -727,8 +726,7 @@
   // starts at offset 1.
   lower_terms_to_word_starts_offsets->resize(lower_terms.size(), 0u);
   for (size_t i = 0; i < lower_terms.size(); ++i) {
-    TailoredWordBreakIterator iter(lower_terms[i],
-                                   base::i18n::BreakIterator::BREAK_WORD);
+    TailoredWordBreakIterator iter(lower_terms[i]);
     // If the iterator doesn't work, assume an offset of 0.
     if (!iter.Init())
       continue;
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp
index a785fbe..9ea8fdba 100644
--- a/components/page_info_strings.grdp
+++ b/components/page_info_strings.grdp
@@ -389,7 +389,7 @@
       Can ask to track your camera position
     </message>
     <message name="IDS_PAGE_INFO_STATE_TEXT_AUTO_PICTURE_IN_PICTURE_ASK" desc="The Page Info permission subpage and the main page info page contain a label which shows the state of the site permission. This is the text shown if the auto picture-in-picture permission is in the ask state and the site can prompt the user to ask if they want to allow the site to automatically open picture-in-picture windows..">
-      Can ask to automatically open picture-in-picture windows
+      Can ask to enter picture-in-picture
     </message>
     <message name="IDS_PAGE_INFO_STATE_TEXT_AUTOMATIC_DOWNLOADS_ASK" desc="The Page Info permission subpage and the main page info page contain a label which shows the state of the site permission. This is the text shown if the automatic download permission is in the ask state and the site can prompt the user to ask if they allow the site to automatically download multiple files.">
       Can ask to automatically download multiple files
diff --git a/components/page_info_strings_grdp/IDS_PAGE_INFO_STATE_TEXT_AUTO_PICTURE_IN_PICTURE_ASK.png.sha1 b/components/page_info_strings_grdp/IDS_PAGE_INFO_STATE_TEXT_AUTO_PICTURE_IN_PICTURE_ASK.png.sha1
index 2ac7f93..d64eb84a 100644
--- a/components/page_info_strings_grdp/IDS_PAGE_INFO_STATE_TEXT_AUTO_PICTURE_IN_PICTURE_ASK.png.sha1
+++ b/components/page_info_strings_grdp/IDS_PAGE_INFO_STATE_TEXT_AUTO_PICTURE_IN_PICTURE_ASK.png.sha1
@@ -1 +1 @@
-c19c21b1dc5b9de45f3fc861a348d4d64a091f6b
\ No newline at end of file
+d1af8839cd13744c365b2e79c1e6d901fbdf4997
\ No newline at end of file
diff --git a/components/performance_manager/resource_attribution/cpu_measurement_monitor.cc b/components/performance_manager/resource_attribution/cpu_measurement_monitor.cc
index 708a16ba..635be88 100644
--- a/components/performance_manager/resource_attribution/cpu_measurement_monitor.cc
+++ b/components/performance_manager/resource_attribution/cpu_measurement_monitor.cc
@@ -498,29 +498,15 @@
 
     // Aggregate new frame and worker measurements to pages.
     if (ContextIs<FrameContext>(context)) {
-      // A FrameNode that's being removed` may not be in the registry anymore,
-      // depending on the order OnBeforeFrameNodeRemoved() observers fire.
-      const auto* remove_frame_change =
-          absl::get_if<GraphChangeRemoveFrame>(&graph_change);
       const FrameNode* frame_node =
-          (remove_frame_change &&
-           remove_frame_change->frame_node->GetResourceContext() == context)
-              ? remove_frame_change->frame_node
-              : frame_registry->GetFrameNodeForContext(context);
+          frame_registry->GetFrameNodeForContext(context);
       CHECK(frame_node);
       ApplyOverlappingDelta(
           measurement_results_[frame_node->GetPageNode()->GetResourceContext()],
           delta);
     } else if (ContextIs<WorkerContext>(context)) {
-      // A WorkerNode that's being removed` may not be in the registry anymore,
-      // depending on the order OnBeforeWorkerNodeRemoved() observers fire.
-      const auto* remove_worker_change =
-          absl::get_if<GraphChangeRemoveWorker>(&graph_change);
       const WorkerNode* worker_node =
-          (remove_worker_change &&
-           remove_worker_change->worker_node->GetResourceContext() == context)
-              ? remove_worker_change->worker_node
-              : worker_registry->GetWorkerNodeForContext(context);
+          worker_registry->GetWorkerNodeForContext(context);
       CHECK(worker_node);
       for (const PageNode* page_node :
            GetClientPages(worker_node, graph_change)) {
diff --git a/components/performance_manager/resource_attribution/frame_context_registry_browsertest.cc b/components/performance_manager/resource_attribution/frame_context_registry_browsertest.cc
index 769b8f5..9a4ee21 100644
--- a/components/performance_manager/resource_attribution/frame_context_registry_browsertest.cc
+++ b/components/performance_manager/resource_attribution/frame_context_registry_browsertest.cc
@@ -5,7 +5,9 @@
 #include "components/performance_manager/public/resource_attribution/frame_context_registry.h"
 
 #include "base/memory/weak_ptr.h"
+#include "base/test/bind.h"
 #include "components/performance_manager/public/graph/frame_node.h"
+#include "components/performance_manager/public/graph/graph.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "components/performance_manager/public/resource_attribution/resource_contexts.h"
 #include "components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.h"
@@ -96,6 +98,31 @@
       });
 }
 
+IN_PROC_BROWSER_TEST_F(FrameContextRegistryTest, OnBeforeFrameNodeRemoved) {
+  CreateNodes();
+
+  auto* rfh = content::RenderFrameHost::FromID(main_frame_id_);
+  ASSERT_TRUE(rfh);
+  absl::optional<FrameContext> frame_context =
+      FrameContextRegistry::ContextForRenderFrameHost(rfh);
+  ASSERT_TRUE(frame_context.has_value());
+
+  RemoveFrameNodeWaiter waiter(
+      PerformanceManager::GetFrameNodeForRenderFrameHost(rfh),
+      base::BindLambdaForTesting([&](const FrameNode* frame_node) {
+        // `frame_node` should still be available from FrameContextRegistry in
+        // OnBeforeFrameNodeRemoved.
+        const auto* registry =
+            FrameContextRegistry::GetFromGraph(frame_node->GetGraph());
+        ASSERT_TRUE(registry);
+        EXPECT_EQ(registry->GetFrameNodeForContext(frame_context.value()),
+                  frame_node);
+      }));
+
+  DeleteNodes();
+  waiter.Wait();
+}
+
 IN_PROC_BROWSER_TEST_F(FrameContextRegistryDisabledTest, UIThreadAccess) {
   CreateNodes();
 
diff --git a/components/performance_manager/resource_attribution/page_context_registry_browsertest.cc b/components/performance_manager/resource_attribution/page_context_registry_browsertest.cc
index 655de960..40e8afc4 100644
--- a/components/performance_manager/resource_attribution/page_context_registry_browsertest.cc
+++ b/components/performance_manager/resource_attribution/page_context_registry_browsertest.cc
@@ -6,7 +6,9 @@
 
 #include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
+#include "base/test/bind.h"
 #include "components/performance_manager/public/graph/frame_node.h"
+#include "components/performance_manager/public/graph/graph.h"
 #include "components/performance_manager/public/graph/page_node.h"
 #include "components/performance_manager/public/graph/process_node.h"
 #include "components/performance_manager/public/performance_manager.h"
@@ -220,6 +222,31 @@
               IsEmpty());
 }
 
+IN_PROC_BROWSER_TEST_F(PageContextRegistryTest, OnBeforePageNodeRemoved) {
+  CreateNodes();
+
+  auto* main_frame = content::RenderFrameHost::FromID(main_frame_id_);
+  ASSERT_TRUE(main_frame);
+  absl::optional<PageContext> page_context =
+      PageContextRegistry::ContextForRenderFrameHost(main_frame);
+  ASSERT_TRUE(page_context.has_value());
+
+  RemovePageNodeWaiter waiter(
+      PerformanceManager::GetPageNodeForRenderFrameHost(main_frame),
+      base::BindLambdaForTesting([&](const PageNode* page_node) {
+        // `page_node` should still be available from PageContextRegistry in
+        // OnBeforePageNodeRemoved.
+        const auto* registry =
+            PageContextRegistry::GetFromGraph(page_node->GetGraph());
+        ASSERT_TRUE(registry);
+        EXPECT_EQ(registry->GetPageNodeForContext(page_context.value()),
+                  page_node);
+      }));
+
+  DeleteNodes();
+  waiter.Wait();
+}
+
 IN_PROC_BROWSER_TEST_F(PageContextRegistryDisabledTest, UIThreadAccess) {
   CreateNodes();
 
diff --git a/components/performance_manager/resource_attribution/process_context_registry_browsertest.cc b/components/performance_manager/resource_attribution/process_context_registry_browsertest.cc
index a5dfbb01..16fc5cd 100644
--- a/components/performance_manager/resource_attribution/process_context_registry_browsertest.cc
+++ b/components/performance_manager/resource_attribution/process_context_registry_browsertest.cc
@@ -8,12 +8,14 @@
 #include <utility>
 #include <vector>
 
+#include "base/functional/bind.h"
 #include "base/memory/weak_ptr.h"
 #include "components/performance_manager/graph/node_base.h"
 #include "components/performance_manager/graph/process_node_impl.h"
 #include "components/performance_manager/performance_manager_impl.h"
 #include "components/performance_manager/public/browser_child_process_host_id.h"
 #include "components/performance_manager/public/browser_child_process_host_proxy.h"
+#include "components/performance_manager/public/graph/graph.h"
 #include "components/performance_manager/public/graph/process_node.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "components/performance_manager/public/render_process_host_id.h"
@@ -364,6 +366,53 @@
       });
 }
 
+IN_PROC_BROWSER_TEST_F(ProcessContextRegistryTest, OnBeforeProcessNodeRemoved) {
+  CreateNodes();
+
+  absl::optional<ProcessContext> browser_process_context =
+      ProcessContextRegistry::BrowserProcessContext();
+  ASSERT_TRUE(browser_process_context.has_value());
+
+  auto* rph =
+      content::RenderProcessHost::FromID(render_process_id_a_.GetUnsafeValue());
+  ASSERT_TRUE(rph);
+  absl::optional<ProcessContext> render_process_context =
+      ProcessContextRegistry::ContextForRenderProcessHost(rph);
+  ASSERT_TRUE(render_process_context.has_value());
+
+  absl::optional<ProcessContext> browser_child_process_context =
+      ProcessContextRegistry::ContextForBrowserChildProcessHost(
+          utility_process_->host());
+  ASSERT_TRUE(browser_child_process_context.has_value());
+
+  auto expect_process_context = [&](const ProcessContext& process_context,
+                                    const ProcessNode* process_node) {
+    // `process_node` should still be available from ProcessContextRegistry
+    // in OnBeforeProcessNodeRemoved.
+    const auto* registry =
+        ProcessContextRegistry::GetFromGraph(process_node->GetGraph());
+    ASSERT_TRUE(registry);
+    EXPECT_EQ(registry->GetProcessNodeForContext(process_context),
+              process_node);
+  };
+
+  RemoveProcessNodeWaiter browser_process_waiter(
+      weak_browser_process_node_,
+      base::BindOnce(expect_process_context, browser_process_context.value()));
+  RemoveProcessNodeWaiter render_process_waiter(
+      PerformanceManager::GetProcessNodeForRenderProcessHost(rph),
+      base::BindOnce(expect_process_context, render_process_context.value()));
+  RemoveProcessNodeWaiter browser_child_process_waiter(
+      weak_utility_process_node_,
+      base::BindOnce(expect_process_context,
+                     browser_child_process_context.value()));
+
+  DeleteNodes();
+  browser_process_waiter.Wait();
+  render_process_waiter.Wait();
+  browser_child_process_waiter.Wait();
+}
+
 IN_PROC_BROWSER_TEST_F(ProcessContextRegistryDisabledTest, UIThreadAccess) {
   CreateNodes();
 
diff --git a/components/performance_manager/resource_attribution/resource_context_registry_storage.cc b/components/performance_manager/resource_attribution/resource_context_registry_storage.cc
index e2609c10..b4fa8c9 100644
--- a/components/performance_manager/resource_attribution/resource_context_registry_storage.cc
+++ b/components/performance_manager/resource_attribution/resource_context_registry_storage.cc
@@ -12,6 +12,10 @@
 #include "base/check_op.h"
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
+#include "components/performance_manager/graph/frame_node_impl.h"
+#include "components/performance_manager/graph/page_node_impl.h"
+#include "components/performance_manager/graph/process_node_impl.h"
+#include "components/performance_manager/graph/worker_node_impl.h"
 #include "components/performance_manager/public/browser_child_process_host_id.h"
 #include "components/performance_manager/public/browser_child_process_host_proxy.h"
 #include "components/performance_manager/public/graph/graph.h"
@@ -31,6 +35,28 @@
 
 namespace performance_manager::resource_attribution {
 
+namespace {
+
+// Helper to return a node from a map of ResourceContext -> WeakPtr, and clear
+// any invalidated WeakPtr from the map.
+template <typename NodeType, typename ContextType>
+const NodeType* GetWeakNodeForContext(
+    const ContextType& context,
+    std::map<ContextType, base::WeakPtr<NodeType>>& weak_nodes_by_context) {
+  const auto it = weak_nodes_by_context.find(context);
+  if (it == weak_nodes_by_context.end()) {
+    return nullptr;
+  }
+  if (!it->second) {
+    // Clear invalidated WeakPtr from map.
+    weak_nodes_by_context.erase(it);
+    return nullptr;
+  }
+  return it->second.get();
+}
+
+}  // namespace
+
 using UIThreadStorage = ResourceContextRegistryStorage::UIThreadStorage;
 
 // Underlying storage for ResourceContext objects, accessible from the UI
@@ -705,29 +731,25 @@
 const FrameNode* ResourceContextRegistryStorage::GetFrameNodeForContext(
     const FrameContext& context) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  const auto it = frame_nodes_by_context_.find(context);
-  return it != frame_nodes_by_context_.end() ? it->second : nullptr;
+  return GetWeakNodeForContext(context, frame_nodes_by_context_);
 }
 
 const PageNode* ResourceContextRegistryStorage::GetPageNodeForContext(
     const PageContext& context) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  const auto it = page_nodes_by_context_.find(context);
-  return it != page_nodes_by_context_.end() ? it->second : nullptr;
+  return GetWeakNodeForContext(context, page_nodes_by_context_);
 }
 
 const ProcessNode* ResourceContextRegistryStorage::GetProcessNodeForContext(
     const ProcessContext& context) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  const auto it = process_nodes_by_context_.find(context);
-  return it != process_nodes_by_context_.end() ? it->second : nullptr;
+  return GetWeakNodeForContext(context, process_nodes_by_context_);
 }
 
 const WorkerNode* ResourceContextRegistryStorage::GetWorkerNodeForContext(
     const WorkerContext& context) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  const auto it = worker_nodes_by_context_.find(context);
-  return it != worker_nodes_by_context_.end() ? it->second : nullptr;
+  return GetWeakNodeForContext(context, worker_nodes_by_context_);
 }
 
 void ResourceContextRegistryStorage::OnFrameNodeAdded(
@@ -745,16 +767,14 @@
                      frame_node->GetRenderFrameHostProxy(),
                      frame_node->IsMainFrame(), frame_node->IsCurrent()));
   const auto [_, inserted] = frame_nodes_by_context_.emplace(
-      frame_node->GetResourceContext(), frame_node);
+      frame_node->GetResourceContext(),
+      FrameNodeImpl::FromNode(frame_node)->GetWeakPtr());
   CHECK(inserted);
 }
 
 void ResourceContextRegistryStorage::OnBeforeFrameNodeRemoved(
     const FrameNode* frame_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  const size_t erased =
-      frame_nodes_by_context_.erase(frame_node->GetResourceContext());
-  CHECK_EQ(erased, 1u);
   CHECK(ui_thread_storage_);
   // Unretained is safe because `ui_thread_storage_` is passed to the UI
   // thread to delete.
@@ -765,6 +785,9 @@
                                 frame_node->GetPageNode()->GetResourceContext(),
                                 frame_node->GetRenderFrameHostProxy(),
                                 frame_node->IsMainFrame()));
+  // Leave the WeakPtr to `frame_node` in `frame_nodes_by_context_` so it can
+  // still be resolved until all OnBeforeFrameNodeRemoved() notifications are
+  // done. At that point the WeakPtr will be invalidated.
 }
 
 void ResourceContextRegistryStorage::OnIsCurrentChanged(
@@ -788,7 +811,8 @@
     const PageNode* page_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const auto [_, inserted] = page_nodes_by_context_.emplace(
-      page_node->GetResourceContext(), page_node);
+      page_node->GetResourceContext(),
+      PageNodeImpl::FromNode(page_node)->GetWeakPtr());
   CHECK(inserted);
   CHECK(ui_thread_storage_);
   // Unretained is safe because `ui_thread_storage_` is deleted on the UI
@@ -803,9 +827,6 @@
 void ResourceContextRegistryStorage::OnBeforePageNodeRemoved(
     const PageNode* page_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  const size_t erased =
-      page_nodes_by_context_.erase(page_node->GetResourceContext());
-  CHECK_EQ(erased, 1u);
   CHECK(ui_thread_storage_);
   // Unretained is safe because `ui_thread_storage_` is deleted on the UI
   // thread.
@@ -813,6 +834,9 @@
       FROM_HERE, base::BindOnce(&UIThreadStorage::OnPageNodeRemoved,
                                 base::Unretained(ui_thread_storage_.get()),
                                 page_node->GetResourceContext()));
+  // Leave the WeakPtr to `page_node` in `page_nodes_by_context_` so it can
+  // still be resolved until all OnBeforePageNodeRemoved() notifications are
+  // done. At that point the WeakPtr will be invalidated.
 }
 
 void ResourceContextRegistryStorage::OnProcessNodeAdded(
@@ -846,7 +870,8 @@
       break;
   }
   const auto [_, inserted] = process_nodes_by_context_.emplace(
-      std::move(process_context), process_node);
+      std::move(process_context),
+      ProcessNodeImpl::FromNode(process_node)->GetWeakPtr());
   CHECK(inserted);
 }
 
@@ -854,9 +879,6 @@
     const ProcessNode* process_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CHECK(ui_thread_storage_);
-  const ProcessContext& process_context = process_node->GetResourceContext();
-  const size_t erased = process_nodes_by_context_.erase(process_context);
-  CHECK_EQ(erased, 1u);
   // Unretained is safe because `ui_thread_storage_` is passed to the UI
   // thread to delete.
   switch (process_node->GetProcessType()) {
@@ -865,14 +887,14 @@
           FROM_HERE,
           base::BindOnce(&UIThreadStorage::OnBrowserProcessNodeRemoved,
                          base::Unretained(ui_thread_storage_.get()),
-                         process_context));
+                         process_node->GetResourceContext()));
       break;
     case content::PROCESS_TYPE_RENDERER:
       content::GetUIThreadTaskRunner()->PostTask(
           FROM_HERE,
           base::BindOnce(&UIThreadStorage::OnRenderProcessNodeRemoved,
                          base::Unretained(ui_thread_storage_.get()),
-                         process_context,
+                         process_node->GetResourceContext(),
                          process_node->GetRenderProcessHostProxy()));
       break;
     default:
@@ -880,18 +902,23 @@
           FROM_HERE,
           base::BindOnce(&UIThreadStorage::OnBrowserChildProcessNodeRemoved,
                          base::Unretained(ui_thread_storage_.get()),
-                         process_context,
+                         process_node->GetResourceContext(),
                          process_node->GetBrowserChildProcessHostProxy()));
       break;
   }
+  // Leave the WeakPtr to `process_node` in `process_nodes_by_context_` so it
+  // can still be resolved until all OnBeforeProcessNodeRemoved() notifications
+  // are done. At that point the WeakPtr will be invalidated.
 }
 
 void ResourceContextRegistryStorage::OnWorkerNodeAdded(
     const WorkerNode* worker_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const auto [_, inserted] = worker_nodes_by_context_.emplace(
-      worker_node->GetResourceContext(), worker_node);
+      worker_node->GetResourceContext(),
+      WorkerNodeImpl::FromNode(worker_node)->GetWeakPtr());
   CHECK(inserted);
+  CHECK(ui_thread_storage_);
   // Unretained is safe because the pointer is deleted on the UI thread.
   content::GetUIThreadTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(&UIThreadStorage::OnWorkerNodeAdded,
@@ -902,14 +929,15 @@
 void ResourceContextRegistryStorage::OnBeforeWorkerNodeRemoved(
     const WorkerNode* worker_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  const size_t erased =
-      worker_nodes_by_context_.erase(worker_node->GetResourceContext());
-  CHECK_EQ(erased, 1u);
+  CHECK(ui_thread_storage_);
   // Unretained is safe because the pointer is deleted on the UI thread.
   content::GetUIThreadTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(&UIThreadStorage::OnWorkerNodeRemoved,
                                 base::Unretained(ui_thread_storage_.get()),
                                 worker_node->GetResourceContext()));
+  // Leave the WeakPtr to `worker_node` in `worker_nodes_by_context_` so it
+  // can still be resolved until all OnBeforeWorkerNodeRemoved() notifications
+  // are done. At that point the WeakPtr will be invalidated.
 }
 
 void ResourceContextRegistryStorage::OnPassedToGraph(Graph* graph) {
diff --git a/components/performance_manager/resource_attribution/resource_context_registry_storage.h b/components/performance_manager/resource_attribution/resource_context_registry_storage.h
index 398fc9b..18dd454 100644
--- a/components/performance_manager/resource_attribution/resource_context_registry_storage.h
+++ b/components/performance_manager/resource_attribution/resource_context_registry_storage.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <set>
 
+#include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "components/performance_manager/public/browser_child_process_host_id.h"
 #include "components/performance_manager/public/graph/frame_node.h"
@@ -131,15 +132,16 @@
   // Validates that non-static methods are called on the PM sequence.
   SEQUENCE_CHECKER(sequence_checker_);
 
-  // Storage used only from the PM sequence.
-  std::map<FrameContext, const FrameNode*> frame_nodes_by_context_
+  // Storage used only from the PM sequence. Mutable so that invalidated
+  // WeakPtr's can be cleaned up from logically const methods.
+  mutable std::map<FrameContext, base::WeakPtr<FrameNode>>
+      frame_nodes_by_context_ GUARDED_BY_CONTEXT(sequence_checker_);
+  mutable std::map<PageContext, base::WeakPtr<PageNode>> page_nodes_by_context_
       GUARDED_BY_CONTEXT(sequence_checker_);
-  std::map<PageContext, const PageNode*> page_nodes_by_context_
-      GUARDED_BY_CONTEXT(sequence_checker_);
-  std::map<ProcessContext, const ProcessNode*> process_nodes_by_context_
-      GUARDED_BY_CONTEXT(sequence_checker_);
-  std::map<WorkerContext, const WorkerNode*> worker_nodes_by_context_
-      GUARDED_BY_CONTEXT(sequence_checker_);
+  mutable std::map<ProcessContext, base::WeakPtr<ProcessNode>>
+      process_nodes_by_context_ GUARDED_BY_CONTEXT(sequence_checker_);
+  mutable std::map<WorkerContext, base::WeakPtr<WorkerNode>>
+      worker_nodes_by_context_ GUARDED_BY_CONTEXT(sequence_checker_);
 
   std::unique_ptr<UIThreadStorage> ui_thread_storage_;
 
diff --git a/components/performance_manager/resource_attribution/worker_context_registry_browsertest.cc b/components/performance_manager/resource_attribution/worker_context_registry_browsertest.cc
index 48eb7423..e892f7a 100644
--- a/components/performance_manager/resource_attribution/worker_context_registry_browsertest.cc
+++ b/components/performance_manager/resource_attribution/worker_context_registry_browsertest.cc
@@ -14,6 +14,7 @@
 #include "components/performance_manager/graph/graph_impl.h"
 #include "components/performance_manager/graph/worker_node_impl.h"
 #include "components/performance_manager/performance_manager_impl.h"
+#include "components/performance_manager/public/graph/graph.h"
 #include "components/performance_manager/public/graph/worker_node.h"
 #include "components/performance_manager/public/resource_attribution/resource_contexts.h"
 #include "components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.h"
@@ -175,6 +176,29 @@
       });
 }
 
+IN_PROC_BROWSER_TEST_F(WorkerContextRegistryTest, OnBeforeWorkerNodeRemoved) {
+  CreateNodes();
+
+  absl::optional<WorkerContext> worker_context =
+      WorkerContextRegistry::ContextForWorkerToken(worker_token_a_);
+  ASSERT_TRUE(worker_context.has_value());
+
+  RemoveWorkerNodeWaiter waiter(
+      weak_worker_node_a_,
+      base::BindLambdaForTesting([&](const WorkerNode* worker_node) {
+        // `worker_node` should still be available from WorkerContextRegistry in
+        // OnBeforeWorkerNodeRemoved.
+        const auto* registry =
+            WorkerContextRegistry::GetFromGraph(worker_node->GetGraph());
+        ASSERT_TRUE(registry);
+        EXPECT_EQ(registry->GetWorkerNodeForContext(worker_context.value()),
+                  worker_node);
+      }));
+
+  DeleteNodes();
+  waiter.Wait();
+}
+
 IN_PROC_BROWSER_TEST_F(WorkerContextRegistryDisabledTest, UIThreadAccess) {
   CreateNodes();
 
diff --git a/components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.cc b/components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.cc
index c923426..a305869 100644
--- a/components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.cc
+++ b/components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.cc
@@ -112,4 +112,55 @@
   Super::PostRunTestOnMainThread();
 }
 
+RemoveFrameNodeWaiter::RemoveFrameNodeWaiter(
+    base::WeakPtr<FrameNode> watched_node,
+    Super::OnRemovedCallback on_removed_callback)
+    : Super(watched_node,
+            std::move(on_removed_callback),
+            &Graph::AddFrameNodeObserver,
+            &Graph::RemoveFrameNodeObserver) {}
+
+void RemoveFrameNodeWaiter::OnBeforeFrameNodeRemoved(
+    const FrameNode* frame_node) {
+  OnBeforeNodeRemoved(frame_node);
+}
+
+RemovePageNodeWaiter::RemovePageNodeWaiter(
+    base::WeakPtr<PageNode> watched_node,
+    Super::OnRemovedCallback on_removed_callback)
+    : Super(watched_node,
+            std::move(on_removed_callback),
+            &Graph::AddPageNodeObserver,
+            &Graph::RemovePageNodeObserver) {}
+
+void RemovePageNodeWaiter::OnBeforePageNodeRemoved(const PageNode* page_node) {
+  OnBeforeNodeRemoved(page_node);
+}
+
+RemoveProcessNodeWaiter::RemoveProcessNodeWaiter(
+    base::WeakPtr<ProcessNode> watched_node,
+    Super::OnRemovedCallback on_removed_callback)
+    : Super(watched_node,
+            std::move(on_removed_callback),
+            &Graph::AddProcessNodeObserver,
+            &Graph::RemoveProcessNodeObserver) {}
+
+void RemoveProcessNodeWaiter::OnBeforeProcessNodeRemoved(
+    const ProcessNode* process_node) {
+  OnBeforeNodeRemoved(process_node);
+}
+
+RemoveWorkerNodeWaiter::RemoveWorkerNodeWaiter(
+    base::WeakPtr<WorkerNode> watched_node,
+    Super::OnRemovedCallback on_removed_callback)
+    : Super(watched_node,
+            std::move(on_removed_callback),
+            &Graph::AddWorkerNodeObserver,
+            &Graph::RemoveWorkerNodeObserver) {}
+
+void RemoveWorkerNodeWaiter::OnBeforeWorkerNodeRemoved(
+    const WorkerNode* worker_node) {
+  OnBeforeNodeRemoved(worker_node);
+}
+
 }  // namespace performance_manager::resource_attribution
diff --git a/components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.h b/components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.h
index a2f68ec..e4b063f 100644
--- a/components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.h
+++ b/components/performance_manager/test_support/resource_attribution/registry_browsertest_harness.h
@@ -7,13 +7,25 @@
 
 #include "components/performance_manager/test_support/performance_manager_browsertest_harness.h"
 
+#include <utility>
+
+#include "base/functional/bind.h"
+#include "base/functional/callback.h"
 #include "base/functional/function_ref.h"
+#include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
+#include "base/sequence_checker.h"
 #include "base/test/bind.h"
+#include "components/performance_manager/public/graph/frame_node.h"
+#include "components/performance_manager/public/graph/graph.h"
+#include "components/performance_manager/public/graph/page_node.h"
+#include "components/performance_manager/public/graph/process_node.h"
+#include "components/performance_manager/public/graph/worker_node.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "components/performance_manager/public/resource_attribution/resource_contexts.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/shell/browser/shell.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
 class WebContents;
@@ -91,6 +103,97 @@
   RegistryDisabledBrowserTestHarness() : RegistryBrowserTestHarness(false) {}
 };
 
+// Helper classes to wait for nodes to be removed from the PM graph, to test
+// registry access from OnBefore*NodeRemoved.
+
+template <typename NodeType, typename ObserverBase>
+class RemoveNodeWaiter : public NodeType::ObserverDefaultImpl {
+ public:
+  using AddRemoveObserverMethod = void (Graph::*)(ObserverBase*);
+  using OnRemovedCallback = base::OnceCallback<void(const NodeType*)>;
+
+  // When `watched_node` is removed from the graph, will call
+  // `on_removed_callback` from OnBefore*NodeRemoved. This must be created
+  // on the main thread before destroying the node's content layer object.
+  RemoveNodeWaiter(base::WeakPtr<NodeType> watched_node,
+                   OnRemovedCallback on_removed_callback,
+                   AddRemoveObserverMethod add_observer,
+                   AddRemoveObserverMethod remove_observer);
+
+  ~RemoveNodeWaiter() override;
+
+  RemoveNodeWaiter(const RemoveNodeWaiter&) = delete;
+  RemoveNodeWaiter& operator=(const RemoveNodeWaiter&) = delete;
+
+  // Waits until `on_removed_callback` is called. This should be called on the
+  // main thread after destroying `watched_node`'s content layer object.
+  void Wait();
+
+ protected:
+  // Invoked on the PM sequence from the corresponding
+  // ObserverDefaultImpl::OnBefore*NodeRemoved() method.
+  void OnBeforeNodeRemoved(const NodeType* node);
+
+ private:
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  // Only accessed from the main thread.
+  base::RunLoop waiter_run_loop_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // These are initialized on the main thread in the constructor and read from
+  // the PM thread.
+  base::WeakPtr<NodeType> watched_node_;
+  OnRemovedCallback on_removed_callback_;
+  AddRemoveObserverMethod remove_observer_;
+  base::OnceClosure waiter_quit_closure_;
+};
+
+class RemoveFrameNodeWaiter final
+    : public RemoveNodeWaiter<FrameNode, FrameNodeObserver> {
+ public:
+  using Super = RemoveNodeWaiter<FrameNode, FrameNodeObserver>;
+
+  RemoveFrameNodeWaiter(base::WeakPtr<FrameNode> watched_node,
+                        Super::OnRemovedCallback on_removed_callback);
+
+  void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) final;
+};
+
+class RemovePageNodeWaiter final
+    : public RemoveNodeWaiter<PageNode, PageNodeObserver> {
+ public:
+  using Super = RemoveNodeWaiter<PageNode, PageNodeObserver>;
+
+  RemovePageNodeWaiter(base::WeakPtr<PageNode> watched_node,
+                       Super::OnRemovedCallback on_removed_callback);
+
+  void OnBeforePageNodeRemoved(const PageNode* page_node) final;
+};
+
+class RemoveProcessNodeWaiter final
+    : public RemoveNodeWaiter<ProcessNode, ProcessNodeObserver> {
+ public:
+  using Super = RemoveNodeWaiter<ProcessNode, ProcessNodeObserver>;
+
+  RemoveProcessNodeWaiter(base::WeakPtr<ProcessNode> watched_node,
+                          Super::OnRemovedCallback on_removed_callback);
+
+  void OnBeforeProcessNodeRemoved(const ProcessNode* process_node) final;
+};
+
+class RemoveWorkerNodeWaiter final
+    : public RemoveNodeWaiter<WorkerNode, WorkerNodeObserver> {
+ public:
+  using Super = RemoveNodeWaiter<WorkerNode, WorkerNodeObserver>;
+
+  RemoveWorkerNodeWaiter(base::WeakPtr<WorkerNode> watched_node,
+                         Super::OnRemovedCallback on_removed_callback);
+
+  void OnBeforeWorkerNodeRemoved(const WorkerNode* worker_node) final;
+};
+
+// Implementation
+
 // static
 template <typename Registry>
 void RegistryBrowserTestHarness::RunInGraphWithRegistry(
@@ -103,6 +206,57 @@
   run_loop.Run();
 }
 
+template <typename NodeType, typename ObserverBase>
+RemoveNodeWaiter<NodeType, ObserverBase>::RemoveNodeWaiter(
+    base::WeakPtr<NodeType> watched_node,
+    OnRemovedCallback on_removed_callback,
+    AddRemoveObserverMethod add_observer,
+    AddRemoveObserverMethod remove_observer)
+    : watched_node_(watched_node),
+      on_removed_callback_(std::move(on_removed_callback)),
+      remove_observer_(remove_observer),
+      waiter_quit_closure_(waiter_run_loop_.QuitClosure()) {
+  // Add a node observer on the PM sequence.
+  base::RunLoop run_loop;
+  PerformanceManager::CallOnGraph(
+      FROM_HERE, base::BindLambdaForTesting([this, add_observer](Graph* graph) {
+                   (graph->*add_observer)(this);
+                 }).Then(run_loop.QuitClosure()));
+  run_loop.Run();
+}
+
+template <typename NodeType, typename ObserverBase>
+RemoveNodeWaiter<NodeType, ObserverBase>::~RemoveNodeWaiter() {
+  // Remove the node observer on the PM sequence.
+  base::RunLoop run_loop;
+  PerformanceManager::CallOnGraph(
+      FROM_HERE, base::BindLambdaForTesting([this](Graph* graph) {
+                   (graph->*remove_observer_)(this);
+                 }).Then(run_loop.QuitClosure()));
+  run_loop.Run();
+}
+
+template <typename NodeType, typename ObserverBase>
+void RemoveNodeWaiter<NodeType, ObserverBase>::Wait() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  waiter_run_loop_.Run();
+}
+
+template <typename NodeType, typename ObserverBase>
+void RemoveNodeWaiter<NodeType, ObserverBase>::OnBeforeNodeRemoved(
+    const NodeType* node) {
+  if (!watched_node_) {
+    // The observer is still installed after the node was removed. Ignore.
+    ASSERT_TRUE(on_removed_callback_.is_null());
+    return;
+  }
+  if (node == watched_node_.get()) {
+    ASSERT_FALSE(on_removed_callback_.is_null());
+    std::move(on_removed_callback_).Run(node);
+    std::move(waiter_quit_closure_).Run();
+  }
+}
+
 }  // namespace performance_manager::resource_attribution
 
 #endif  // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_REGISTRY_BROWSERTEST_HARNESS_H_
diff --git a/components/privacy_sandbox/BUILD.gn b/components/privacy_sandbox/BUILD.gn
index 18d2132..87074e6 100644
--- a/components/privacy_sandbox/BUILD.gn
+++ b/components/privacy_sandbox/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/features.gni")
+
 static_library("privacy_sandbox_prefs") {
   sources = [
     "privacy_sandbox_prefs.cc",
@@ -30,57 +32,6 @@
   public_deps = [ "//base" ]
 }
 
-source_set("privacy_sandbox_settings_headers") {
-  sources = [
-    "privacy_sandbox_settings.h",
-    "privacy_sandbox_settings_impl.h",
-  ]
-
-  deps = [
-    ":tracking_protection_settings",
-    "//components/browsing_topics/common:common",
-    "//components/keyed_service/core:core",
-    "//components/pref_registry:pref_registry",
-    "//components/prefs",
-    "//content/public/browser",
-    "//third_party/blink/public/common",
-    "//url:url",
-  ]
-
-  public_deps = [ "//base" ]
-}
-
-source_set("privacy_sandbox") {
-  sources = [
-    "canonical_topic.cc",
-    "canonical_topic.h",
-    "privacy_sandbox_settings_impl.cc",
-  ]
-
-  deps = [
-    ":privacy_sandbox_prefs",
-    ":tracking_protection_settings",
-    "//components/browsing_topics/common:common",
-    "//components/content_settings/core/browser",
-    "//components/content_settings/core/common",
-    "//components/keyed_service/core:core",
-    "//components/pref_registry:pref_registry",
-    "//components/prefs",
-    "//components/privacy_sandbox/privacy_sandbox_attestations",
-    "//components/strings:components_strings_grit",
-    "//content/public/browser",
-    "//net:net",
-    "//third_party/blink/public/common",
-    "//ui/base:base",
-    "//url:url",
-  ]
-
-  public_deps = [
-    ":features",
-    ":privacy_sandbox_settings_headers",
-  ]
-}
-
 source_set("tracking_protection_onboarding") {
   sources = [
     "tracking_protection_onboarding.cc",
@@ -118,66 +69,6 @@
   public_deps = [ "//base" ]
 }
 
-source_set("unit_tests") {
-  testonly = true
-  sources = [
-    "canonical_topic_unittest.cc",
-    "privacy_sandbox_settings_impl_unittest.cc",
-    "privacy_sandbox_test_util_unittest.cc",
-    "tracking_protection_onboarding_unittest.cc",
-    "tracking_protection_settings_unittest.cc",
-  ]
-
-  deps = [
-    ":privacy_sandbox",
-    ":privacy_sandbox_prefs",
-    ":test_support",
-    ":tracking_protection_onboarding",
-    ":tracking_protection_prefs",
-    ":tracking_protection_settings",
-    "//components/browsing_topics:test_support",
-    "//components/content_settings/core/browser:browser",
-    "//components/content_settings/core/test:test_support",
-    "//components/prefs:test_support",
-    "//components/privacy_sandbox/privacy_sandbox_attestations",
-    "//components/privacy_sandbox/privacy_sandbox_attestations:test_support",
-    "//components/strings:components_strings_grit",
-    "//components/sync_preferences:test_support",
-    "//content/public/browser",
-    "//content/test:test_support",
-    "//net",
-    "//testing/gtest",
-  ]
-}
-
-source_set("test_support") {
-  testonly = true
-  sources = [
-    "mock_privacy_sandbox_settings.cc",
-    "mock_privacy_sandbox_settings.h",
-    "privacy_sandbox_test_util.cc",
-    "privacy_sandbox_test_util.h",
-  ]
-  deps = [
-    ":privacy_sandbox",
-    ":privacy_sandbox_prefs",
-    "//base/test:test_support",
-    "//components/browsing_topics:test_support",
-    "//components/content_settings/core/browser:browser",
-    "//components/content_settings/core/common:common",
-    "//components/content_settings/core/test:test_support",
-    "//components/prefs:test_support",
-    "//components/privacy_sandbox/privacy_sandbox_attestations",
-    "//components/privacy_sandbox/privacy_sandbox_attestations:test_support",
-    "//components/sync_preferences:test_support",
-    "//content/test:test_support",
-    "//testing/gmock",
-    "//testing/gtest:gtest",
-    "//ui/base:base",
-    "//url:url",
-  ]
-}
-
 static_library("tracking_protection_prefs") {
   sources = [
     "tracking_protection_prefs.cc",
@@ -191,3 +82,129 @@
 
   public_deps = [ "//base" ]
 }
+
+# These sources depend on targets from "//content/browser", which means they can't be
+# loaded on ios.
+# TOOD(b/301947962): Delete this check after CookieSettings is removed from iOS.
+if (use_blink) {
+  source_set("privacy_sandbox_settings_headers") {
+    sources = [
+      "privacy_sandbox_settings.h",
+      "privacy_sandbox_settings_impl.h",
+    ]
+
+    deps = [
+      ":tracking_protection_settings",
+      "//components/browsing_topics/common:common",
+      "//components/keyed_service/core:core",
+      "//components/pref_registry:pref_registry",
+      "//components/prefs",
+      "//content/public/browser",
+      "//third_party/blink/public/common",
+      "//url:url",
+    ]
+
+    public_deps = [ "//base" ]
+  }
+
+  source_set("privacy_sandbox") {
+    sources = [
+      "canonical_topic.cc",
+      "canonical_topic.h",
+      "privacy_sandbox_settings_impl.cc",
+    ]
+
+    deps = [
+      ":privacy_sandbox_prefs",
+      ":tracking_protection_settings",
+      "//components/browsing_topics/common:common",
+      "//components/content_settings/core/browser",
+      "//components/content_settings/core/common",
+      "//components/keyed_service/core:core",
+      "//components/pref_registry:pref_registry",
+      "//components/prefs",
+      "//components/privacy_sandbox/privacy_sandbox_attestations",
+      "//components/strings:components_strings_grit",
+      "//content/public/browser",
+      "//net:net",
+      "//third_party/blink/public/common",
+      "//ui/base:base",
+      "//url:url",
+    ]
+
+    public_deps = [
+      ":features",
+      ":privacy_sandbox_settings_headers",
+    ]
+  }
+
+  source_set("test_support") {
+    testonly = true
+    sources = [
+      "mock_privacy_sandbox_settings.cc",
+      "mock_privacy_sandbox_settings.h",
+      "privacy_sandbox_test_util.cc",
+      "privacy_sandbox_test_util.h",
+    ]
+    deps = [
+      ":privacy_sandbox",
+      ":privacy_sandbox_prefs",
+      "//base/test:test_support",
+      "//components/browsing_topics:test_support",
+      "//components/content_settings/core/browser:browser",
+      "//components/content_settings/core/common:common",
+      "//components/content_settings/core/test:test_support",
+      "//components/prefs:test_support",
+      "//components/privacy_sandbox/privacy_sandbox_attestations",
+      "//components/privacy_sandbox/privacy_sandbox_attestations:test_support",
+      "//components/sync_preferences:test_support",
+      "//content/test:test_support",
+      "//testing/gmock",
+      "//testing/gtest:gtest",
+      "//ui/base:base",
+      "//url:url",
+    ]
+  }
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "tracking_protection_onboarding_unittest.cc",
+    "tracking_protection_settings_unittest.cc",
+  ]
+
+  deps = [
+    ":features",
+    ":privacy_sandbox_prefs",
+    ":tracking_protection_onboarding",
+    ":tracking_protection_prefs",
+    ":tracking_protection_settings",
+    "//base/test:test_support",
+    "//components/prefs:test_support",
+    "//components/sync_preferences:test_support",
+    "//testing/gtest",
+  ]
+
+  if (use_blink) {
+    sources += [
+      "canonical_topic_unittest.cc",
+      "privacy_sandbox_settings_impl_unittest.cc",
+      "privacy_sandbox_test_util_unittest.cc",
+    ]
+
+    deps += [
+      ":privacy_sandbox",
+      ":test_support",
+      "//components/browsing_topics:test_support",
+      "//components/content_settings/core/browser:browser",
+      "//components/content_settings/core/test:test_support",
+      "//components/privacy_sandbox/privacy_sandbox_attestations",
+      "//components/privacy_sandbox/privacy_sandbox_attestations:test_support",
+      "//components/strings:components_strings_grit",
+      "//content/public/browser",
+      "//content/test:test_support",
+      "//net",
+    ]
+  }
+}
diff --git a/components/privacy_sandbox/android/BUILD.gn b/components/privacy_sandbox/android/BUILD.gn
index f56eb840..cb54a92 100644
--- a/components/privacy_sandbox/android/BUILD.gn
+++ b/components/privacy_sandbox/android/BUILD.gn
@@ -5,12 +5,19 @@
 import("//build/config/android/rules.gni")
 
 android_library("java") {
-  sources = [ "java/src/org/chromium/components/privacy_sandbox/TrackingProtectionSettings.java" ]
+  sources = [
+    "java/src/org/chromium/components/privacy_sandbox/TrackingProtectionDelegate.java",
+    "java/src/org/chromium/components/privacy_sandbox/TrackingProtectionSettings.java",
+  ]
   resources_package = "org.chromium.components.privacy_sandbox"
   deps = [
     ":java_resources",
     "//components/browser_ui/settings/android:java",
+    "//components/prefs/android:java",
     "//components/strings:components_strings_grd",
+    "//components/user_prefs/android:java",
+    "//content/public/android:content_java",
+    "//third_party/androidx:androidx_fragment_fragment_java",
     "//third_party/androidx:androidx_preference_preference_java",
   ]
 }
diff --git a/components/privacy_sandbox/android/java/src/org/chromium/components/privacy_sandbox/TrackingProtectionDelegate.java b/components/privacy_sandbox/android/java/src/org/chromium/components/privacy_sandbox/TrackingProtectionDelegate.java
new file mode 100644
index 0000000..be85b41e7
--- /dev/null
+++ b/components/privacy_sandbox/android/java/src/org/chromium/components/privacy_sandbox/TrackingProtectionDelegate.java
@@ -0,0 +1,20 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.privacy_sandbox;
+
+/** Interface implemented by the embedder to access embedder-specific logic. */
+public interface TrackingProtectionDelegate {
+    /** @return whether block all 3PCD pref is enabled. */
+    boolean isBlockAll3PCDEnabled();
+
+    /** Set the value of the block all 3PCD pref. */
+    void setBlockAll3PCD(boolean enabled);
+
+    /** @return whether the Do Not Track pref is enabled. */
+    boolean isDoNotTrackEnabled();
+
+    /** Set the value of the Do Not Track Pref. */
+    void setDoNotTrack(boolean enabled);
+}
diff --git a/components/privacy_sandbox/android/java/src/org/chromium/components/privacy_sandbox/TrackingProtectionSettings.java b/components/privacy_sandbox/android/java/src/org/chromium/components/privacy_sandbox/TrackingProtectionSettings.java
index 1415fa0..fd08381b 100644
--- a/components/privacy_sandbox/android/java/src/org/chromium/components/privacy_sandbox/TrackingProtectionSettings.java
+++ b/components/privacy_sandbox/android/java/src/org/chromium/components/privacy_sandbox/TrackingProtectionSettings.java
@@ -8,12 +8,43 @@
 
 import androidx.preference.PreferenceFragmentCompat;
 
+import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 
 /** Fragment to manage settings for tracking protection. */
 public class TrackingProtectionSettings extends PreferenceFragmentCompat {
+    // Must match keys in tracking_protection_preferences.xml.
+    private static final String PREF_BLOCK_ALL_TOGGLE = "block_all_3pcd_toggle";
+    private static final String PREF_DNT_TOGGLE = "dnt_toggle";
+
+    private TrackingProtectionDelegate mDelegate;
+
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         SettingsUtils.addPreferencesFromResource(this, R.xml.tracking_protection_preferences);
+        getActivity().setTitle(R.string.privacy_sandbox_tracking_protection_title);
+
+        ChromeSwitchPreference blockAll3PCookiesSwitch =
+                (ChromeSwitchPreference) findPreference(PREF_BLOCK_ALL_TOGGLE);
+        ChromeSwitchPreference doNotTrackSwitch =
+                (ChromeSwitchPreference) findPreference(PREF_DNT_TOGGLE);
+
+        // Block all 3PCD switch.
+        blockAll3PCookiesSwitch.setChecked(mDelegate.isBlockAll3PCDEnabled());
+        blockAll3PCookiesSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
+            mDelegate.setBlockAll3PCD((boolean) newValue);
+            return true;
+        });
+
+        // Do not track switch.
+        doNotTrackSwitch.setChecked(mDelegate.isDoNotTrackEnabled());
+        doNotTrackSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
+            mDelegate.setDoNotTrack((boolean) newValue);
+            return true;
+        });
+    }
+
+    public void setTrackingProtectionDelegate(TrackingProtectionDelegate delegate) {
+        mDelegate = delegate;
     }
 }
diff --git a/components/privacy_sandbox_strings.grdp b/components/privacy_sandbox_strings.grdp
index 73cf265..cbf3bd91 100644
--- a/components/privacy_sandbox_strings.grdp
+++ b/components/privacy_sandbox_strings.grdp
@@ -2163,6 +2163,9 @@
 
   <!-- Tracking Protection -->
   <!-- TODO(b/295926938: finalize the strings. -->
+  <message name="IDS_PRIVACY_SANDBOX_TRACKING_PROTECTION_TITLE" desc="" translateable="false" formatter_data="android_java">
+    Tracking Protection
+  </message>
   <message name="IDS_PRIVACY_SANDBOX_TRACKING_PROTECTION_DESCRIPTION" desc="" translateable="false" formatter_data="android_java">
     Chrome limits the amount of information sites can use to track you as you browse. You can change your settings to choose your own level of protection.
   </message>
diff --git a/components/remote_cocoa/app_shim/BUILD.gn b/components/remote_cocoa/app_shim/BUILD.gn
index 0625f07f..0369b1e 100644
--- a/components/remote_cocoa/app_shim/BUILD.gn
+++ b/components/remote_cocoa/app_shim/BUILD.gn
@@ -31,11 +31,11 @@
     "color_panel_bridge.h",
     "color_panel_bridge.mm",
     "drag_drop_client.h",
-    "immersive_mode_controller.h",
-    "immersive_mode_controller.mm",
+    "immersive_mode_controller_cocoa.h",
+    "immersive_mode_controller_cocoa.mm",
     "immersive_mode_delegate_mac.h",
-    "immersive_mode_tabbed_controller.h",
-    "immersive_mode_tabbed_controller.mm",
+    "immersive_mode_tabbed_controller_cocoa.h",
+    "immersive_mode_tabbed_controller_cocoa.mm",
     "mouse_capture.h",
     "mouse_capture.mm",
     "mouse_capture_delegate.h",
diff --git a/components/remote_cocoa/app_shim/immersive_mode_controller.h b/components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.h
similarity index 93%
rename from components/remote_cocoa/app_shim/immersive_mode_controller.h
rename to components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.h
index e5b9f133..3b59b68 100644
--- a/components/remote_cocoa/app_shim/immersive_mode_controller.h
+++ b/components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.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_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_CONTROLLER_H_
-#define COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_CONTROLLER_H_
+#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_CONTROLLER_COCOA_H_
+#define COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_CONTROLLER_COCOA_H_
 
 #import <AppKit/AppKit.h>
 
@@ -17,14 +17,14 @@
 @class ImmersiveModeTitlebarObserver;
 
 namespace remote_cocoa {
-class ImmersiveModeController;
+class ImmersiveModeControllerCocoa;
 }  // namespace remote_cocoa
 
 // Host of the overlay view.
 @interface ImmersiveModeTitlebarViewController
     : NSTitlebarAccessoryViewController {
   NSView* __strong _blank_separator_view;
-  base::WeakPtr<remote_cocoa::ImmersiveModeController>
+  base::WeakPtr<remote_cocoa::ImmersiveModeControllerCocoa>
       _immersive_mode_controller;
 }
 @end
@@ -41,11 +41,12 @@
 REMOTE_COCOA_APP_SHIM_EXPORT bool IsNSToolbarFullScreenWindow(NSWindow* window);
 
 // Manages a single fullscreen session.
-class REMOTE_COCOA_APP_SHIM_EXPORT ImmersiveModeController {
+class REMOTE_COCOA_APP_SHIM_EXPORT ImmersiveModeControllerCocoa {
  public:
-  explicit ImmersiveModeController(NativeWidgetMacNSWindow* browser_window,
-                                   NativeWidgetMacNSWindow* overlay_window);
-  virtual ~ImmersiveModeController();
+  explicit ImmersiveModeControllerCocoa(
+      NativeWidgetMacNSWindow* browser_window,
+      NativeWidgetMacNSWindow* overlay_window);
+  virtual ~ImmersiveModeControllerCocoa();
 
   // Must be called once and only once after construction. Prevents the side-
   // effects of adding a toolbar accessory from accessing partially constructed
@@ -167,7 +168,7 @@
   // Keeps track of which windows have received titlebar and reveal locks.
   std::set<NSWindow*> window_lock_received_;
 
-  base::WeakPtrFactory<ImmersiveModeController> weak_ptr_factory_;
+  base::WeakPtrFactory<ImmersiveModeControllerCocoa> weak_ptr_factory_;
 };
 
 }  // namespace remote_cocoa
@@ -187,7 +188,7 @@
 REMOTE_COCOA_APP_SHIM_EXPORT @interface ImmersiveModeTitlebarObserver : NSObject
 
 - (instancetype)initWithController:
-                    (base::WeakPtr<remote_cocoa::ImmersiveModeController>)
+                    (base::WeakPtr<remote_cocoa::ImmersiveModeControllerCocoa>)
                         controller
              titlebarContainerView:(NSView*)titlebarContainerView;
 
@@ -197,4 +198,4 @@
 @interface OpaqueView : NSView
 @end
 
-#endif  // COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_CONTROLLER_H_
+#endif  // COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_CONTROLLER_COCOA_H_
diff --git a/components/remote_cocoa/app_shim/immersive_mode_controller.mm b/components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.mm
similarity index 90%
rename from components/remote_cocoa/app_shim/immersive_mode_controller.mm
rename to components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.mm
index aa40cbc..492e53c 100644
--- a/components/remote_cocoa/app_shim/immersive_mode_controller.mm
+++ b/components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.mm
@@ -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/remote_cocoa/app_shim/immersive_mode_controller.h"
+#include "components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.h"
 
 #include "base/apple/foundation_util.h"
 #include "base/auto_reset.h"
@@ -29,7 +29,7 @@
 }  // namespace
 
 @interface ImmersiveModeTitlebarObserver () {
-  base::WeakPtr<remote_cocoa::ImmersiveModeController> _controller;
+  base::WeakPtr<remote_cocoa::ImmersiveModeControllerCocoa> _controller;
   NSView* __weak _titlebarContainerView;
 }
 @end
@@ -37,7 +37,7 @@
 @implementation ImmersiveModeTitlebarObserver
 
 - (instancetype)initWithController:
-                    (base::WeakPtr<remote_cocoa::ImmersiveModeController>)
+                    (base::WeakPtr<remote_cocoa::ImmersiveModeControllerCocoa>)
                         controller
              titlebarContainerView:(NSView*)titlebarContainerView {
   self = [super init];
@@ -92,7 +92,7 @@
 
 @implementation ImmersiveModeTitlebarViewController
 
-- (instancetype)init:(base::WeakPtr<remote_cocoa::ImmersiveModeController>)
+- (instancetype)init:(base::WeakPtr<remote_cocoa::ImmersiveModeControllerCocoa>)
                          immersiveModeController {
   if ((self = [super init])) {
     _blank_separator_view = [[NSView alloc] init];
@@ -161,15 +161,15 @@
 // NSTitlebarAccessoryViewController API.
 @interface ImmersiveModeView : NSView
 - (instancetype)initWithController:
-    (base::WeakPtr<remote_cocoa::ImmersiveModeController>)controller;
+    (base::WeakPtr<remote_cocoa::ImmersiveModeControllerCocoa>)controller;
 @end
 
 @implementation ImmersiveModeView {
-  base::WeakPtr<remote_cocoa::ImmersiveModeController> _controller;
+  base::WeakPtr<remote_cocoa::ImmersiveModeControllerCocoa> _controller;
 }
 
 - (instancetype)initWithController:
-    (base::WeakPtr<remote_cocoa::ImmersiveModeController>)controller {
+    (base::WeakPtr<remote_cocoa::ImmersiveModeControllerCocoa>)controller {
   self = [super init];
   if (self) {
     _controller = std::move(controller);
@@ -200,7 +200,7 @@
   return [window isKindOfClass:NSClassFromString(@"NSToolbarFullScreenWindow")];
 }
 
-ImmersiveModeController::ImmersiveModeController(
+ImmersiveModeControllerCocoa::ImmersiveModeControllerCocoa(
     NativeWidgetMacNSWindow* browser_window,
     NativeWidgetMacNSWindow* overlay_window)
     : weak_ptr_factory_(this) {
@@ -256,7 +256,7 @@
       NSLayoutAttributeBottom;
 }
 
-ImmersiveModeController::~ImmersiveModeController() {
+ImmersiveModeControllerCocoa::~ImmersiveModeControllerCocoa() {
   // Remove the titlebar observer before moving the view.
   immersive_mode_titlebar_observer_ = nil;
 
@@ -273,7 +273,7 @@
   }
 }
 
-void ImmersiveModeController::Init() {
+void ImmersiveModeControllerCocoa::Init() {
   DCHECK(!initialized_);
   initialized_ = true;
   [browser_window_ addTitlebarAccessoryViewController:
@@ -295,7 +295,7 @@
       .active = YES;
 }
 
-void ImmersiveModeController::FullscreenTransitionCompleted() {
+void ImmersiveModeControllerCocoa::FullscreenTransitionCompleted() {
   fullscreen_transition_complete_ = true;
   UpdateToolbarVisibility(last_used_style_);
 
@@ -316,7 +316,8 @@
   NotifyBrowserWindowAboutToolbarRevealChanged();
 }
 
-void ImmersiveModeController::OnTopViewBoundsChanged(const gfx::Rect& bounds) {
+void ImmersiveModeControllerCocoa::OnTopViewBoundsChanged(
+    const gfx::Rect& bounds) {
   // Set the height of the AppKit fullscreen view. The width will be
   // automatically handled by AppKit.
   NSRect frame = NSRectFromCGRect(bounds.ToCGRect());
@@ -340,7 +341,7 @@
   }
 }
 
-void ImmersiveModeController::UpdateToolbarVisibility(
+void ImmersiveModeControllerCocoa::UpdateToolbarVisibility(
     mojom::ToolbarVisibilityStyle style) {
   // Remember the last used style for internal use of UpdateToolbarVisibility.
   last_used_style_ = style;
@@ -389,7 +390,7 @@
   }
 }
 
-void ImmersiveModeController::ObserveChildWindows(NSWindow* window) {
+void ImmersiveModeControllerCocoa::ObserveChildWindows(NSWindow* window) {
   // Watch the Widget for addition and removal of child Widgets.
   NativeWidgetMacNSWindow* widget_window =
       base::apple::ObjCCastStrict<NativeWidgetMacNSWindow>(window);
@@ -401,28 +402,28 @@
   };
 }
 
-void ImmersiveModeController::StopObservingChildWindows(NSWindow* window) {
+void ImmersiveModeControllerCocoa::StopObservingChildWindows(NSWindow* window) {
   NativeWidgetMacNSWindow* widget_window =
       base::apple::ObjCCastStrict<NativeWidgetMacNSWindow>(window);
   widget_window.childWindowAddedHandler = nil;
   widget_window.childWindowRemovedHandler = nil;
 }
 
-bool ImmersiveModeController::ShouldObserveChildWindow(NSWindow* child) {
+bool ImmersiveModeControllerCocoa::ShouldObserveChildWindow(NSWindow* child) {
   return true;
 }
 
-NSWindow* ImmersiveModeController::browser_window() {
+NSWindow* ImmersiveModeControllerCocoa::browser_window() {
   return browser_window_;
 }
-NSWindow* ImmersiveModeController::overlay_window() {
+NSWindow* ImmersiveModeControllerCocoa::overlay_window() {
   return overlay_window_;
 }
-BridgedContentView* ImmersiveModeController::overlay_content_view() {
+BridgedContentView* ImmersiveModeControllerCocoa::overlay_content_view() {
   return overlay_content_view_;
 }
 
-void ImmersiveModeController::OnChildWindowAdded(NSWindow* child) {
+void ImmersiveModeControllerCocoa::OnChildWindowAdded(NSWindow* child) {
   // Skip applying the reveal lock if the window is in the process of being
   // re-ordered, as this may inadvertently trigger a recursive re-ordering.
   // This is because changing the titlebar visibility (which reveal lock does)
@@ -441,7 +442,7 @@
   // TODO(https://crbug.com/1350595): Handle a detached find bar.
 }
 
-void ImmersiveModeController::OnChildWindowRemoved(NSWindow* child) {
+void ImmersiveModeControllerCocoa::OnChildWindowRemoved(NSWindow* child) {
   // Skip applying the reveal lock if the window is in the process of being
   // re-ordered, as this may inadvertently trigger a recursive re-ordering.
   // This is because changing the titlebar visibility (which reveal lock does)
@@ -455,13 +456,13 @@
   RevealUnlock();
 }
 
-void ImmersiveModeController::RevealLock() {
+void ImmersiveModeControllerCocoa::RevealLock() {
   reveal_lock_count_++;
   [immersive_mode_titlebar_view_controller_
       setVisibility:mojom::ToolbarVisibilityStyle::kAlways];
 }
 
-void ImmersiveModeController::RevealUnlock() {
+void ImmersiveModeControllerCocoa::RevealUnlock() {
   // Re-hide the toolbar if appropriate.
   if (--reveal_lock_count_ < 1 &&
       immersive_mode_titlebar_view_controller_.fullScreenMinHeight > 0 &&
@@ -477,7 +478,7 @@
   DCHECK(reveal_lock_count_ >= 0);
 }
 
-bool ImmersiveModeController::IsToolbarRevealed() {
+bool ImmersiveModeControllerCocoa::IsToolbarRevealed() {
   // If `fullScreenMinHeight` is not `kMinHeight`, "Always Show Toolbar in Full
   // Screen" is enabled. If `revealAmount` > 0, the toolbar is revealed
   // because of mouse hovering. In both cases, the toolbar is visible.
@@ -486,7 +487,7 @@
          immersive_mode_titlebar_view_controller_.revealAmount > 0;
 }
 
-void ImmersiveModeController::OnToolbarRevealMaybeChanged() {
+void ImmersiveModeControllerCocoa::OnToolbarRevealMaybeChanged() {
   bool is_toolbar_revealed = IsToolbarRevealed();
   if (is_toolbar_revealed_ != is_toolbar_revealed) {
     is_toolbar_revealed_ = is_toolbar_revealed;
@@ -494,7 +495,7 @@
   }
 }
 
-void ImmersiveModeController::OnMenuBarRevealChanged() {
+void ImmersiveModeControllerCocoa::OnMenuBarRevealChanged() {
   if (NativeWidgetNSWindowBridge* bridge =
           NativeWidgetNSWindowBridge::GetFromNativeWindow(browser_window_)) {
     bridge->OnImmersiveFullscreenMenuBarRevealChanged(
@@ -502,7 +503,7 @@
   }
 }
 
-void ImmersiveModeController::ImmersiveModeViewWillMoveToWindow(
+void ImmersiveModeControllerCocoa::ImmersiveModeViewWillMoveToWindow(
     NSWindow* window) {
   // AppKit hands this view controller over to a fullscreen transition window
   // before we finally land at the NSToolbarFullScreenWindow. Add the frame
@@ -535,15 +536,15 @@
   }
 }
 
-void ImmersiveModeController::OnTitlebarFrameDidChange(NSRect frame) {
+void ImmersiveModeControllerCocoa::OnTitlebarFrameDidChange(NSRect frame) {
   LayoutWindowWithAnchorView(overlay_window_, overlay_content_view_);
 }
 
-bool ImmersiveModeController::IsTabbed() {
+bool ImmersiveModeControllerCocoa::IsTabbed() {
   return false;
 }
 
-double ImmersiveModeController::GetOffscreenYOrigin() {
+double ImmersiveModeControllerCocoa::GetOffscreenYOrigin() {
   // Get the height of the screen. Using this as the y origin will move a window
   // offscreen.
   double y = browser_window_.screen.frame.size.height;
@@ -557,15 +558,17 @@
   return y;
 }
 
-void ImmersiveModeController::NotifyBrowserWindowAboutToolbarRevealChanged() {
+void ImmersiveModeControllerCocoa::
+    NotifyBrowserWindowAboutToolbarRevealChanged() {
   if (NativeWidgetNSWindowBridge* bridge =
           NativeWidgetNSWindowBridge::GetFromNativeWindow(browser_window_)) {
     bridge->OnImmersiveFullscreenToolbarRevealChanged(IsToolbarRevealed());
   }
 }
 
-void ImmersiveModeController::LayoutWindowWithAnchorView(NSWindow* window,
-                                                         NSView* anchor_view) {
+void ImmersiveModeControllerCocoa::LayoutWindowWithAnchorView(
+    NSWindow* window,
+    NSView* anchor_view) {
   // Find the anchor view's point on screen (bottom left).
   NSPoint point_in_window = [anchor_view convertPoint:NSZeroPoint toView:nil];
   NSPoint point_on_screen =
diff --git a/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h b/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.h
similarity index 81%
rename from components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h
rename to components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.h
index 834edad..1f0d988 100644
--- a/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h
+++ b/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_TABBED_CONTROLLER_H_
-#define COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_TABBED_CONTROLLER_H_
+#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_TABBED_CONTROLLER_COCOA_H_
+#define COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_TABBED_CONTROLLER_COCOA_H_
 
-#include "components/remote_cocoa/app_shim/immersive_mode_controller.h"
+#include "components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.h"
 
 #import "components/remote_cocoa/app_shim/bridged_content_view.h"
 
@@ -13,17 +13,18 @@
 
 namespace remote_cocoa {
 
-class REMOTE_COCOA_APP_SHIM_EXPORT ImmersiveModeTabbedController
-    : public ImmersiveModeController {
+class REMOTE_COCOA_APP_SHIM_EXPORT ImmersiveModeTabbedControllerCocoa
+    : public ImmersiveModeControllerCocoa {
  public:
-  explicit ImmersiveModeTabbedController(
+  explicit ImmersiveModeTabbedControllerCocoa(
       NativeWidgetMacNSWindow* browser_window,
       NativeWidgetMacNSWindow* overlay_window,
       NativeWidgetMacNSWindow* tab_window);
-  ImmersiveModeTabbedController(const ImmersiveModeTabbedController&) = delete;
-  ImmersiveModeTabbedController& operator=(
-      const ImmersiveModeTabbedController&) = delete;
-  ~ImmersiveModeTabbedController() override;
+  ImmersiveModeTabbedControllerCocoa(
+      const ImmersiveModeTabbedControllerCocoa&) = delete;
+  ImmersiveModeTabbedControllerCocoa& operator=(
+      const ImmersiveModeTabbedControllerCocoa&) = delete;
+  ~ImmersiveModeTabbedControllerCocoa() override;
 
   // ImmersiveModeController overrides
   // TODO(https://crbug.com/1426944): Init() does not add the controller. It
@@ -58,4 +59,4 @@
 
 }  // namespace remote_cocoa
 
-#endif  // COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_TABBED_CONTROLLER_H_
+#endif  // COMPONENTS_REMOTE_COCOA_APP_SHIM_IMMERSIVE_MODE_TABBED_CONTROLLER__COCOA_H_
diff --git a/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.mm b/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.mm
similarity index 79%
rename from components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.mm
rename to components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.mm
index a9d85b8..f43f74aa 100644
--- a/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.mm
+++ b/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.mm
@@ -2,20 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h"
+#include "components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.h"
 
 #include "base/apple/foundation_util.h"
 #include "base/functional/callback_forward.h"
 #import "components/remote_cocoa/app_shim/bridged_content_view.h"
-#include "components/remote_cocoa/app_shim/immersive_mode_controller.h"
 
 namespace remote_cocoa {
 
-ImmersiveModeTabbedController::ImmersiveModeTabbedController(
+ImmersiveModeTabbedControllerCocoa::ImmersiveModeTabbedControllerCocoa(
     NativeWidgetMacNSWindow* browser_window,
     NativeWidgetMacNSWindow* overlay_window,
     NativeWidgetMacNSWindow* tab_window)
-    : ImmersiveModeController(browser_window, overlay_window) {
+    : ImmersiveModeControllerCocoa(browser_window, overlay_window) {
   tab_window_ = tab_window;
 
   browser_window.titleVisibility = NSWindowTitleHidden;
@@ -30,7 +29,7 @@
   tab_titlebar_view_controller_.layoutAttribute = NSLayoutAttributeTrailing;
 }
 
-ImmersiveModeTabbedController::~ImmersiveModeTabbedController() {
+ImmersiveModeTabbedControllerCocoa::~ImmersiveModeTabbedControllerCocoa() {
   StopObservingChildWindows(tab_window_);
   browser_window().toolbar = nil;
   BridgedContentView* tab_content_view = tab_content_view_;
@@ -40,8 +39,8 @@
   tab_titlebar_view_controller_ = nil;
 }
 
-void ImmersiveModeTabbedController::Init() {
-  ImmersiveModeController::Init();
+void ImmersiveModeTabbedControllerCocoa::Init() {
+  ImmersiveModeControllerCocoa::Init();
   BridgedContentView* tab_content_view =
       base::apple::ObjCCastStrict<BridgedContentView>(tab_window_.contentView);
   [tab_content_view removeFromSuperview];
@@ -94,7 +93,7 @@
   UpdateToolbarVisibility(last_used_style());
 }
 
-void ImmersiveModeTabbedController::UpdateToolbarVisibility(
+void ImmersiveModeTabbedControllerCocoa::UpdateToolbarVisibility(
     mojom::ToolbarVisibilityStyle style) {
   // Don't make changes when a reveal lock is active. Do update the
   // `last_used_style` so the style will be updated once all outstanding reveal
@@ -123,7 +122,7 @@
       TitlebarHide();
       break;
   }
-  ImmersiveModeController::UpdateToolbarVisibility(style);
+  ImmersiveModeControllerCocoa::UpdateToolbarVisibility(style);
 
   // During fullscreen restore or split screen restore tab window can be left
   // without a parent, leading to the window being hidden which causes
@@ -139,7 +138,7 @@
   LayoutWindowWithAnchorView(tab_window_, tab_content_view_);
 }
 
-void ImmersiveModeTabbedController::AddController() {
+void ImmersiveModeTabbedControllerCocoa::AddController() {
   NSWindow* window = browser_window();
   if (![window.titlebarAccessoryViewControllers
           containsObject:tab_titlebar_view_controller_]) {
@@ -147,13 +146,13 @@
   }
 }
 
-void ImmersiveModeTabbedController::RemoveController() {
+void ImmersiveModeTabbedControllerCocoa::RemoveController() {
   [tab_titlebar_view_controller_ removeFromParentViewController];
 }
 
-void ImmersiveModeTabbedController::OnTopViewBoundsChanged(
+void ImmersiveModeTabbedControllerCocoa::OnTopViewBoundsChanged(
     const gfx::Rect& bounds) {
-  ImmersiveModeController::OnTopViewBoundsChanged(bounds);
+  ImmersiveModeControllerCocoa::OnTopViewBoundsChanged(bounds);
   NSRect frame = NSRectFromCGRect(bounds.ToCGRect());
   [tab_titlebar_view_controller_.view
       setFrameSize:NSMakeSize(
@@ -161,41 +160,43 @@
                        tab_titlebar_view_controller_.view.frame.size.height)];
 }
 
-void ImmersiveModeTabbedController::RevealLock() {
+void ImmersiveModeTabbedControllerCocoa::RevealLock() {
   TitlebarReveal();
 
   // Call after TitlebarReveal() for a proper layout.
-  ImmersiveModeController::RevealLock();
+  ImmersiveModeControllerCocoa::RevealLock();
   LayoutWindowWithAnchorView(tab_window_, tab_content_view_);
 }
 
-void ImmersiveModeTabbedController::RevealUnlock() {
+void ImmersiveModeTabbedControllerCocoa::RevealUnlock() {
   // The reveal lock count will be updated in
-  // ImmersiveModeController::RevealUnlock(), count 1 or less here as unlocked.
+  // ImmersiveModeControllerCocoa::RevealUnlock(), count 1 or less here as
+  // unlocked.
   if (reveal_lock_count() < 2 &&
       last_used_style() == mojom::ToolbarVisibilityStyle::kAutohide) {
     TitlebarHide();
   }
 
   // Call after TitlebarHide() for a proper layout.
-  ImmersiveModeController::RevealUnlock();
+  ImmersiveModeControllerCocoa::RevealUnlock();
   LayoutWindowWithAnchorView(tab_window_, tab_content_view_);
 }
 
-void ImmersiveModeTabbedController::TitlebarReveal() {
+void ImmersiveModeTabbedControllerCocoa::TitlebarReveal() {
   browser_window().toolbar.visible = YES;
 }
 
-void ImmersiveModeTabbedController::TitlebarHide() {
+void ImmersiveModeTabbedControllerCocoa::TitlebarHide() {
   browser_window().toolbar.visible = NO;
 }
 
-void ImmersiveModeTabbedController::OnTitlebarFrameDidChange(NSRect frame) {
-  ImmersiveModeController::OnTitlebarFrameDidChange(frame);
+void ImmersiveModeTabbedControllerCocoa::OnTitlebarFrameDidChange(
+    NSRect frame) {
+  ImmersiveModeControllerCocoa::OnTitlebarFrameDidChange(frame);
   LayoutWindowWithAnchorView(tab_window_, tab_content_view_);
 }
 
-void ImmersiveModeTabbedController::OnChildWindowAdded(NSWindow* child) {
+void ImmersiveModeTabbedControllerCocoa::OnChildWindowAdded(NSWindow* child) {
   // The `tab_window_` is a child of the `overlay_window_`. Ignore
   // the `tab_window_`.
   if (child == tab_window_) {
@@ -203,31 +204,32 @@
   }
 
   OrderTabWindowZOrderOnTop();
-  ImmersiveModeController::OnChildWindowAdded(child);
+  ImmersiveModeControllerCocoa::OnChildWindowAdded(child);
 }
 
-void ImmersiveModeTabbedController::OnChildWindowRemoved(NSWindow* child) {
+void ImmersiveModeTabbedControllerCocoa::OnChildWindowRemoved(NSWindow* child) {
   // The `tab_window_` is a child of the `overlay_window_`. Ignore
   // the `tab_window_`.
   if (child == tab_window_) {
     return;
   }
-  ImmersiveModeController::OnChildWindowRemoved(child);
+  ImmersiveModeControllerCocoa::OnChildWindowRemoved(child);
 }
 
-bool ImmersiveModeTabbedController::ShouldObserveChildWindow(NSWindow* child) {
+bool ImmersiveModeTabbedControllerCocoa::ShouldObserveChildWindow(
+    NSWindow* child) {
   // Filter out the `tab_window_`.
   if (child == tab_window_) {
     return false;
   }
-  return ImmersiveModeController::ShouldObserveChildWindow(child);
+  return ImmersiveModeControllerCocoa::ShouldObserveChildWindow(child);
 }
 
-bool ImmersiveModeTabbedController::IsTabbed() {
+bool ImmersiveModeTabbedControllerCocoa::IsTabbed() {
   return true;
 }
 
-void ImmersiveModeTabbedController::OrderTabWindowZOrderOnTop() {
+void ImmersiveModeTabbedControllerCocoa::OrderTabWindowZOrderOnTop() {
   // Keep the tab window on top of its siblings. This will allow children of tab
   // window to always be z-order on top of overlay window children.
   // Practically this allows for the tab preview hover card to be z-order on top
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
index f4d631e7..26a4fb1 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
@@ -12,8 +12,8 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "components/remote_cocoa/app_shim/immersive_mode_controller.h"
-#include "components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h"
+#include "components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.h"
+#include "components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.h"
 #import "components/remote_cocoa/app_shim/mouse_capture_delegate.h"
 #include "components/remote_cocoa/app_shim/native_widget_ns_window_fullscreen_controller.h"
 #include "components/remote_cocoa/app_shim/ns_view_ids.h"
@@ -425,7 +425,7 @@
   std::vector<uint8_t> pending_restoration_data_;
 
   // Manages immersive mode when in fullscreen.
-  std::unique_ptr<ImmersiveModeController> immersive_mode_controller_;
+  std::unique_ptr<ImmersiveModeControllerCocoa> immersive_mode_controller_;
 
   // This tracks headless window visibility and fullscreen states.
   // In headless mode the platform window is never made visible or change its
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index 9a118ce0..1a51ad6 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -972,11 +972,11 @@
   if (tab_widget_bridge) {
     NSWindow* tab_window = tab_widget_bridge->ns_window();
     immersive_mode_controller_ =
-        std::make_unique<ImmersiveModeTabbedController>(
+        std::make_unique<ImmersiveModeTabbedControllerCocoa>(
             ns_window(), GetFromId(fullscreen_overlay_widget_id)->ns_window(),
             tab_window);
   } else {
-    immersive_mode_controller_ = std::make_unique<ImmersiveModeController>(
+    immersive_mode_controller_ = std::make_unique<ImmersiveModeControllerCocoa>(
         ns_window(), GetFromId(fullscreen_overlay_widget_id)->ns_window());
   }
   immersive_mode_controller_->Init();
diff --git a/components/segmentation_platform/embedder/default_model/low_user_engagement_model.cc b/components/segmentation_platform/embedder/default_model/low_user_engagement_model.cc
index e43c564..4641753 100644
--- a/components/segmentation_platform/embedder/default_model/low_user_engagement_model.cc
+++ b/components/segmentation_platform/embedder/default_model/low_user_engagement_model.cc
@@ -24,6 +24,7 @@
     SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT;
 constexpr int64_t kChromeStartSignalStorageLength = 28;
 constexpr int64_t kChromeStartMinSignalCollectionLength = 28;
+constexpr int64_t kModelVersion = 2;
 
 // InputFeatures.
 constexpr std::array<MetadataWriter::UMAFeature, 1> kChromeStartUMAFeatures = {
@@ -51,15 +52,6 @@
   config->AddSegmentId(kChromeStartSegmentId,
                        std::make_unique<LowUserEngagementModel>());
   config->auto_execute_and_cache = true;
-
-  int segment_selection_ttl_days = base::GetFieldTrialParamByFeatureAsInt(
-      features::kSegmentationPlatformLowEngagementFeature,
-      kVariationsParamNameSegmentSelectionTTLDays, 7);
-  int unknown_selection_ttl_days = base::GetFieldTrialParamByFeatureAsInt(
-      features::kSegmentationPlatformLowEngagementFeature,
-      kVariationsParamNameUnknownSelectionTTLDays, 7);
-  config->segment_selection_ttl = base::Days(segment_selection_ttl_days);
-  config->unknown_selection_ttl = base::Days(unknown_selection_ttl_days);
   config->is_boolean_segment = true;
 
   return config;
@@ -72,15 +64,20 @@
   writer.SetDefaultSegmentationMetadataConfig(
       kChromeStartMinSignalCollectionLength, kChromeStartSignalStorageLength);
 
-  // Set discrete mapping.
-  writer.AddBooleanSegmentDiscreteMapping(
-      kChromeLowUserEngagementSegmentationKey);
-
   // Set features.
   writer.AddUmaFeatures(kChromeStartUMAFeatures.data(),
                         kChromeStartUMAFeatures.size());
 
-  constexpr int kModelVersion = 1;
+  // Set OutputConfig.
+  writer.AddOutputConfigForBinaryClassifier(
+      /*threshold=*/0.5f,
+      /*positive_label=*/kChromeLowUserEngagementUmaName,
+      /*negative_label=*/kLegacyNegativeLabel);
+
+  writer.AddPredictedResultTTLInOutputConfig(
+      /*top_label_to_ttl_list=*/{}, /*default_ttl=*/7,
+      /*time_unit=*/proto::TimeUnit::DAY);
+
   return std::make_unique<ModelConfig>(std::move(chrome_start_metadata),
                                        kModelVersion);
 }
diff --git a/components/segmentation_platform/embedder/default_model/low_user_engagement_model_unittest.cc b/components/segmentation_platform/embedder/default_model/low_user_engagement_model_unittest.cc
index b342ccb..0ad8bb1 100644
--- a/components/segmentation_platform/embedder/default_model/low_user_engagement_model_unittest.cc
+++ b/components/segmentation_platform/embedder/default_model/low_user_engagement_model_unittest.cc
@@ -17,33 +17,32 @@
 
 TEST_F(LowUserEngagementModelTest, 2) {
   ExpectInitAndFetchModel();
+  ASSERT_TRUE(fetched_metadata_);
 }
 
 TEST_F(LowUserEngagementModelTest, ExecuteModelWithInput) {
+  ExpectInitAndFetchModel();
+  ASSERT_TRUE(fetched_metadata_);
+
+  EXPECT_FALSE(ExecuteWithInput(/*inputs=*/{}));
+
   ModelProvider::Request input;
-  ExpectExecutionWithInput(input, /*expected_error=*/true,
-                           /*expected_result=*/{0});
 
-  input.assign(27, 0);
-  ExpectExecutionWithInput(input, /*expected_error=*/true,
-                           /*expected_result=*/{0});
-
+  // Low engaged users.
   input.assign(28, 0);
-  ExpectExecutionWithInput(input, /*expected_error=*/false,
-                           /*expected_result=*/{1});
+  ExpectClassifierResults(input, {kChromeLowUserEngagementUmaName});
 
   input.assign(21, 0);
   input.insert(input.end(), 7, 1);
-  ExpectExecutionWithInput(input, /*expected_error=*/false,
-                           /*expected_result=*/{1});
+  ExpectClassifierResults(input, {kChromeLowUserEngagementUmaName});
 
+  // Not low engaged users.
   input.assign(28, 0);
   input[1] = 2;
   input[8] = 3;
   input[15] = 4;
   input[22] = 2;
-  ExpectExecutionWithInput(input, /*expected_error=*/false,
-                           /*expected_result=*/{0});
+  ExpectClassifierResults(input, {kLegacyNegativeLabel});
 }
 
 }  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/metadata/metadata_utils.cc b/components/segmentation_platform/internal/metadata/metadata_utils.cc
index d11f246..dd7253e 100644
--- a/components/segmentation_platform/internal/metadata/metadata_utils.cc
+++ b/components/segmentation_platform/internal/metadata/metadata_utils.cc
@@ -590,7 +590,6 @@
       SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE,
       SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID,
       SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_QUERY_TILES,
-      SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT,
       SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_FEED_USER,
       SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID_V2,
       SegmentId::CROSS_DEVICE_USER_SEGMENT};
diff --git a/components/segmentation_platform/internal/segmentation_ukm_helper.cc b/components/segmentation_platform/internal/segmentation_ukm_helper.cc
index 7d1af63..2c17365 100644
--- a/components/segmentation_platform/internal/segmentation_ukm_helper.cc
+++ b/components/segmentation_platform/internal/segmentation_ukm_helper.cc
@@ -170,7 +170,6 @@
         SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_DUMMY,
         SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID,
         SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_QUERY_TILES,
-        SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT,
         SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID_V2};
   }
   sampling_rate_ = GetModelExecutionSamplingRate();
diff --git a/components/services/screen_ai/BUILD.gn b/components/services/screen_ai/BUILD.gn
index c70a5b7..f41c6c0 100644
--- a/components/services/screen_ai/BUILD.gn
+++ b/components/services/screen_ai/BUILD.gn
@@ -27,6 +27,8 @@
     "//skia",
     "//ui/accessibility:accessibility",
   ]
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
 if (is_linux || is_chromeos) {
@@ -45,6 +47,8 @@
     ]
 
     public_deps = [ "//sandbox/policy" ]
+
+    configs += [ "//build/config/compiler:wexit_time_destructors" ]
   }
 }
 
diff --git a/components/services/screen_ai/proto/BUILD.gn b/components/services/screen_ai/proto/BUILD.gn
index 9331026..9360094 100644
--- a/components/services/screen_ai/proto/BUILD.gn
+++ b/components/services/screen_ai/proto/BUILD.gn
@@ -34,4 +34,6 @@
     "//components/strings:components_strings_grit",
     "//ui/accessibility",
   ]
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
diff --git a/components/services/screen_ai/proto/main_content_extractor_proto_convertor.cc b/components/services/screen_ai/proto/main_content_extractor_proto_convertor.cc
index ecd7732d..8f281be 100644
--- a/components/services/screen_ai/proto/main_content_extractor_proto_convertor.cc
+++ b/components/services/screen_ai/proto/main_content_extractor_proto_convertor.cc
@@ -5,7 +5,9 @@
 #include "components/services/screen_ai/proto/main_content_extractor_proto_convertor.h"
 
 #include "base/check_op.h"
-#include "base/containers/flat_set.h"
+#include "base/containers/contains.h"
+#include "base/containers/fixed_flat_map.h"
+#include "base/containers/fixed_flat_set.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "components/services/screen_ai/proto/view_hierarchy.pb.h"
@@ -26,126 +28,129 @@
 std::string GetMainContentExtractorRoleFromChromeRole(ax::mojom::Role role) {
   std::string role_name = ui::ToString(role);
 
-  static base::flat_set<ax::mojom::Role> roles_with_similar_name = {
-      ax::mojom::Role::kAlert,       ax::mojom::Role::kArticle,
-      ax::mojom::Role::kBanner,      ax::mojom::Role::kBlockquote,
-      ax::mojom::Role::kButton,      ax::mojom::Role::kCaption,
-      ax::mojom::Role::kCell,        ax::mojom::Role::kCode,
-      ax::mojom::Role::kComment,     ax::mojom::Role::kComplementary,
-      ax::mojom::Role::kDefinition,  ax::mojom::Role::kDialog,
-      ax::mojom::Role::kDirectory,   ax::mojom::Role::kDocument,
-      ax::mojom::Role::kEmphasis,    ax::mojom::Role::kFeed,
-      ax::mojom::Role::kFigure,      ax::mojom::Role::kForm,
-      ax::mojom::Role::kGrid,        ax::mojom::Role::kGroup,
-      ax::mojom::Role::kHeading,     ax::mojom::Role::kLink,
-      ax::mojom::Role::kList,        ax::mojom::Role::kLog,
-      ax::mojom::Role::kMain,        ax::mojom::Role::kMarquee,
-      ax::mojom::Role::kMath,        ax::mojom::Role::kMenu,
-      ax::mojom::Role::kMark,        ax::mojom::Role::kMeter,
-      ax::mojom::Role::kNavigation,  ax::mojom::Role::kNone,
-      ax::mojom::Role::kNote,        ax::mojom::Role::kParagraph,
-      ax::mojom::Role::kRegion,      ax::mojom::Role::kRow,
-      ax::mojom::Role::kSearch,      ax::mojom::Role::kSlider,
-      ax::mojom::Role::kStatus,      ax::mojom::Role::kStrong,
-      ax::mojom::Role::kSubscript,   ax::mojom::Role::kSuggestion,
-      ax::mojom::Role::kSuperscript, ax::mojom::Role::kSwitch,
-      ax::mojom::Role::kTab,         ax::mojom::Role::kTable,
-      ax::mojom::Role::kTerm,        ax::mojom::Role::kTime,
-      ax::mojom::Role::kTimer,       ax::mojom::Role::kToolbar,
-      ax::mojom::Role::kTooltip,     ax::mojom::Role::kTree,
-  };
-  if (roles_with_similar_name.find(role) != roles_with_similar_name.end())
+  constexpr auto kRolesWithSimilarName =
+      base::MakeFixedFlatSet<ax::mojom::Role>({
+          ax::mojom::Role::kAlert,       ax::mojom::Role::kArticle,
+          ax::mojom::Role::kBanner,      ax::mojom::Role::kBlockquote,
+          ax::mojom::Role::kButton,      ax::mojom::Role::kCaption,
+          ax::mojom::Role::kCell,        ax::mojom::Role::kCode,
+          ax::mojom::Role::kComment,     ax::mojom::Role::kComplementary,
+          ax::mojom::Role::kDefinition,  ax::mojom::Role::kDialog,
+          ax::mojom::Role::kDirectory,   ax::mojom::Role::kDocument,
+          ax::mojom::Role::kEmphasis,    ax::mojom::Role::kFeed,
+          ax::mojom::Role::kFigure,      ax::mojom::Role::kForm,
+          ax::mojom::Role::kGrid,        ax::mojom::Role::kGroup,
+          ax::mojom::Role::kHeading,     ax::mojom::Role::kLink,
+          ax::mojom::Role::kList,        ax::mojom::Role::kLog,
+          ax::mojom::Role::kMain,        ax::mojom::Role::kMarquee,
+          ax::mojom::Role::kMath,        ax::mojom::Role::kMenu,
+          ax::mojom::Role::kMark,        ax::mojom::Role::kMeter,
+          ax::mojom::Role::kNavigation,  ax::mojom::Role::kNone,
+          ax::mojom::Role::kNote,        ax::mojom::Role::kParagraph,
+          ax::mojom::Role::kRegion,      ax::mojom::Role::kRow,
+          ax::mojom::Role::kSearch,      ax::mojom::Role::kSlider,
+          ax::mojom::Role::kStatus,      ax::mojom::Role::kStrong,
+          ax::mojom::Role::kSubscript,   ax::mojom::Role::kSuggestion,
+          ax::mojom::Role::kSuperscript, ax::mojom::Role::kSwitch,
+          ax::mojom::Role::kTab,         ax::mojom::Role::kTable,
+          ax::mojom::Role::kTerm,        ax::mojom::Role::kTime,
+          ax::mojom::Role::kTimer,       ax::mojom::Role::kToolbar,
+          ax::mojom::Role::kTooltip,     ax::mojom::Role::kTree,
+      });
+  if (base::Contains(kRolesWithSimilarName, role)) {
     return role_name;
+  }
 
-  static base::flat_set<ax::mojom::Role> roles_with_all_lowercase_name = {
-      ax::mojom::Role::kAlertDialog,   ax::mojom::Role::kApplication,
-      ax::mojom::Role::kCheckBox,      ax::mojom::Role::kColumnHeader,
-      ax::mojom::Role::kContentInfo,   ax::mojom::Role::kListBox,
-      ax::mojom::Role::kListItem,      ax::mojom::Role::kMenuBar,
-      ax::mojom::Role::kMenuItem,      ax::mojom::Role::kMenuItemCheckBox,
-      ax::mojom::Role::kMenuItemRadio, ax::mojom::Role::kRadioGroup,
-      ax::mojom::Role::kRowGroup,      ax::mojom::Role::kRowHeader,
-      ax::mojom::Role::kScrollBar,     ax::mojom::Role::kSearchBox,
-      ax::mojom::Role::kSpinButton,    ax::mojom::Role::kTabList,
-      ax::mojom::Role::kTabPanel,      ax::mojom::Role::kTreeItem,
-  };
-  if (roles_with_all_lowercase_name.find(role) !=
-      roles_with_all_lowercase_name.end()) {
+  constexpr auto kRolesWithAllLowercaseName =
+      base::MakeFixedFlatSet<ax::mojom::Role>({
+          ax::mojom::Role::kAlertDialog,   ax::mojom::Role::kApplication,
+          ax::mojom::Role::kCheckBox,      ax::mojom::Role::kColumnHeader,
+          ax::mojom::Role::kContentInfo,   ax::mojom::Role::kListBox,
+          ax::mojom::Role::kListItem,      ax::mojom::Role::kMenuBar,
+          ax::mojom::Role::kMenuItem,      ax::mojom::Role::kMenuItemCheckBox,
+          ax::mojom::Role::kMenuItemRadio, ax::mojom::Role::kRadioGroup,
+          ax::mojom::Role::kRowGroup,      ax::mojom::Role::kRowHeader,
+          ax::mojom::Role::kScrollBar,     ax::mojom::Role::kSearchBox,
+          ax::mojom::Role::kSpinButton,    ax::mojom::Role::kTabList,
+          ax::mojom::Role::kTabPanel,      ax::mojom::Role::kTreeItem,
+      });
+  if (base::Contains(kRolesWithAllLowercaseName, role)) {
     return base::ToLowerASCII(role_name);
   }
 
-  static base::flat_map<ax::mojom::Role, std::string>
-      roles_with_different_name = {
-          // Aria Roles.
-          {ax::mojom::Role::kComboBoxGrouping, "combobox"},
-          {ax::mojom::Role::kComboBoxSelect, "combobox"},
-          {ax::mojom::Role::kContentDeletion, "deletion"},
-          {ax::mojom::Role::kDocAbstract, "doc-abstract"},
-          {ax::mojom::Role::kDocAcknowledgments, "doc-acknowledgments"},
-          {ax::mojom::Role::kDocAfterword, "doc-afterword"},
-          {ax::mojom::Role::kDocAppendix, "doc-appendix"},
-          {ax::mojom::Role::kDocBackLink, "doc-backlink"},
-          {ax::mojom::Role::kDocBiblioEntry, "doc-biblioentry"},
-          {ax::mojom::Role::kDocBibliography, "doc-bibliography"},
-          {ax::mojom::Role::kDocBiblioRef, "doc-biblioref"},
-          {ax::mojom::Role::kDocChapter, "doc-chapter"},
-          {ax::mojom::Role::kDocColophon, "doc-colophon"},
-          {ax::mojom::Role::kDocConclusion, "doc-conclusion"},
-          {ax::mojom::Role::kDocCover, "doc-cover"},
-          {ax::mojom::Role::kDocCredit, "doc-credit"},
-          {ax::mojom::Role::kDocCredits, "doc-credits"},
-          {ax::mojom::Role::kDocDedication, "doc-dedication"},
-          {ax::mojom::Role::kDocEndnote, "doc-endnote"},
-          {ax::mojom::Role::kDocEndnotes, "doc-endnotes"},
-          {ax::mojom::Role::kDocEpigraph, "doc-epigraph"},
-          {ax::mojom::Role::kDocEpilogue, "doc-epilogue"},
-          {ax::mojom::Role::kDocErrata, "doc-errata"},
-          {ax::mojom::Role::kDocExample, "doc-example"},
-          {ax::mojom::Role::kDocFootnote, "doc-footnote"},
-          {ax::mojom::Role::kDocForeword, "doc-foreword"},
-          {ax::mojom::Role::kDocGlossary, "doc-glossary"},
-          {ax::mojom::Role::kDocGlossRef, "doc-glossref"},
-          {ax::mojom::Role::kDocIndex, "doc-index"},
-          {ax::mojom::Role::kDocIntroduction, "doc-introduction"},
-          {ax::mojom::Role::kDocNoteRef, "doc-noteref"},
-          {ax::mojom::Role::kDocNotice, "doc-notice"},
-          {ax::mojom::Role::kDocPageBreak, "doc-pagebreak"},
-          {ax::mojom::Role::kDocPageFooter, "doc-pagefooter"},
-          {ax::mojom::Role::kDocPageHeader, "doc-pageheader"},
-          {ax::mojom::Role::kDocPageList, "doc-pagelist"},
-          {ax::mojom::Role::kDocPart, "doc-part"},
-          {ax::mojom::Role::kDocPreface, "doc-preface"},
-          {ax::mojom::Role::kDocPrologue, "doc-prologue"},
-          {ax::mojom::Role::kDocPullquote, "doc-pullquote"},
-          {ax::mojom::Role::kDocQna, "doc-qna"},
-          {ax::mojom::Role::kDocSubtitle, "doc-subtitle"},
-          {ax::mojom::Role::kDocTip, "doc-tip"},
-          {ax::mojom::Role::kDocToc, "doc-toc"},
-          {ax::mojom::Role::kGenericContainer, "generic"},
-          {ax::mojom::Role::kGraphicsDocument, "graphics-document"},
-          {ax::mojom::Role::kGraphicsObject, "graphics-object"},
-          {ax::mojom::Role::kGraphicsSymbol, "graphics-symbol"},
-          {ax::mojom::Role::kCell, "gridcell"},
-          {ax::mojom::Role::kImage, "img"},
-          {ax::mojom::Role::kContentInsertion, "insertion"},
-          {ax::mojom::Role::kListBoxOption, "option"},
-          {ax::mojom::Role::kProgressIndicator, "progressbar"},
-          {ax::mojom::Role::kRadioButton, "radio"},
-          {ax::mojom::Role::kSplitter, "separator"},
-          {ax::mojom::Role::kTextField, "textbox"},
-          {ax::mojom::Role::kTreeGrid, "treegrid"},
-          // Reverse Roles
-          {ax::mojom::Role::kHeader, "banner"},
-          {ax::mojom::Role::kToggleButton, "button"},
-          {ax::mojom::Role::kPopUpButton, "combobox"},
-          {ax::mojom::Role::kFooter, "contentinfo"},
-          {ax::mojom::Role::kMenuListOption, "menuitem"},
-          {ax::mojom::Role::kComboBoxMenuButton, "combobox"},
-          {ax::mojom::Role::kTextFieldWithComboBox, "combobox"}};
+  constexpr auto kRolesWithDifferentName =
+      base::MakeFixedFlatMap<ax::mojom::Role, std::string_view>(
+          {// Aria Roles.
+           {ax::mojom::Role::kComboBoxGrouping, "combobox"},
+           {ax::mojom::Role::kComboBoxSelect, "combobox"},
+           {ax::mojom::Role::kContentDeletion, "deletion"},
+           {ax::mojom::Role::kDocAbstract, "doc-abstract"},
+           {ax::mojom::Role::kDocAcknowledgments, "doc-acknowledgments"},
+           {ax::mojom::Role::kDocAfterword, "doc-afterword"},
+           {ax::mojom::Role::kDocAppendix, "doc-appendix"},
+           {ax::mojom::Role::kDocBackLink, "doc-backlink"},
+           {ax::mojom::Role::kDocBiblioEntry, "doc-biblioentry"},
+           {ax::mojom::Role::kDocBibliography, "doc-bibliography"},
+           {ax::mojom::Role::kDocBiblioRef, "doc-biblioref"},
+           {ax::mojom::Role::kDocChapter, "doc-chapter"},
+           {ax::mojom::Role::kDocColophon, "doc-colophon"},
+           {ax::mojom::Role::kDocConclusion, "doc-conclusion"},
+           {ax::mojom::Role::kDocCover, "doc-cover"},
+           {ax::mojom::Role::kDocCredit, "doc-credit"},
+           {ax::mojom::Role::kDocCredits, "doc-credits"},
+           {ax::mojom::Role::kDocDedication, "doc-dedication"},
+           {ax::mojom::Role::kDocEndnote, "doc-endnote"},
+           {ax::mojom::Role::kDocEndnotes, "doc-endnotes"},
+           {ax::mojom::Role::kDocEpigraph, "doc-epigraph"},
+           {ax::mojom::Role::kDocEpilogue, "doc-epilogue"},
+           {ax::mojom::Role::kDocErrata, "doc-errata"},
+           {ax::mojom::Role::kDocExample, "doc-example"},
+           {ax::mojom::Role::kDocFootnote, "doc-footnote"},
+           {ax::mojom::Role::kDocForeword, "doc-foreword"},
+           {ax::mojom::Role::kDocGlossary, "doc-glossary"},
+           {ax::mojom::Role::kDocGlossRef, "doc-glossref"},
+           {ax::mojom::Role::kDocIndex, "doc-index"},
+           {ax::mojom::Role::kDocIntroduction, "doc-introduction"},
+           {ax::mojom::Role::kDocNoteRef, "doc-noteref"},
+           {ax::mojom::Role::kDocNotice, "doc-notice"},
+           {ax::mojom::Role::kDocPageBreak, "doc-pagebreak"},
+           {ax::mojom::Role::kDocPageFooter, "doc-pagefooter"},
+           {ax::mojom::Role::kDocPageHeader, "doc-pageheader"},
+           {ax::mojom::Role::kDocPageList, "doc-pagelist"},
+           {ax::mojom::Role::kDocPart, "doc-part"},
+           {ax::mojom::Role::kDocPreface, "doc-preface"},
+           {ax::mojom::Role::kDocPrologue, "doc-prologue"},
+           {ax::mojom::Role::kDocPullquote, "doc-pullquote"},
+           {ax::mojom::Role::kDocQna, "doc-qna"},
+           {ax::mojom::Role::kDocSubtitle, "doc-subtitle"},
+           {ax::mojom::Role::kDocTip, "doc-tip"},
+           {ax::mojom::Role::kDocToc, "doc-toc"},
+           {ax::mojom::Role::kGenericContainer, "generic"},
+           {ax::mojom::Role::kGraphicsDocument, "graphics-document"},
+           {ax::mojom::Role::kGraphicsObject, "graphics-object"},
+           {ax::mojom::Role::kGraphicsSymbol, "graphics-symbol"},
+           {ax::mojom::Role::kCell, "gridcell"},
+           {ax::mojom::Role::kImage, "img"},
+           {ax::mojom::Role::kContentInsertion, "insertion"},
+           {ax::mojom::Role::kListBoxOption, "option"},
+           {ax::mojom::Role::kProgressIndicator, "progressbar"},
+           {ax::mojom::Role::kRadioButton, "radio"},
+           {ax::mojom::Role::kSplitter, "separator"},
+           {ax::mojom::Role::kTextField, "textbox"},
+           {ax::mojom::Role::kTreeGrid, "treegrid"},
+           // Reverse Roles
+           {ax::mojom::Role::kHeader, "banner"},
+           {ax::mojom::Role::kToggleButton, "button"},
+           {ax::mojom::Role::kPopUpButton, "combobox"},
+           {ax::mojom::Role::kFooter, "contentinfo"},
+           {ax::mojom::Role::kMenuListOption, "menuitem"},
+           {ax::mojom::Role::kComboBoxMenuButton, "combobox"},
+           {ax::mojom::Role::kTextFieldWithComboBox, "combobox"}});
 
-  const auto& item = roles_with_different_name.find(role);
-  if (item != roles_with_different_name.end())
-    return item->second;
+  const auto* it = kRolesWithDifferentName.find(role);
+  if (it != kRolesWithDifferentName.end()) {
+    return std::string(it->second);
+  }
 
   // Roles that are not in the above tree groups have uppercase first letter
   // names.
@@ -356,20 +361,16 @@
   return proto.SerializeAsString();
 }
 
-const std::map<std::string, ax::mojom::Role>&
+std::map<std::string, ax::mojom::Role>
 GetMainContentExtractorToChromeRoleConversionMapForTesting() {
-  static std::map<std::string, ax::mojom::Role> contentExtractionToChromeRoles;
-
-  if (contentExtractionToChromeRoles.empty()) {
-    for (int i = static_cast<int>(ax::mojom::Role::kMinValue);
-         i <= static_cast<int>(ax::mojom::Role::kMaxValue); i++) {
-      auto role = static_cast<ax::mojom::Role>(i);
-      contentExtractionToChromeRoles[GetMainContentExtractorRoleFromChromeRole(
-          role)] = role;
-    }
+  std::map<std::string, ax::mojom::Role> content_extraction_to_chrome_roles;
+  for (int i = static_cast<int>(ax::mojom::Role::kMinValue);
+       i <= static_cast<int>(ax::mojom::Role::kMaxValue); i++) {
+    auto role = static_cast<ax::mojom::Role>(i);
+    content_extraction_to_chrome_roles
+        [GetMainContentExtractorRoleFromChromeRole(role)] = role;
   }
-
-  return contentExtractionToChromeRoles;
+  return content_extraction_to_chrome_roles;
 }
 
 }  // namespace screen_ai
diff --git a/components/services/screen_ai/proto/main_content_extractor_proto_convertor.h b/components/services/screen_ai/proto/main_content_extractor_proto_convertor.h
index 9934519..577d6c9c 100644
--- a/components/services/screen_ai/proto/main_content_extractor_proto_convertor.h
+++ b/components/services/screen_ai/proto/main_content_extractor_proto_convertor.h
@@ -17,7 +17,7 @@
 std::string SnapshotToViewHierarchy(const ui::AXTreeUpdate& snapshot);
 
 // Returns a map of MainContentExtractor role strings to Chrome roles.
-const std::map<std::string, ax::mojom::Role>&
+std::map<std::string, ax::mojom::Role>
 GetMainContentExtractorToChromeRoleConversionMapForTesting();
 
 }  // namespace screen_ai
diff --git a/components/services/screen_ai/proto/main_content_extractor_proto_convertor_unittest.cc b/components/services/screen_ai/proto/main_content_extractor_proto_convertor_unittest.cc
index e2f09fc..b169dfd 100644
--- a/components/services/screen_ai/proto/main_content_extractor_proto_convertor_unittest.cc
+++ b/components/services/screen_ai/proto/main_content_extractor_proto_convertor_unittest.cc
@@ -339,9 +339,11 @@
   ASSERT_TRUE(json.has_value());
 
   // Convert JSON file to AX tree update.
+  const std::map<std::string, ax::mojom::Role>
+      content_extraction_to_chrome_roles =
+          GetMainContentExtractorToChromeRoleConversionMapForTesting();
   ui::AXTreeUpdate tree_update = ui::AXTreeUpdateFromJSON(
-      json.value(),
-      &GetMainContentExtractorToChromeRoleConversionMapForTesting());
+      json.value(), &content_extraction_to_chrome_roles);
   ASSERT_GT(tree_update.nodes.size(), 0u);
 
   // Convert AX Tree to Screen2x proto.
diff --git a/components/services/screen_ai/public/cpp/BUILD.gn b/components/services/screen_ai/public/cpp/BUILD.gn
index d8b2b43..240357f0 100644
--- a/components/services/screen_ai/public/cpp/BUILD.gn
+++ b/components/services/screen_ai/public/cpp/BUILD.gn
@@ -12,4 +12,6 @@
     "//base",
     "//components/component_updater",
   ]
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
diff --git a/components/services/storage/public/mojom/blob_storage_context.mojom b/components/services/storage/public/mojom/blob_storage_context.mojom
index 7db83fe..bb575ae 100644
--- a/components/services/storage/public/mojom/blob_storage_context.mojom
+++ b/components/services/storage/public/mojom/blob_storage_context.mojom
@@ -85,4 +85,7 @@
                   bool flush_on_write,
                   mojo_base.mojom.Time? last_modified)
       => (WriteBlobToFileResult result);
+
+  // Binds another Mojo connection to this context.
+  Clone(pending_receiver<BlobStorageContext> receiver);
 };
diff --git a/components/services/storage/public/mojom/file_system_access_context.mojom b/components/services/storage/public/mojom/file_system_access_context.mojom
index b9eff93..fcba3a55 100644
--- a/components/services/storage/public/mojom/file_system_access_context.mojom
+++ b/components/services/storage/public/mojom/file_system_access_context.mojom
@@ -33,4 +33,7 @@
       blink.mojom.StorageKey storage_key,
       array<uint8> bits,
       pending_receiver<blink.mojom.FileSystemAccessTransferToken> token);
+
+  // Binds another mojo pipe to `this`.
+  Clone(pending_receiver<FileSystemAccessContext> receiever);
 };
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index 89dd858..8023bd5a 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -122,6 +122,7 @@
     "//components/content_settings/core/browser",
     "//components/prefs",
     "//components/prefs:test_support",
+    "//components/privacy_sandbox:privacy_sandbox_prefs",
     "//components/signin/public/base:signin_buildflags",
     "//components/signin/public/base:test_support",
     "//components/signin/public/identity_manager",
diff --git a/components/signin/core/browser/DEPS b/components/signin/core/browser/DEPS
index 98ee68f..46a7ee3f 100644
--- a/components/signin/core/browser/DEPS
+++ b/components/signin/core/browser/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/metrics",
+  "+components/privacy_sandbox/privacy_sandbox_prefs.h",
   "+components/signin/public/base",
   "+components/signin/public/identity_manager",
   "+components/supervised_user/core/common/features.h",
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index d6d0893..c3c45fb 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -16,6 +16,7 @@
 #include "build/chromeos_buildflags.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/prefs/pref_member.h"
+#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
 #include "components/signin/core/browser/chrome_connected_header_helper.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_buildflags.h"
@@ -73,6 +74,7 @@
   void SetUp() override {
     content_settings::CookieSettings::RegisterProfilePrefs(prefs_.registry());
     HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
+    privacy_sandbox::RegisterProfilePrefs(prefs_.registry());
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
     // TODO(crbug.com/1198528): remove this after the rollout.
diff --git a/components/site_settings_strings.grdp b/components/site_settings_strings.grdp
index 7ac8c932..417bc6f 100644
--- a/components/site_settings_strings.grdp
+++ b/components/site_settings_strings.grdp
@@ -23,10 +23,10 @@
     automatic downloads
   </message>
   <message name="IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE" desc="The label used for the auto-picture-in-picture site settings controls.">
-    Auto picture-in-picture
+    Automatic picture-in-picture
   </message>
   <message name="IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE_MID_SENTENCE" desc="The label used for the auto-picture-in-picture site settings controls when used mid-sentence.">
-    auto picture-in-picture
+    automatic picture-in-picture
   </message>
   <message name="IDS_SITE_SETTINGS_TYPE_BACKGROUND_SYNC" desc="The label used for the background sync site settings controls.">
     Background sync
diff --git a/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE.png.sha1 b/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE.png.sha1
index 94e1ba4..418a619 100644
--- a/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE.png.sha1
+++ b/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE.png.sha1
@@ -1 +1 @@
-abbeabf2300cf637e1e418456545d75bf350d829
\ No newline at end of file
+33e2203d32e64aa7488f932c20302eeb766fe6bb
\ No newline at end of file
diff --git a/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE_MID_SENTENCE.png.sha1 b/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE_MID_SENTENCE.png.sha1
index 94e1ba4..418a619 100644
--- a/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE_MID_SENTENCE.png.sha1
+++ b/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_AUTO_PICTURE_IN_PICTURE_MID_SENTENCE.png.sha1
@@ -1 +1 @@
-abbeabf2300cf637e1e418456545d75bf350d829
\ No newline at end of file
+33e2203d32e64aa7488f932c20302eeb766fe6bb
\ No newline at end of file
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.cc b/components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.cc
index bfe247c..b005da1 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.cc
@@ -245,6 +245,14 @@
     ContentSubresourceFilterThrottleManager* throttle_manager =
         GetThrottleManager(navigation_handle->GetRenderFrameHost()->GetPage());
 
+    // TODO(https://crbug.com/1234233): This shouldn't be possible but, from
+    // the investigation in https://crbug.com/1264667, this is likely a symptom
+    // of navigating a detached WebContents so (very rarely) was causing
+    // crashes.
+    if (!throttle_manager) {
+      return;
+    }
+
     throttle_manager->DidBecomePrimaryPage();
 
     return;
@@ -264,11 +272,12 @@
         ThrottleManagerInUserDataContainer::GetForNavigationHandle(
             *navigation_handle);
 
-    // It is theoretically possible to start a navigation in an unattached
-    // WebContents (so the WebContents doesn't yet have any WebContentsHelpers
-    // such as this class) but attach it before a navigation completes. If that
-    // happened we won't have a throttle manager for the navigation. Not sure
-    // this would ever happen in real usage but it does happen in some tests.
+    // TODO(https://crbug.com/1234233): It is theoretically possible to start a
+    // navigation in an unattached WebContents (so the WebContents doesn't yet
+    // have any WebContentsHelpers such as this class) but attach it before a
+    // navigation completes. If that happened we won't have a throttle manager
+    // for the navigation. Not sure this would ever happen in real usage but it
+    // does happen in some tests.
     if (!container) {
       return;
     }
@@ -286,10 +295,10 @@
     } else if (is_initial_navigation) {
       if (auto* rfh = content::RenderFrameHost::FromID(
               navigation_handle->GetPreviousRenderFrameHostId())) {
-        // TODO(bokan): Ideally this should only happen on the first navigation
-        // in a frame, however, in some cases we actually attach this TabHelper
-        // after a navigation has occurred (possibly before it has finished).
-        // See
+        // TODO(https://crbug.com/1234233): Ideally this should only happen on
+        // the first navigation in a frame, however, in some cases we actually
+        // attach this TabHelper after a navigation has occurred (possibly
+        // before it has finished). See
         // https://groups.google.com/a/chromium.org/g/navigation-dev/c/cY5V-w-xPRM/m/uC1Nsg_KAwAJ.
         // DCHECK(rfh->GetLastCommittedURL().is_empty() ||
         //        rfh->GetLastCommittedURL().IsAboutBlank());
diff --git a/components/sync/base/pref_names.h b/components/sync/base/pref_names.h
index 39806ae8..7a318001 100644
--- a/components/sync/base/pref_names.h
+++ b/components/sync/base/pref_names.h
@@ -24,9 +24,13 @@
 // TODO(crbug.com/1435427): Clean up/replace any existing references to these
 // prefs from outside components/sync/.
 namespace internal {
+
 // Boolean specifying whether the user finished setting up sync at least once.
+// On ChromeOS-Ash, the concept of initial-sync-setup doesn't exist.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 inline constexpr char kSyncInitialSyncFeatureSetupComplete[] =
     "sync.has_setup_completed";
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Boolean specifying whether to automatically sync all data types (including
 // future ones, as they're added).  If this is true, the following preferences
diff --git a/components/sync/service/sync_prefs.cc b/components/sync/service/sync_prefs.cc
index bf7234e61..e290e784 100644
--- a/components/sync/service/sync_prefs.cc
+++ b/components/sync/service/sync_prefs.cc
@@ -66,10 +66,13 @@
       prefs::internal::kSyncManaged, pref_service_,
       base::BindRepeating(&SyncPrefs::OnSyncManagedPrefChanged,
                           base::Unretained(this)));
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   pref_initial_sync_feature_setup_complete_.Init(
       prefs::internal::kSyncInitialSyncFeatureSetupComplete, pref_service_,
       base::BindRepeating(&SyncPrefs::OnFirstSetupCompletePrefChange,
                           base::Unretained(this)));
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Cache the value of the kEnableLocalSyncBackend pref to avoid it flipping
   // during the lifetime of the service.
@@ -84,8 +87,6 @@
 // static
 void SyncPrefs::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   // Actual user-controlled preferences.
-  registry->RegisterBooleanPref(
-      prefs::internal::kSyncInitialSyncFeatureSetupComplete, false);
   registry->RegisterBooleanPref(prefs::internal::kSyncRequested, false);
   registry->RegisterBooleanPref(prefs::internal::kSyncKeepEverythingSynced,
                                 true);
@@ -103,7 +104,10 @@
   registry->RegisterBooleanPref(prefs::internal::kSyncOsPreferences, false);
   registry->RegisterBooleanPref(prefs::internal::kSyncWifiConfigurations,
                                 false);
-#endif
+#else   // BUILDFLAG(IS_CHROMEOS_ASH)
+  registry->RegisterBooleanPref(
+      prefs::internal::kSyncInitialSyncFeatureSetupComplete, false);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   registry->RegisterBooleanPref(prefs::internal::kSyncAppsEnabledByOs, false);
@@ -143,10 +147,15 @@
 
 bool SyncPrefs::IsInitialSyncFeatureSetupComplete() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  return true;
+#else   // BUILDFLAG(IS_CHROMEOS_ASH)
   return pref_service_->GetBoolean(
       prefs::internal::kSyncInitialSyncFeatureSetupComplete);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void SyncPrefs::SetInitialSyncFeatureSetupComplete() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetBoolean(
@@ -158,6 +167,7 @@
   pref_service_->ClearPref(
       prefs::internal::kSyncInitialSyncFeatureSetupComplete);
 }
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 bool SyncPrefs::IsSyncRequested() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -621,6 +631,7 @@
   }
 }
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void SyncPrefs::OnFirstSetupCompletePrefChange() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (SyncPrefObserver& observer : sync_pref_observers_) {
@@ -628,6 +639,7 @@
         *pref_initial_sync_feature_setup_complete_);
   }
 }
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // static
 void SyncPrefs::RegisterTypeSelectedPref(PrefRegistrySimple* registry,
diff --git a/components/sync/service/sync_prefs.h b/components/sync/service/sync_prefs.h
index 722ecdb..41b759e 100644
--- a/components/sync/service/sync_prefs.h
+++ b/components/sync/service/sync_prefs.h
@@ -34,8 +34,10 @@
 class SyncPrefObserver {
  public:
   virtual void OnSyncManagedPrefChange(bool is_sync_managed) = 0;
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   virtual void OnFirstSetupCompletePrefChange(
       bool is_initial_sync_feature_setup_complete) = 0;
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   virtual void OnPreferredDataTypesPrefChange(
       bool payments_integration_enabled_changed) = 0;
 
@@ -72,8 +74,12 @@
   // First-Setup-Complete is conceptually similar to the user's consent to
   // enable sync-the-feature.
   bool IsInitialSyncFeatureSetupComplete() const;
+
+  // ChromeOS Ash, IsInitialSyncFeatureSetupComplete() always returns true.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   void SetInitialSyncFeatureSetupComplete();
   void ClearInitialSyncFeatureSetupComplete();
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Whether the user wants Sync to run. This is false by default, but gets set
   // to true early in the Sync setup flow, after the user has pressed "turn on
@@ -251,7 +257,10 @@
   static bool IsTypeSupportedInTransportMode(UserSelectableType type);
 
   void OnSyncManagedPrefChanged();
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   void OnFirstSetupCompletePrefChange();
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Never null.
   const raw_ptr<PrefService> pref_service_;
@@ -262,7 +271,9 @@
   // configuration management.
   BooleanPrefMember pref_sync_managed_;
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   BooleanPrefMember pref_initial_sync_feature_setup_complete_;
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   bool local_sync_enabled_;
 
diff --git a/components/sync/service/sync_prefs_unittest.cc b/components/sync/service/sync_prefs_unittest.cc
index 531b173..560214c 100644
--- a/components/sync/service/sync_prefs_unittest.cc
+++ b/components/sync/service/sync_prefs_unittest.cc
@@ -71,7 +71,9 @@
 class MockSyncPrefObserver : public SyncPrefObserver {
  public:
   MOCK_METHOD(void, OnSyncManagedPrefChange, (bool), (override));
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   MOCK_METHOD(void, OnFirstSetupCompletePrefChange, (bool), (override));
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   MOCK_METHOD(void, OnPreferredDataTypesPrefChange, (bool), (override));
 };
 
@@ -80,11 +82,8 @@
   InSequence dummy;
   EXPECT_CALL(mock_sync_pref_observer, OnSyncManagedPrefChange(true));
   EXPECT_CALL(mock_sync_pref_observer, OnSyncManagedPrefChange(false));
-  EXPECT_CALL(mock_sync_pref_observer, OnFirstSetupCompletePrefChange(true));
-  EXPECT_CALL(mock_sync_pref_observer, OnFirstSetupCompletePrefChange(false));
 
   ASSERT_FALSE(sync_prefs_->IsSyncClientDisabledByPolicy());
-  ASSERT_FALSE(sync_prefs_->IsInitialSyncFeatureSetupComplete());
   ASSERT_FALSE(sync_prefs_->IsSyncRequested());
 
   sync_prefs_->AddObserver(&mock_sync_pref_observer);
@@ -94,11 +93,6 @@
   pref_service_.SetBoolean(prefs::internal::kSyncManaged, false);
   EXPECT_FALSE(sync_prefs_->IsSyncClientDisabledByPolicy());
 
-  sync_prefs_->SetInitialSyncFeatureSetupComplete();
-  EXPECT_TRUE(sync_prefs_->IsInitialSyncFeatureSetupComplete());
-  sync_prefs_->ClearInitialSyncFeatureSetupComplete();
-  EXPECT_FALSE(sync_prefs_->IsInitialSyncFeatureSetupComplete());
-
   sync_prefs_->SetSyncRequested(true);
   EXPECT_TRUE(sync_prefs_->IsSyncRequested());
   sync_prefs_->SetSyncRequested(false);
@@ -107,6 +101,27 @@
   sync_prefs_->RemoveObserver(&mock_sync_pref_observer);
 }
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+TEST_F(SyncPrefsTest, FirstSetupCompletePrefChange) {
+  StrictMock<MockSyncPrefObserver> mock_sync_pref_observer;
+  InSequence dummy;
+
+  EXPECT_CALL(mock_sync_pref_observer, OnFirstSetupCompletePrefChange(true));
+  EXPECT_CALL(mock_sync_pref_observer, OnFirstSetupCompletePrefChange(false));
+
+  ASSERT_FALSE(sync_prefs_->IsInitialSyncFeatureSetupComplete());
+
+  sync_prefs_->AddObserver(&mock_sync_pref_observer);
+
+  sync_prefs_->SetInitialSyncFeatureSetupComplete();
+  EXPECT_TRUE(sync_prefs_->IsInitialSyncFeatureSetupComplete());
+  sync_prefs_->ClearInitialSyncFeatureSetupComplete();
+  EXPECT_FALSE(sync_prefs_->IsInitialSyncFeatureSetupComplete());
+
+  sync_prefs_->RemoveObserver(&mock_sync_pref_observer);
+}
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(SyncPrefsTest, SetSelectedOsTypesTriggersPreferredDataTypesPrefChange) {
   StrictMock<MockSyncPrefObserver> mock_sync_pref_observer;
@@ -123,8 +138,11 @@
 #endif
 
 TEST_F(SyncPrefsTest, Basic) {
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_FALSE(sync_prefs_->IsInitialSyncFeatureSetupComplete());
   sync_prefs_->SetInitialSyncFeatureSetupComplete();
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+
   EXPECT_TRUE(sync_prefs_->IsInitialSyncFeatureSetupComplete());
 
   EXPECT_FALSE(sync_prefs_->IsSyncRequested());
diff --git a/components/sync/service/sync_service_impl.cc b/components/sync/service/sync_service_impl.cc
index 713f0ee..04bd6d92 100644
--- a/components/sync/service/sync_service_impl.cc
+++ b/components/sync/service/sync_service_impl.cc
@@ -972,12 +972,15 @@
 
   crypto_.SetSyncEngine(GetAccountInfo(), engine_.get());
 
-  // Auto-start means IsInitialSyncFeatureSetupComplete gets set automatically.
-  if (ShouldAutoStartSyncFeature() &&
+  // TODO(crbug.com/1445931): Reconsider if local-sync actually needs
+  // IsInitialSyncFeatureSetupComplete() returning true.
+  if (IsLocalSyncEnabled() &&
       !user_settings_->IsInitialSyncFeatureSetupComplete()) {
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     // This will trigger a configure if it completes setup.
     user_settings_->SetInitialSyncFeatureSetupComplete(
         SyncFirstSetupCompleteSource::ENGINE_INITIALIZED_WITH_AUTO_START);
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   } else if (CanConfigureDataTypes(/*bypass_setup_in_progress_check=*/false)) {
     // Datatype downloads on restart are generally due to newly supported
     // datatypes (although it's also possible we're picking up where a failed
@@ -1808,6 +1811,7 @@
   }
 }
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void SyncServiceImpl::OnFirstSetupCompletePrefChange(
     bool is_initial_sync_feature_setup_complete) {
   if (engine_ && engine_->IsInitialized()) {
@@ -1817,6 +1821,7 @@
     MaybeRecordTrustedVaultHistograms();
   }
 }
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 void SyncServiceImpl::OnAccountsInCookieUpdated(
     const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
@@ -2105,7 +2110,9 @@
   // that if the user ever chooses to enable Sync again, they start off with
   // their previous settings by default. We do however require going through
   // first-time setup again and set SyncRequested to false.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   sync_prefs_.ClearInitialSyncFeatureSetupComplete();
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   sync_prefs_.ClearPassphrasePromptMutedProductVersion();
   // The passphrase type is now undefined again.
   sync_prefs_.ClearCachedPassphraseType();
diff --git a/components/sync/service/sync_service_impl.h b/components/sync/service/sync_service_impl.h
index e52b172..7b08d4d 100644
--- a/components/sync/service/sync_service_impl.h
+++ b/components/sync/service/sync_service_impl.h
@@ -203,8 +203,10 @@
 
   // SyncPrefObserver implementation.
   void OnSyncManagedPrefChange(bool is_sync_managed) override;
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   void OnFirstSetupCompletePrefChange(
       bool is_initial_sync_feature_setup_complete) override;
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   void OnPreferredDataTypesPrefChange(
       bool payments_integration_enabled_changed) override;
 
diff --git a/components/sync/service/sync_service_impl_startup_unittest.cc b/components/sync/service/sync_service_impl_startup_unittest.cc
index dd0476a..d0a9b48 100644
--- a/components/sync/service/sync_service_impl_startup_unittest.cc
+++ b/components/sync/service/sync_service_impl_startup_unittest.cc
@@ -139,7 +139,10 @@
     CHECK(!sync_service_);
 
     sync_prefs_.SetSyncRequested(true);
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
     sync_prefs_.SetInitialSyncFeatureSetupComplete();
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   }
 
   SyncPrefs* sync_prefs() { return &sync_prefs_; }
@@ -396,7 +399,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(SyncServiceImplStartupTest, StartAshNoCredentials) {
   // We've never completed startup.
-  ASSERT_FALSE(sync_prefs()->IsInitialSyncFeatureSetupComplete());
+  ASSERT_FALSE(component_factory()->HasTransportDataIncludingFirstSync());
 
   // On ChromeOS, the user is always immediately signed in, but a refresh token
   // isn't necessarily available yet.
@@ -421,7 +424,7 @@
 
 TEST_F(SyncServiceImplStartupTest, StartAshFirstTime) {
   // We've never completed Sync startup.
-  ASSERT_FALSE(sync_prefs()->IsInitialSyncFeatureSetupComplete());
+  ASSERT_FALSE(component_factory()->HasTransportDataIncludingFirstSync());
 
   // There is already a signed-in user.
   SignInWithSyncConsent();
@@ -578,7 +581,11 @@
   sync_prefs()->SetSyncRequested(true);
   CreateSyncService();
   SignInWithSyncConsent();
+  ASSERT_FALSE(component_factory()->HasTransportDataIncludingFirstSync());
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   ASSERT_FALSE(sync_prefs()->IsInitialSyncFeatureSetupComplete());
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Prevent automatic (and successful) completion of engine initialization.
   component_factory()->AllowFakeEngineInitCompletion(false);
@@ -603,6 +610,7 @@
 TEST_F(SyncServiceImplStartupTest, FullStartupSequenceFirstTime) {
   // We've never completed startup.
   ASSERT_FALSE(sync_prefs()->IsInitialSyncFeatureSetupComplete());
+  ASSERT_FALSE(component_factory()->HasTransportDataIncludingFirstSync());
 
   CreateSyncService({SESSIONS});
   sync_service()->Initialize();
diff --git a/components/sync/service/sync_service_impl_unittest.cc b/components/sync/service/sync_service_impl_unittest.cc
index a009b83..86d65f18 100644
--- a/components/sync/service/sync_service_impl_unittest.cc
+++ b/components/sync/service/sync_service_impl_unittest.cc
@@ -192,7 +192,11 @@
         /*keep_everything_synced=*/true,
         /*registered_types=*/UserSelectableTypeSet::All(),
         /*selected_types=*/UserSelectableTypeSet::All());
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    ASSERT_TRUE(sync_prefs.IsInitialSyncFeatureSetupComplete());
+#else   // BUILDFLAG(IS_CHROMEOS_ASH)
     sync_prefs.SetInitialSyncFeatureSetupComplete();
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   }
 
   void SetInvalidationsEnabled() {
diff --git a/components/sync/service/sync_user_settings.h b/components/sync/service/sync_user_settings.h
index 390345f..22a6bf0 100644
--- a/components/sync/service/sync_user_settings.h
+++ b/components/sync/service/sync_user_settings.h
@@ -23,6 +23,7 @@
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser
 // These values are persisted to logs. Entries should not be renumbered and
 // numeric values should never be reused.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 enum class SyncFirstSetupCompleteSource {
   BASIC_FLOW = 0,
   ADVANCED_FLOW_CONFIRM = 1,
@@ -32,6 +33,7 @@
   ANDROID_BACKUP_RESTORE = 5,
   kMaxValue = ANDROID_BACKUP_RESTORE,
 };
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 // This class encapsulates all the user-configurable bits of Sync.
 class SyncUserSettings {
@@ -43,8 +45,11 @@
   // NOTE: On ChromeOS, this gets set automatically, so it doesn't really mean
   // anything.
   virtual bool IsInitialSyncFeatureSetupComplete() const = 0;
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   virtual void SetInitialSyncFeatureSetupComplete(
       SyncFirstSetupCompleteSource source) = 0;
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Getting selected types, for both Sync-the-feature and Sync-the-transport
   // users.
diff --git a/components/sync/service/sync_user_settings_impl.cc b/components/sync/service/sync_user_settings_impl.cc
index b8ece3867..c7fbb0c 100644
--- a/components/sync/service/sync_user_settings_impl.cc
+++ b/components/sync/service/sync_user_settings_impl.cc
@@ -80,6 +80,7 @@
   return prefs_->IsInitialSyncFeatureSetupComplete();
 }
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void SyncUserSettingsImpl::SetInitialSyncFeatureSetupComplete(
     SyncFirstSetupCompleteSource source) {
   if (IsInitialSyncFeatureSetupComplete()) {
@@ -88,6 +89,7 @@
   UMA_HISTOGRAM_ENUMERATION("Signin.SyncFirstSetupCompleteSource", source);
   prefs_->SetInitialSyncFeatureSetupComplete();
 }
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 bool SyncUserSettingsImpl::IsSyncEverythingEnabled() const {
   return prefs_->HasKeepEverythingSynced();
diff --git a/components/sync/service/sync_user_settings_impl.h b/components/sync/service/sync_user_settings_impl.h
index 3b9440d..c479199 100644
--- a/components/sync/service/sync_user_settings_impl.h
+++ b/components/sync/service/sync_user_settings_impl.h
@@ -40,8 +40,10 @@
 
   // SyncUserSettings implementation.
   bool IsInitialSyncFeatureSetupComplete() const override;
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   void SetInitialSyncFeatureSetupComplete(
       SyncFirstSetupCompleteSource source) override;
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   bool IsSyncEverythingEnabled() const override;
   UserSelectableTypeSet GetSelectedTypes() const override;
   bool IsTypeManagedByPolicy(UserSelectableType type) const override;
diff --git a/components/sync/test/sync_user_settings_mock.h b/components/sync/test/sync_user_settings_mock.h
index 640a42a..f731324d 100644
--- a/components/sync/test/sync_user_settings_mock.h
+++ b/components/sync/test/sync_user_settings_mock.h
@@ -22,10 +22,12 @@
   SyncUserSettingsMock();
   ~SyncUserSettingsMock() override;
   MOCK_METHOD(bool, IsInitialSyncFeatureSetupComplete, (), (const override));
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   MOCK_METHOD(void,
               SetInitialSyncFeatureSetupComplete,
               (SyncFirstSetupCompleteSource),
               (override));
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
   MOCK_METHOD(bool, IsSyncEverythingEnabled, (), (const override));
   MOCK_METHOD(UserSelectableTypeSet, GetSelectedTypes, (), (const override));
   MOCK_METHOD(bool,
diff --git a/components/sync/test/test_sync_user_settings.cc b/components/sync/test/test_sync_user_settings.cc
index ed56f495..061870cd 100644
--- a/components/sync/test/test_sync_user_settings.cc
+++ b/components/sync/test/test_sync_user_settings.cc
@@ -49,10 +49,12 @@
   return initial_sync_feature_setup_complete_;
 }
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 void TestSyncUserSettings::SetInitialSyncFeatureSetupComplete(
     SyncFirstSetupCompleteSource source) {
   SetInitialSyncFeatureSetupComplete();
 }
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
 bool TestSyncUserSettings::IsSyncEverythingEnabled() const {
   return sync_everything_enabled_;
diff --git a/components/sync/test/test_sync_user_settings.h b/components/sync/test/test_sync_user_settings.h
index 92488c8..684183f0 100644
--- a/components/sync/test/test_sync_user_settings.h
+++ b/components/sync/test/test_sync_user_settings.h
@@ -28,8 +28,11 @@
   ~TestSyncUserSettings() override;
 
   bool IsInitialSyncFeatureSetupComplete() const override;
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   void SetInitialSyncFeatureSetupComplete(
       SyncFirstSetupCompleteSource source) override;
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 
   bool IsSyncEverythingEnabled() const override;
   UserSelectableTypeSet GetSelectedTypes() const override;
diff --git a/components/ukm/ukm_service.cc b/components/ukm/ukm_service.cc
index d80b7b5..67a0c13 100644
--- a/components/ukm/ukm_service.cc
+++ b/components/ukm/ukm_service.cc
@@ -19,7 +19,6 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/metrics/log_decoder.h"
-#include "components/metrics/metrics_features.h"
 #include "components/metrics/metrics_log.h"
 #include "components/metrics/metrics_service_client.h"
 #include "components/metrics/ukm_demographic_metrics_provider.h"
@@ -213,12 +212,9 @@
   DVLOG(1) << "UkmService::Constructor";
   reporting_service_.Initialize();
 
-  if (base::FeatureList::IsEnabled(
-          metrics::features::kMetricsClearLogsOnClonedInstall)) {
-    cloned_install_subscription_ = client->AddOnClonedInstallDetectedCallback(
-        base::BindOnce(&UkmService::OnClonedInstallDetected,
-                       self_ptr_factory_.GetWeakPtr()));
-  }
+  cloned_install_subscription_ = client->AddOnClonedInstallDetectedCallback(
+      base::BindOnce(&UkmService::OnClonedInstallDetected,
+                     self_ptr_factory_.GetWeakPtr()));
 
   base::RepeatingClosure rotate_callback = base::BindRepeating(
       &UkmService::RotateLog, self_ptr_factory_.GetWeakPtr());
diff --git a/components/ukm/ukm_service_unittest.cc b/components/ukm/ukm_service_unittest.cc
index 501625c4..6872c82 100644
--- a/components/ukm/ukm_service_unittest.cc
+++ b/components/ukm/ukm_service_unittest.cc
@@ -204,8 +204,7 @@
   raw_ptr<UkmRecorder> test_recording_helper_;
 };
 
-class UkmServiceTest : public testing::Test,
-                       public testing::WithParamInterface<std::tuple<bool>> {
+class UkmServiceTest : public testing::Test {
  public:
   UkmServiceTest()
       : task_runner_(new base::TestSimpleTaskRunner),
@@ -217,26 +216,6 @@
   UkmServiceTest(const UkmServiceTest&) = delete;
   UkmServiceTest& operator=(const UkmServiceTest&) = delete;
 
-  bool ShouldClearLogsOnClonedInstall() { return std::get<0>(GetParam()); }
-
-  void SetUp() override {
-    testing::Test::SetUp();
-    std::vector<base::test::FeatureRefAndParams> enabled_features;
-    std::vector<base::test::FeatureRef> disabled_features;
-
-    if (ShouldClearLogsOnClonedInstall()) {
-      enabled_features.emplace_back(
-          metrics::features::kMetricsClearLogsOnClonedInstall,
-          /*params=*/std::map<std::string, std::string>());
-    } else {
-      disabled_features.emplace_back(
-          metrics::features::kMetricsClearLogsOnClonedInstall);
-    }
-
-    feature_list_.InitWithFeaturesAndParameters(enabled_features,
-                                                disabled_features);
-  }
-
   void ClearPrefs() {
     prefs_.ClearPref(prefs::kUkmClientId);
     prefs_.ClearPref(prefs::kUkmSessionId);
@@ -260,7 +239,6 @@
   }
 
  protected:
-  base::test::ScopedFeatureList feature_list_;
   TestingPrefServiceSimple prefs_;
   metrics::TestMetricsServiceClient client_;
 
@@ -296,11 +274,7 @@
 };
 }  // namespace
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         UkmServiceTest,
-                         testing::Combine(testing::Bool()));
-
-TEST_P(UkmServiceTest, ClientIdMigration) {
+TEST_F(UkmServiceTest, ClientIdMigration) {
   prefs_.SetInt64(prefs::kUkmClientId, -1);
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
@@ -310,7 +284,7 @@
   EXPECT_EQ(migrated_id, 18446744073709551615ULL);
 }
 
-TEST_P(UkmServiceTest, ClientIdClonedInstall) {
+TEST_F(UkmServiceTest, ClientIdClonedInstall) {
   prefs_.SetInt64(prefs::kUkmClientId, 123);
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
@@ -325,7 +299,7 @@
   EXPECT_NE(original_id, new_id);
 }
 
-TEST_P(UkmServiceTest, EnableDisableSchedule) {
+TEST_F(UkmServiceTest, EnableDisableSchedule) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   EXPECT_FALSE(task_runner_->HasPendingTask());
@@ -339,7 +313,7 @@
   EXPECT_FALSE(task_runner_->HasPendingTask());
 }
 
-TEST_P(UkmServiceTest, PersistAndPurge) {
+TEST_F(UkmServiceTest, PersistAndPurge) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -362,7 +336,7 @@
   EXPECT_EQ(GetPersistedLogCount(), 0);
 }
 
-TEST_P(UkmServiceTest, Purge) {
+TEST_F(UkmServiceTest, Purge) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -383,7 +357,7 @@
   EXPECT_EQ(0, GetPersistedLogCount());
 }
 
-TEST_P(UkmServiceTest, PurgeExtensionDataFromUnsentLogStore) {
+TEST_F(UkmServiceTest, PurgeExtensionDataFromUnsentLogStore) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   auto* unsent_log_store = service.reporting_service_.ukm_log_store();
@@ -448,7 +422,7 @@
   EXPECT_EQ(source_id_1, filtered_report.entries(0).source_id());
 }
 
-TEST_P(UkmServiceTest, PurgeAppDataFromUnsentLogStore) {
+TEST_F(UkmServiceTest, PurgeAppDataFromUnsentLogStore) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   auto* unsent_log_store = service.reporting_service_.ukm_log_store();
@@ -533,7 +507,7 @@
   EXPECT_EQ(source_id_1, filtered_report.entries(0).source_id());
 }
 
-TEST_P(UkmServiceTest, PurgeMsbbDataFromUnsentLogStore) {
+TEST_F(UkmServiceTest, PurgeMsbbDataFromUnsentLogStore) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   auto* unsent_log_store = service.reporting_service_.ukm_log_store();
@@ -630,7 +604,7 @@
   EXPECT_EQ(source_id_3, filtered_report.entries(1).source_id());
 }
 
-TEST_P(UkmServiceTest, SourceSerialization) {
+TEST_F(UkmServiceTest, SourceSerialization) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -660,7 +634,7 @@
             proto_source.urls(1).url());
 }
 
-TEST_P(UkmServiceTest, AddEntryWithEmptyMetrics) {
+TEST_F(UkmServiceTest, AddEntryWithEmptyMetrics) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -680,7 +654,7 @@
   EXPECT_EQ(1, proto_report.entries_size());
 }
 
-TEST_P(UkmServiceTest, MetricsProviderTest) {
+TEST_F(UkmServiceTest, MetricsProviderTest) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -716,7 +690,7 @@
 
 // Currently just testing brand is set, would be good to test other core
 // system profile fields.
-TEST_P(UkmServiceTest, SystemProfileTest) {
+TEST_F(UkmServiceTest, SystemProfileTest) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -738,7 +712,7 @@
             proto_report.system_profile().brand_code());
 }
 
-TEST_P(UkmServiceTest, AddUserDemograhicsWhenAvailableAndFeatureEnabled) {
+TEST_F(UkmServiceTest, AddUserDemograhicsWhenAvailableAndFeatureEnabled) {
   int number_of_invocations = 0;
   int test_birth_year = 1983;
   metrics::UserDemographicsProto::Gender test_gender =
@@ -788,7 +762,7 @@
   EXPECT_EQ(1, number_of_invocations);
 }
 
-TEST_P(UkmServiceTest,
+TEST_F(UkmServiceTest,
        DontAddUserDemograhicsWhenNotAvailableAndFeatureEnabled) {
   auto provider = std::make_unique<MockDemographicMetricsProvider>();
   EXPECT_CALL(*provider,
@@ -816,7 +790,7 @@
   EXPECT_FALSE(proto_report.has_user_demographics());
 }
 
-TEST_P(UkmServiceTest, DontAddUserDemograhicsWhenFeatureDisabled) {
+TEST_F(UkmServiceTest, DontAddUserDemograhicsWhenFeatureDisabled) {
   base::test::ScopedFeatureList local_feature;
   local_feature.InitAndDisableFeature(kReportUserNoisedUserBirthYearAndGender);
 
@@ -847,7 +821,7 @@
   EXPECT_FALSE(proto_report.has_user_demographics());
 }
 
-TEST_P(UkmServiceTest, LogsRotation) {
+TEST_F(UkmServiceTest, LogsRotation) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -888,7 +862,7 @@
   }
 }
 
-TEST_P(UkmServiceTest, LogsUploadedOnlyWhenHavingSourcesOrEntries) {
+TEST_F(UkmServiceTest, LogsUploadedOnlyWhenHavingSourcesOrEntries) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -928,7 +902,7 @@
   EXPECT_EQ(GetPersistedLogCount(), 3);
 }
 
-TEST_P(UkmServiceTest, GetNewSourceID) {
+TEST_F(UkmServiceTest, GetNewSourceID) {
   SourceId id1 = UkmRecorder::GetNewSourceID();
   SourceId id2 = UkmRecorder::GetNewSourceID();
   SourceId id3 = UkmRecorder::GetNewSourceID();
@@ -937,7 +911,7 @@
   EXPECT_NE(id2, id3);
 }
 
-TEST_P(UkmServiceTest, RecordRedirectedUrl) {
+TEST_F(UkmServiceTest, RecordRedirectedUrl) {
   ClearPrefs();
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
@@ -968,7 +942,7 @@
             proto_source.urls(1).url());
 }
 
-TEST_P(UkmServiceTest, RecordSessionId) {
+TEST_F(UkmServiceTest, RecordSessionId) {
   ClearPrefs();
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
@@ -990,7 +964,7 @@
   EXPECT_EQ(1, proto_report.report_id());
 }
 
-TEST_P(UkmServiceTest, SourceSize) {
+TEST_F(UkmServiceTest, SourceSize) {
   ClearPrefs();
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
@@ -1015,7 +989,7 @@
   EXPECT_EQ(500, proto_report.sources_size());
 }
 
-TEST_P(UkmServiceTest, PurgeMidUpload) {
+TEST_F(UkmServiceTest, PurgeMidUpload) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -1038,7 +1012,7 @@
   EXPECT_FALSE(client_.uploader()->is_uploading());
 }
 
-TEST_P(UkmServiceTest, SourceURLLength) {
+TEST_F(UkmServiceTest, SourceURLLength) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -1064,7 +1038,7 @@
   EXPECT_EQ("URLTooLong", proto_source.urls(0).url());
 }
 
-TEST_P(UkmServiceTest, UnreferencedNonAllowlistedSources) {
+TEST_F(UkmServiceTest, UnreferencedNonAllowlistedSources) {
   const GURL kURL("https://google.com/foobar");
 
   ClearPrefs();
@@ -1145,7 +1119,7 @@
   ASSERT_EQ(3, proto_report.sources_size());
 }
 
-TEST_P(UkmServiceTest, NonAllowlistedUrls) {
+TEST_F(UkmServiceTest, NonAllowlistedUrls) {
   // URL to be manually allowlisted using allowlisted source type.
   const GURL kURL("https://google.com/foobar");
   struct {
@@ -1232,7 +1206,7 @@
   }
 }
 
-TEST_P(UkmServiceTest, AllowlistIdType) {
+TEST_F(UkmServiceTest, AllowlistIdType) {
   std::map<SourceIdType, bool> source_id_type_allowlisted = {
       {SourceIdType::DEFAULT, false},  {SourceIdType::NAVIGATION_ID, true},
       {SourceIdType::APP_ID, true},    {SourceIdType::HISTORY_ID, true},
@@ -1281,7 +1255,7 @@
   }
 }
 
-TEST_P(UkmServiceTest, SupportedSchemes) {
+TEST_F(UkmServiceTest, SupportedSchemes) {
   struct {
     const char* url;
     bool expected_kept;
@@ -1340,7 +1314,7 @@
   }
 }
 
-TEST_P(UkmServiceTest, SupportedSchemesNoExtensions) {
+TEST_F(UkmServiceTest, SupportedSchemesNoExtensions) {
   struct {
     const char* url;
     bool expected_kept;
@@ -1396,7 +1370,7 @@
   }
 }
 
-TEST_P(UkmServiceTest, SanitizeUrlAuthParams) {
+TEST_F(UkmServiceTest, SanitizeUrlAuthParams) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -1418,7 +1392,7 @@
   EXPECT_EQ("https://example.com/", proto_source.urls(0).url());
 }
 
-TEST_P(UkmServiceTest, SanitizeChromeUrlParams) {
+TEST_F(UkmServiceTest, SanitizeChromeUrlParams) {
   struct {
     const char* url;
     const char* expected_url;
@@ -1460,7 +1434,7 @@
   }
 }
 
-TEST_P(UkmServiceTest, MarkSourceForDeletion) {
+TEST_F(UkmServiceTest, MarkSourceForDeletion) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -1510,7 +1484,7 @@
 
 // Verifies that sources of some types are deleted at the end of reporting
 // cycle.
-TEST_P(UkmServiceTest, PurgeNonCarriedOverSources) {
+TEST_F(UkmServiceTest, PurgeNonCarriedOverSources) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -1576,7 +1550,7 @@
   EXPECT_EQ(app_id, proto_report.sources(1).id());
 }
 
-TEST_P(UkmServiceTest, IdentifiabilityMetricsDontExplode) {
+TEST_F(UkmServiceTest, IdentifiabilityMetricsDontExplode) {
   UkmService service(&prefs_, &client_,
                      std::make_unique<MockDemographicMetricsProvider>());
   TestRecordingHelper recorder(&service);
@@ -1596,7 +1570,7 @@
   EXPECT_EQ(1, proto_report.entries_size());
 }
 
-TEST_P(UkmServiceTest, FilterCanRemoveMetrics) {
+TEST_F(UkmServiceTest, FilterCanRemoveMetrics) {
   class TestEntryFilter : public UkmEntryFilter {
    public:
     // This implementation removes the last metric in an event and returns it in
@@ -1643,7 +1617,7 @@
   EXPECT_EQ(2u, proto_report.aggregates(0).metrics(1).dropped_due_to_filter());
 }
 
-TEST_P(UkmServiceTest, FilterRejectsEvent) {
+TEST_F(UkmServiceTest, FilterRejectsEvent) {
   static const auto kTestEvent1EntryNameHash =
       base::HashMetricName(TestEvent1::kEntryName);
 
@@ -1695,7 +1669,7 @@
       proto_report.aggregates(0).metrics(0).has_dropped_due_to_filter());
 }
 
-TEST_P(UkmServiceTest, PruneUnseenFirst) {
+TEST_F(UkmServiceTest, PruneUnseenFirst) {
   // We will be testing with the prune unseen feature both off and on.
   for (bool prune_unseen_sources_first : {true, false}) {
     const GURL kURL("https://google.com/foobar");
@@ -1807,7 +1781,7 @@
   }
 }
 
-TEST_P(UkmServiceTest, PruneAppIDLast) {
+TEST_F(UkmServiceTest, PruneAppIDLast) {
   // We will be testing with the PruneAppIdLast feature both off and on.
   for (bool prune_app_id_last : {true, false}) {
     const GURL kURL("https://google.com/foobar");
@@ -1904,7 +1878,7 @@
   }
 }
 
-TEST_P(UkmServiceTest, UseExternalClientID) {
+TEST_F(UkmServiceTest, UseExternalClientID) {
   prefs_.SetUint64(prefs::kUkmClientId, 1234);
   uint64_t external_client_id = 5678;
   UkmService service(&prefs_, &client_,
@@ -1916,7 +1890,7 @@
 }
 
 // Verifies that when a cloned install is detected, logs are purged.
-TEST_P(UkmServiceTest, PurgeLogsOnClonedInstallDetected) {
+TEST_F(UkmServiceTest, PurgeLogsOnClonedInstallDetected) {
   TestMetricsServiceClientWithClonedInstallDetector client;
   UkmService service(&prefs_, &client,
                      std::make_unique<MockDemographicMetricsProvider>());
@@ -1953,15 +1927,9 @@
   // Save a machine id that will cause a clone to be detected.
   prefs_.SetInteger(metrics::prefs::kMetricsMachineId, kTestHashedId + 1);
   cloned_install_detector->SaveMachineIdForTesting(&prefs_, kTestRawId);
-  // Verify that the logs were purged if the |kMetricsClearLogsOnClonedInstall|
-  // feature is enabled.
-  if (ShouldClearLogsOnClonedInstall()) {
-    EXPECT_FALSE(test_log_store->has_staged_log());
-    EXPECT_FALSE(test_log_store->has_unsent_logs());
-  } else {
-    EXPECT_TRUE(test_log_store->has_staged_log());
-    EXPECT_TRUE(test_log_store->has_unsent_logs());
-  }
+  // Verify that the logs were purged.
+  EXPECT_FALSE(test_log_store->has_staged_log());
+  EXPECT_FALSE(test_log_store->has_unsent_logs());
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/components/update_client/background_downloader_win.cc b/components/update_client/background_downloader_win.cc
index 8b72af8..7d8f5dbda 100644
--- a/components/update_client/background_downloader_win.cc
+++ b/components/update_client/background_downloader_win.cc
@@ -9,8 +9,6 @@
 
 #include <stddef.h>
 #include <stdint.h>
-#include <functional>
-#include <iomanip>
 #include <limits>
 #include <memory>
 #include <utility>
@@ -24,21 +22,18 @@
 #include "base/functional/callback_helpers.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_thread_priority.h"
-#include "base/win/atl.h"
 #include "base/win/scoped_co_mem.h"
 #include "components/update_client/task_traits.h"
 #include "components/update_client/update_client_errors.h"
 #include "components/update_client/utils.h"
 #include "url/gurl.h"
 
-using Microsoft::WRL::ComPtr;
 using base::win::ScopedCoMem;
+using Microsoft::WRL::ComPtr;
 
 // The class BackgroundDownloader in this module is an adapter between
 // the CrxDownloader interface and the BITS service interfaces.
@@ -185,18 +180,21 @@
                       std::vector<ComPtr<IBackgroundCopyFile>>* files) {
   ComPtr<IEnumBackgroundCopyFiles> enum_files;
   HRESULT hr = job->EnumFiles(&enum_files);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   ULONG num_files = 0;
   hr = enum_files->GetCount(&num_files);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   for (ULONG i = 0; i != num_files; ++i) {
     ComPtr<IBackgroundCopyFile> file;
-    if (enum_files->Next(1, &file, nullptr) == S_OK && file.Get())
+    if (enum_files->Next(1, &file, nullptr) == S_OK && file.Get()) {
       files->push_back(file);
+    }
   }
 
   return S_OK;
@@ -208,32 +206,36 @@
                              std::wstring* local_name,
                              std::wstring* remote_name,
                              BG_FILE_PROGRESS* progress) {
-  if (!file)
+  if (!file) {
     return E_FAIL;
+  }
 
   HRESULT hr = S_OK;
 
   if (local_name) {
     ScopedCoMem<wchar_t> name;
     hr = file->GetLocalName(&name);
-    if (FAILED(hr))
+    if (FAILED(hr)) {
       return hr;
+    }
     local_name->assign(name);
   }
 
   if (remote_name) {
     ScopedCoMem<wchar_t> name;
     hr = file->GetRemoteName(&name);
-    if (FAILED(hr))
+    if (FAILED(hr)) {
       return hr;
+    }
     remote_name->assign(name);
   }
 
   if (progress) {
     BG_FILE_PROGRESS bg_file_progress = {};
     hr = file->GetProgress(&bg_file_progress);
-    if (FAILED(hr))
+    if (FAILED(hr)) {
       return hr;
+    }
     *progress = bg_file_progress;
   }
 
@@ -249,22 +251,26 @@
   *downloaded_bytes = -1;
   *total_bytes = -1;
 
-  if (!job)
+  if (!job) {
     return E_FAIL;
+  }
 
   BG_JOB_PROGRESS job_progress = {};
   HRESULT hr = job->GetProgress(&job_progress);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   const uint64_t kMaxNumBytes =
       static_cast<uint64_t>(std::numeric_limits<int64_t>::max());
-  if (job_progress.BytesTransferred <= kMaxNumBytes)
+  if (job_progress.BytesTransferred <= kMaxNumBytes) {
     *downloaded_bytes = job_progress.BytesTransferred;
+  }
 
   if (job_progress.BytesTotal <= kMaxNumBytes &&
-      job_progress.BytesTotal != BG_SIZE_UNKNOWN)
+      job_progress.BytesTotal != BG_SIZE_UNKNOWN) {
     *total_bytes = job_progress.BytesTotal;
+  }
 
   return S_OK;
 }
@@ -273,8 +279,9 @@
                           std::wstring* name) {
   ScopedCoMem<wchar_t> local_name;
   const HRESULT hr = job->GetDisplayName(&local_name);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
   *name = local_name.get();
   return S_OK;
 }
@@ -287,14 +294,16 @@
   *error_code_out = S_OK;
   ComPtr<IBackgroundCopyError> copy_error;
   HRESULT hr = job->GetError(&copy_error);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   BG_ERROR_CONTEXT error_context = BG_ERROR_CONTEXT_NONE;
   HRESULT error_code = S_OK;
   hr = copy_error->GetError(&error_context, &error_code);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   *error_code_out = FAILED(error_code) ? error_code : E_FAIL;
   return S_OK;
@@ -309,13 +318,15 @@
                       std::vector<ComPtr<IBackgroundCopyJob>>* jobs) {
   ComPtr<IEnumBackgroundCopyJobs> enum_jobs;
   HRESULT hr = bits_manager->EnumJobs(0, &enum_jobs);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   ULONG job_count = 0;
   hr = enum_jobs->GetCount(&job_count);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   // Iterate over jobs, run the predicate, and select the job only if
   // the job description matches the component updater jobs.
@@ -325,8 +336,9 @@
         pred(current_job)) {
       std::wstring job_name;
       hr = GetJobDisplayName(current_job, &job_name);
-      if (job_name.compare(kJobName) == 0)
+      if (job_name.compare(kJobName) == 0) {
         jobs->push_back(current_job);
+      }
     }
   }
 
@@ -337,8 +349,9 @@
                                        int num_days) {
   BG_JOB_TIMES times = {};
   HRESULT hr = job->GetTimes(&times);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return false;
+  }
 
   const base::TimeDelta time_delta(base::Days(num_days));
   const base::Time creation_time(base::Time::FromFileTime(times.CreationTime));
@@ -349,14 +362,16 @@
 bool JobFileUrlEqualPredicate(ComPtr<IBackgroundCopyJob> job, const GURL& url) {
   std::vector<ComPtr<IBackgroundCopyFile>> files;
   HRESULT hr = GetFilesInJob(job, &files);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return false;
+  }
 
   for (size_t i = 0; i != files.size(); ++i) {
     ScopedCoMem<wchar_t> remote_name;
     if (SUCCEEDED(files[i]->GetRemoteName(&remote_name)) &&
-        url == GURL(base::SysWideToUTF8(remote_name.get())))
+        url == GURL(base::SysWideToUTF8(remote_name.get()))) {
       return true;
+    }
   }
 
   return false;
@@ -385,8 +400,9 @@
 }
 
 void CleanupJob(const ComPtr<IBackgroundCopyJob>& job) {
-  if (!job)
+  if (!job) {
     return;
+  }
 
   // Get the file paths associated with this job before canceling the job.
   // Canceling the job removes it from the BITS queue right away. It appears
@@ -399,14 +415,16 @@
   for (const auto& file : files) {
     std::wstring local_name;
     HRESULT hr = GetJobFileProperties(file, &local_name, nullptr, nullptr);
-    if (SUCCEEDED(hr))
+    if (SUCCEEDED(hr)) {
       paths.push_back(base::FilePath(local_name));
+    }
   }
 
   job->Cancel();
 
-  for (const auto& path : paths)
+  for (const auto& path : paths) {
     DeleteFileAndEmptyParentDirectory(path);
+  }
 }
 
 }  // namespace
@@ -468,24 +486,29 @@
 HRESULT BackgroundDownloader::BeginDownloadHelper(const GURL& url) {
   ComPtr<IGlobalInterfaceTable> git;
   HRESULT hr = GetGit(&git);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = CreateBitsManager(&bits_manager_);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = QueueBitsJob(url, &job_);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = RegisterInterfaceInGit(git, bits_manager_, &git_cookie_bits_manager_);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = RegisterInterfaceInGit(git, job_, &git_cookie_job_);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   return S_OK;
 }
@@ -507,7 +530,7 @@
     return;
   }
 
-  bool is_handled =  false;
+  bool is_handled = false;
   switch (job_state) {
     case BG_JOB_STATE_TRANSFERRED:
       is_handled = OnStateTransferred();
@@ -545,8 +568,9 @@
       break;
   }
 
-  if (is_handled)
+  if (is_handled) {
     return;
+  }
 
   ResetInterfacePointers();
   main_task_runner()->PostTask(
@@ -568,8 +592,9 @@
   int64_t total_bytes = -1;
   GetJobByteCount(job_, &downloaded_bytes, &total_bytes);
 
-  if (FAILED(error))
+  if (FAILED(error)) {
     CleanupJob(job_);
+  }
 
   ClearGit();
 
@@ -590,8 +615,9 @@
 
   Result result;
   result.error = error_to_report;
-  if (!result.error)
+  if (!result.error) {
     result.response = response_;
+  }
   main_task_runner()->PostTask(
       FROM_HERE, base::BindOnce(&BackgroundDownloader::OnDownloadComplete, this,
                                 is_handled, result, download_metrics));
@@ -610,8 +636,9 @@
 bool BackgroundDownloader::OnStateError() {
   HRESULT error_code = S_OK;
   HRESULT hr = GetJobError(job_, &error_code);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     error_code = hr;
+  }
 
   CHECK(FAILED(error_code));
   EndDownload(error_code);
@@ -654,8 +681,9 @@
 }
 
 bool BackgroundDownloader::OnStateQueued() {
-  if (!IsStuck())
+  if (!IsStuck()) {
     return false;
+  }
 
   // Terminate the download if the job has not made progress in a while.
   EndDownload(E_ABORT);
@@ -687,9 +715,10 @@
   // Remove some old jobs from the BITS queue before creating new jobs.
   CleanupStaleJobs();
 
-  if (FAILED(hr) || num_jobs >= kMaxQueuedJobs)
+  if (FAILED(hr) || num_jobs >= kMaxQueuedJobs) {
     return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF,
                         CrxDownloaderError::BITS_TOO_MANY_JOBS);
+  }
 
   ComPtr<IBackgroundCopyJob> local_job;
   hr = CreateOrOpenJob(url, &local_job);
@@ -746,31 +775,37 @@
     const GURL& url) {
   base::FilePath tempdir;
   if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_BITS_"),
-                                    &tempdir))
+                                    &tempdir)) {
     return E_FAIL;
+  }
 
   const std::wstring filename(base::SysUTF8ToWide(url.ExtractFileName()));
   HRESULT hr = job->AddFile(base::SysUTF8ToWide(url.spec()).c_str(),
                             tempdir.Append(filename).value().c_str());
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = job->SetDescription(filename.c_str());
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = job->SetPriority(BG_JOB_PRIORITY_NORMAL);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = job->SetMinimumRetryDelay(60 * kMinimumRetryDelayMin);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   const int kSecondsDay = 60 * 60 * 24;
   hr = job->SetNoProgressTimeout(kSecondsDay * kSetNoProgressTimeoutDays);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   return S_OK;
 }
@@ -782,22 +817,26 @@
 
 HRESULT BackgroundDownloader::CompleteJob() {
   HRESULT hr = job_->Complete();
-  if (FAILED(hr) && hr != BG_S_UNABLE_TO_DELETE_FILES)
+  if (FAILED(hr) && hr != BG_S_UNABLE_TO_DELETE_FILES) {
     return hr;
+  }
 
   std::vector<ComPtr<IBackgroundCopyFile>> files;
   hr = GetFilesInJob(job_, &files);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
-  if (files.empty())
+  if (files.empty()) {
     return E_UNEXPECTED;
+  }
 
   std::wstring local_name;
   BG_FILE_PROGRESS progress = {0};
   hr = GetJobFileProperties(files.front(), &local_name, nullptr, &progress);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   // Check the post-conditions of a successful download, including the file and
   // job invariants. The byte counts for a job and its file must match as a job
@@ -818,17 +857,20 @@
 
   ComPtr<IGlobalInterfaceTable> git;
   HRESULT hr = GetGit(&git);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = GetInterfaceFromGit(git, git_cookie_bits_manager_,
                            IID_PPV_ARGS(&bits_manager_));
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   hr = GetInterfaceFromGit(git, git_cookie_job_, IID_PPV_ARGS(&job_));
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   return S_OK;
 }
@@ -845,12 +887,11 @@
 
   ComPtr<IGlobalInterfaceTable> git;
   HRESULT hr = GetGit(&git);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
-  const DWORD cookies[] = {
-      git_cookie_job_, git_cookie_bits_manager_
-  };
+  const DWORD cookies[] = {git_cookie_job_, git_cookie_bits_manager_};
 
   for (auto cookie : cookies) {
     git->RevokeInterfaceFromGlobal(cookie);
@@ -868,8 +909,9 @@
   const HRESULT hr =
       FindBitsJobIf([](const ComPtr<IBackgroundCopyJob>&) { return true; },
                     bits_manager_, &jobs);
-  if (FAILED(hr))
+  if (FAILED(hr)) {
     return hr;
+  }
 
   *num_jobs = jobs.size();
   return S_OK;
@@ -884,8 +926,9 @@
   const base::TimeDelta time_delta(
       base::Days(kPurgeStaleJobsIntervalBetweenChecksDays));
   const base::Time current_time(base::Time::Now());
-  if (last_sweep + time_delta > current_time)
+  if (last_sweep + time_delta > current_time) {
     return;
+  }
 
   last_sweep = current_time;
 
@@ -896,8 +939,9 @@
       },
       bits_manager_, &jobs);
 
-  for (const auto& job : jobs)
+  for (const auto& job : jobs) {
     CleanupJob(job);
+  }
 }
 
 }  // namespace update_client
diff --git a/components/user_education/common/BUILD.gn b/components/user_education/common/BUILD.gn
index bdda0eb5..c3739f813c 100644
--- a/components/user_education/common/BUILD.gn
+++ b/components/user_education/common/BUILD.gn
@@ -46,6 +46,7 @@
   ]
 
   deps = [
+    ":events",
     "//base",
     "//components/feature_engagement/public",
     "//components/strings",
@@ -58,6 +59,19 @@
   ]
 }
 
+component("events") {
+  output_name = "user_education_common_events"
+
+  defines = [ "IS_USER_EDUCATION_COMMON_EVENTS_IMPL" ]
+
+  sources = [
+    "events.cc",
+    "events.h",
+  ]
+
+  deps = [ "//ui/base" ]
+}
+
 source_set("unit_tests") {
   testonly = true
 
@@ -72,6 +86,7 @@
 
   deps = [
     ":common",
+    ":events",
     "//base",
     "//base/test:test_support",
     "//components/feature_engagement/public",
diff --git a/components/user_education/common/events.cc b/components/user_education/common/events.cc
new file mode 100644
index 0000000..cee8bd5
--- /dev/null
+++ b/components/user_education/common/events.cc
@@ -0,0 +1,12 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/user_education/common/events.h"
+
+namespace user_education {
+
+DEFINE_CUSTOM_ELEMENT_EVENT_TYPE(kHelpBubbleAnchorBoundsChangedEvent);
+DEFINE_CUSTOM_ELEMENT_EVENT_TYPE(kHelpBubbleNextButtonClickedEvent);
+
+}  // namespace user_education
diff --git a/components/user_education/common/events.h b/components/user_education/common/events.h
new file mode 100644
index 0000000..1ecc5f7
--- /dev/null
+++ b/components/user_education/common/events.h
@@ -0,0 +1,23 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_USER_EDUCATION_COMMON_EVENTS_H_
+#define COMPONENTS_USER_EDUCATION_COMMON_EVENTS_H_
+
+#include "base/component_export.h"
+#include "ui/base/interaction/element_tracker.h"
+
+namespace user_education {
+
+DECLARE_EXPORTED_CUSTOM_ELEMENT_EVENT_TYPE(
+    COMPONENT_EXPORT(USER_EDUCATION_COMMON_EVENTS),
+    kHelpBubbleAnchorBoundsChangedEvent);
+
+DECLARE_EXPORTED_CUSTOM_ELEMENT_EVENT_TYPE(
+    COMPONENT_EXPORT(USER_EDUCATION_COMMON_EVENTS),
+    kHelpBubbleNextButtonClickedEvent);
+
+}  // namespace user_education
+
+#endif  // COMPONENTS_USER_EDUCATION_COMMON_EVENTS_H_
diff --git a/components/user_education/common/help_bubble.cc b/components/user_education/common/help_bubble.cc
index 9d1cf44..ea0915d 100644
--- a/components/user_education/common/help_bubble.cc
+++ b/components/user_education/common/help_bubble.cc
@@ -9,9 +9,6 @@
 
 namespace user_education {
 
-DEFINE_CUSTOM_ELEMENT_EVENT_TYPE(kHelpBubbleAnchorBoundsChangedEvent);
-DEFINE_CUSTOM_ELEMENT_EVENT_TYPE(kHelpBubbleNextButtonClickedEvent);
-
 HelpBubble::HelpBubble()
     : on_close_callbacks_(std::make_unique<CallbackList>()) {}
 
diff --git a/components/user_education/common/help_bubble.h b/components/user_education/common/help_bubble.h
index 451c8aa..6b04d14 100644
--- a/components/user_education/common/help_bubble.h
+++ b/components/user_education/common/help_bubble.h
@@ -15,9 +15,6 @@
 
 namespace user_education {
 
-DECLARE_CUSTOM_ELEMENT_EVENT_TYPE(kHelpBubbleAnchorBoundsChangedEvent);
-DECLARE_CUSTOM_ELEMENT_EVENT_TYPE(kHelpBubbleNextButtonClickedEvent);
-
 // HelpBubble is an interface for the lifecycle of an IPH or tutorial bubble.
 // it is implemented by a framework's bubble. It is returned as the result of
 // HelpBubbleFactory's CreateBubble...() method.
diff --git a/components/user_education/common/tutorial_description.cc b/components/user_education/common/tutorial_description.cc
index 113326db..d9d1611f 100644
--- a/components/user_education/common/tutorial_description.cc
+++ b/components/user_education/common/tutorial_description.cc
@@ -4,6 +4,7 @@
 
 #include "components/user_education/common/tutorial_description.h"
 
+#include "components/user_education/common/events.h"
 #include "components/user_education/common/help_bubble.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
diff --git a/components/user_education/common/tutorial_unittest.cc b/components/user_education/common/tutorial_unittest.cc
index 44744ed..d90d2e3 100644
--- a/components/user_education/common/tutorial_unittest.cc
+++ b/components/user_education/common/tutorial_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/scoped_run_loop_timeout.h"
 #include "base/test/task_environment.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/user_education/common/events.h"
 #include "components/user_education/common/help_bubble_factory_registry.h"
 #include "components/user_education/common/help_bubble_params.h"
 #include "components/user_education/common/tutorial_description.h"
diff --git a/components/user_education/views/BUILD.gn b/components/user_education/views/BUILD.gn
index 9d5e4f8b..48e7e0b 100644
--- a/components/user_education/views/BUILD.gn
+++ b/components/user_education/views/BUILD.gn
@@ -30,6 +30,7 @@
   deps = [
     "//base",
     "//components/strings",
+    "//components/user_education/common:events",
     "//components/variations",
     "//components/vector_icons",
     "//skia",
@@ -79,6 +80,7 @@
     "//components/feature_engagement/public",
     "//components/strings",
     "//components/user_education/common",
+    "//components/user_education/common:events",
     "//components/user_education/test",
     "//components/variations",
     "//skia",
diff --git a/components/user_education/views/help_bubble_factory_views.cc b/components/user_education/views/help_bubble_factory_views.cc
index 05de23e..1a4231a 100644
--- a/components/user_education/views/help_bubble_factory_views.cc
+++ b/components/user_education/views/help_bubble_factory_views.cc
@@ -10,6 +10,7 @@
 #include "base/functional/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "components/user_education/common/events.h"
 #include "components/user_education/common/help_bubble.h"
 #include "components/user_education/common/help_bubble_params.h"
 #include "components/user_education/common/user_education_class_properties.h"
diff --git a/components/user_education/views/help_bubble_view_unittest.cc b/components/user_education/views/help_bubble_view_unittest.cc
index 780e58a..5535f0eb 100644
--- a/components/user_education/views/help_bubble_view_unittest.cc
+++ b/components/user_education/views/help_bubble_view_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/functional/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
 #include "base/test/mock_callback.h"
+#include "components/user_education/common/events.h"
 #include "components/user_education/common/feature_promo_specification.h"
 #include "components/user_education/common/help_bubble.h"
 #include "components/user_education/common/help_bubble_params.h"
diff --git a/components/user_education/webui/BUILD.gn b/components/user_education/webui/BUILD.gn
index 7f3af412..c3ff367 100644
--- a/components/user_education/webui/BUILD.gn
+++ b/components/user_education/webui/BUILD.gn
@@ -17,6 +17,7 @@
   deps = [
     "//base",
     "//components/user_education/common",
+    "//components/user_education/common:events",
     "//components/user_education/views",
     "//components/vector_icons",
     "//content/public/browser",
diff --git a/components/user_education/webui/tracked_element_webui.cc b/components/user_education/webui/tracked_element_webui.cc
index 515acfe..b1e0abae 100644
--- a/components/user_education/webui/tracked_element_webui.cc
+++ b/components/user_education/webui/tracked_element_webui.cc
@@ -5,6 +5,7 @@
 #include "components/user_education/webui/tracked_element_webui.h"
 
 #include "base/check.h"
+#include "components/user_education/common/events.h"
 #include "components/user_education/common/help_bubble.h"
 #include "components/user_education/webui/help_bubble_handler.h"
 #include "content/public/browser/web_contents.h"
diff --git a/components/webxr/android/java/res/layout/cardboard_ui.xml b/components/webxr/android/java/res/layout/cardboard_ui.xml
index fafc5b8..ae9e1ee 100644
--- a/components/webxr/android/java/res/layout/cardboard_ui.xml
+++ b/components/webxr/android/java/res/layout/cardboard_ui.xml
@@ -52,11 +52,11 @@
             <org.chromium.ui.widget.ChromeImageButton
                 style="@style/CardboardUiButton"
                 android:id="@+id/cardboard_ui_settings_button"
-                android:contentDescription="@string/menu"
+                android:contentDescription="@string/vr_menu"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:src="@drawable/ic_more_vert_24dp_on_dark_bg"
                 android:layout_gravity="end|top"/>
         </FrameLayout>
 
-</RelativeLayout>
\ No newline at end of file
+</RelativeLayout>
diff --git a/components/webxr/android/java/res/values/dimens.xml b/components/webxr/android/java/res/values/dimens.xml
index 4213ec3d..2926e1c 100644
--- a/components/webxr/android/java/res/values/dimens.xml
+++ b/components/webxr/android/java/res/values/dimens.xml
@@ -10,8 +10,8 @@
     <!-- Thickess of thin line. -->
     <dimen name="align_marker_thickness">2dip</dimen>
 
-    <dimen name="ui_button_width">24dp</dimen>
-    <dimen name="ui_button_height">24dp</dimen>
+    <dimen name="ui_button_width">48dp</dimen>
+    <dimen name="ui_button_height">48dp</dimen>
     <dimen name="ui_settings_button_margin_top">16dp</dimen>
     <dimen name="ui_settings_button_margin_right">16dp</dimen>
     <dimen name="ui_close_button_margin_top">16dp</dimen>
@@ -21,7 +21,7 @@
     <dimen name="pop_up_menu_margin_horizontal">0dp</dimen>
     <!--
     Given that the menu has to overlap the button, a vertical offset of
-    -24dp is needed, which is the expected height of the button image.
+    -48dp is needed, which is the expected height of the button image.
     -->
-    <dimen name="pop_up_menu_margin_vertical">-24dp</dimen>
+    <dimen name="pop_up_menu_margin_vertical">-48dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/components/webxr_strings.grdp b/components/webxr_strings.grdp
index 05f44f83..a4f2c030 100644
--- a/components/webxr_strings.grdp
+++ b/components/webxr_strings.grdp
@@ -20,5 +20,8 @@
     <message name="IDS_USE_ANOTHER_DEVICE" desc="Short text shown on the settings menu to let the user switch viewer.[CHAR_LIMIT=30]" formatter_data="android_java">
       Use another device
     </message>
+    <message name="IDS_VR_MENU" desc="The accessible name for the VR Menu. This is used as the aria-roledescription for context menus." formatter_data="android_java">
+        VR Menu
+    </message>
   </if>
 </grit-part>
diff --git a/components/webxr_strings_grdp/IDS_VR_MENU.png.sha1 b/components/webxr_strings_grdp/IDS_VR_MENU.png.sha1
new file mode 100644
index 0000000..24fc53d0
--- /dev/null
+++ b/components/webxr_strings_grdp/IDS_VR_MENU.png.sha1
@@ -0,0 +1 @@
+d563a8a865e9c7f30765c9e2ddd5efaabbee3eff
\ No newline at end of file
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 9b8162d..5dcd887 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1118,8 +1118,6 @@
     "indexed_db/indexed_db_internals_ui.h",
     "indexed_db/indexed_db_leveldb_coding.cc",
     "indexed_db/indexed_db_leveldb_coding.h",
-    "indexed_db/indexed_db_leveldb_env.cc",
-    "indexed_db/indexed_db_leveldb_env.h",
     "indexed_db/indexed_db_leveldb_operations.cc",
     "indexed_db/indexed_db_leveldb_operations.h",
     "indexed_db/indexed_db_pending_connection.cc",
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc
index 5faeef7..8ad1c2d 100644
--- a/content/browser/attribution_reporting/attribution_storage_sql.cc
+++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -1072,8 +1072,12 @@
   // Prioritization is scoped within report windows.
   // This is reasonably optimized as is because we only store a ~small number
   // of reports per source_id. Selects the report with lowest priority,
-  // and uses the greatest trigger_time to break ties. This favors sending
-  // reports for report closer to the source time.
+  // and uses the greatest rowid to break ties. This favors sending
+  // reports for report closer to the source time. report_id is used instead of
+  // trigger time because the former is strictly increasing while the latter is
+  // subject to clock adjustments. This property is only guaranteed because of
+  // the use of AUTOINCREMENT on the report_id column, which prevents reuse upon
+  // row deletion.
   sql::Statement min_priority_statement(db_.GetCachedStatement(
       SQL_FROM_HERE, attribution_queries::kMinPrioritySql));
   min_priority_statement.BindInt64(0, *source.source_id());
@@ -1081,7 +1085,6 @@
 
   absl::optional<AttributionReport::Id> conversion_id_with_min_priority;
   int64_t min_priority;
-  base::Time max_trigger_time;
 
   while (min_priority_statement.Step()) {
     std::string metadata;
@@ -1094,15 +1097,15 @@
     if (!DeserializeReportMetadata(metadata, trigger_data, priority)) {
       continue;
     }
-    base::Time trigger_time = min_priority_statement.ColumnTime(1);
+
+    AttributionReport::Id report_id(min_priority_statement.ColumnInt64(1));
 
     if (!conversion_id_with_min_priority.has_value() ||
         priority < min_priority ||
-        (priority == min_priority && trigger_time > max_trigger_time)) {
-      conversion_id_with_min_priority.emplace(
-          min_priority_statement.ColumnInt64(2));
+        (priority == min_priority &&
+         report_id > *conversion_id_with_min_priority)) {
+      conversion_id_with_min_priority = report_id;
       min_priority = priority;
-      max_trigger_time = trigger_time;
     }
   }
 
diff --git a/content/browser/attribution_reporting/attribution_storage_unittest.cc b/content/browser/attribution_reporting/attribution_storage_unittest.cc
index 1f3eca6..0ba594f 100644
--- a/content/browser/attribution_reporting/attribution_storage_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_storage_unittest.cc
@@ -1837,10 +1837,11 @@
        MultipleImpressionsPerConversion_MostRecentAttributesForSamePriority) {
   storage()->StoreSource(SourceBuilder().SetSourceEventId(3).Build());
 
-  task_environment_.FastForwardBy(base::Milliseconds(1));
+  // Note: Fast-forwards aren't necessary here because source order for the
+  // purposes of prioritization is based on rowid, not source time.
+
   storage()->StoreSource(SourceBuilder().SetSourceEventId(7).Build());
 
-  task_environment_.FastForwardBy(base::Milliseconds(1));
   storage()->StoreSource(SourceBuilder().SetSourceEventId(5).Build());
 
   EXPECT_THAT(storage()->GetActiveSources(), SizeIs(3));
@@ -2114,21 +2115,23 @@
             MaybeCreateAndStoreEventLevelReport(
                 TriggerBuilder().SetPriority(1).SetTriggerData(3).Build()));
 
-  task_environment_.FastForwardBy(base::Milliseconds(1));
+  // Note: Fast-forwards aren't necessary here because trigger order for the
+  // purposes of prioritization is based on rowid, not trigger time.
+
   EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess,
             MaybeCreateAndStoreEventLevelReport(
                 TriggerBuilder().SetPriority(1).SetTriggerData(2).Build()));
 
   // This report should not be stored, as even though it has the same priority
   // as the previous two, it is the most recent.
-  task_environment_.FastForwardBy(base::Milliseconds(1));
+
   EXPECT_EQ(AttributionTrigger::EventLevelResult::kPriorityTooLow,
             MaybeCreateAndStoreEventLevelReport(
                 TriggerBuilder().SetPriority(1).SetTriggerData(8).Build()));
 
   // This report should be stored by replacing the one with `trigger_data ==
   // 2`, which is the most recent of the two with `priority == 1`.
-  task_environment_.FastForwardBy(base::Milliseconds(1));
+
   EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccessDroppedLowerPriority,
             MaybeCreateAndStoreEventLevelReport(
                 TriggerBuilder().SetPriority(2).SetTriggerData(5).Build()));
diff --git a/content/browser/attribution_reporting/sql_queries.h b/content/browser/attribution_reporting/sql_queries.h
index 1f02625e..a81829c 100644
--- a/content/browser/attribution_reporting/sql_queries.h
+++ b/content/browser/attribution_reporting/sql_queries.h
@@ -14,9 +14,13 @@
                   attribution_reporting::mojom::ReportType::kEventLevel) == 0,
               "update `report_type=0` clause below");
 inline constexpr const char kMinPrioritySql[] =
-    "SELECT metadata,trigger_time,report_id FROM reports "
+    "SELECT metadata,report_id FROM reports "
     "WHERE source_id=? AND report_time=? AND report_type=0";
 
+// Rows are ordered by source_id instead of source_time because the former is
+// strictly increasing while the latter is subject to clock adjustments. This
+// property is only guaranteed because of the use of AUTOINCREMENT on the
+// source_id column, which prevents reuse upon row deletion.
 inline constexpr const char kGetMatchingSourcesSql[] =
     "SELECT I.source_id,I.num_attributions,I.aggregatable_budget_consumed "
     "FROM sources I "
@@ -25,7 +29,7 @@
     "WHERE I.reporting_origin=? "
     "AND(I.event_level_active=1 OR I.aggregatable_active=1)"
     "AND I.expiry_time>? "
-    "ORDER BY I.priority DESC,I.source_time DESC";
+    "ORDER BY I.priority DESC,I.source_id DESC";
 
 inline constexpr const char kSelectExpiredSourcesSql[] =
     "SELECT source_id FROM sources "
diff --git a/content/browser/file_system_access/file_system_access_change_source.cc b/content/browser/file_system_access/file_system_access_change_source.cc
index e23d8a3..bc7cbfc 100644
--- a/content/browser/file_system_access/file_system_access_change_source.cc
+++ b/content/browser/file_system_access/file_system_access_change_source.cc
@@ -28,12 +28,13 @@
 }
 
 void FileSystemAccessChangeSource::EnsureInitialized(
-    base::OnceCallback<void(bool)> on_source_initialized) {
+    base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+        on_source_initialized) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (initialization_result_.has_value()) {
     CHECK(initialization_callbacks_.empty());
-    std::move(on_source_initialized).Run(*initialization_result_);
+    std::move(on_source_initialized).Run(initialization_result_->Clone());
     return;
   }
 
@@ -46,18 +47,19 @@
                             weak_factory_.GetWeakPtr()));
 }
 
-void FileSystemAccessChangeSource::DidInitialize(bool result) {
+void FileSystemAccessChangeSource::DidInitialize(
+    blink::mojom::FileSystemAccessErrorPtr result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CHECK(!initialization_result_.has_value());
   CHECK(!initialization_callbacks_.empty());
 
-  initialization_result_ = result;
+  initialization_result_ = std::move(result);
 
   // Move the callbacks to the stack since they may cause |this| to be deleted.
   auto initialization_callbacks = std::move(initialization_callbacks_);
   initialization_callbacks_.clear();
   for (auto& callback : initialization_callbacks) {
-    std::move(callback).Run(result);
+    std::move(callback).Run(initialization_result_->Clone());
   }
 }
 
diff --git a/content/browser/file_system_access/file_system_access_change_source.h b/content/browser/file_system_access/file_system_access_change_source.h
index f2ee0d35..01eb7d0 100644
--- a/content/browser/file_system_access/file_system_access_change_source.h
+++ b/content/browser/file_system_access/file_system_access_change_source.h
@@ -17,6 +17,7 @@
 #include "content/browser/file_system_access/file_system_access_watch_scope.h"
 #include "content/common/content_export.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h"
 
 namespace content {
 
@@ -46,11 +47,13 @@
 
   // Ensures that this change source is ready to watch for changes within its
   // `scope_`. This may fail if the scope cannot be watched.
-  // `on_source_initialized` is run with a bool indicating whether setting up
-  // this source succeeds.
+  // `on_source_initialized` is run with a error status indicating whether
+  // setting up this source succeeds.
   // TODO(https://crbug.com/1019297): Assert that this is called before
   // notifying of changes.
-  void EnsureInitialized(base::OnceCallback<void(bool)> on_source_initialized);
+  void EnsureInitialized(
+      base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+          on_source_initialized);
 
   base::WeakPtr<FileSystemAccessChangeSource> AsWeakPtr();
 
@@ -58,7 +61,8 @@
 
  protected:
   virtual void Initialize(
-      base::OnceCallback<void(bool)> on_source_initialized) = 0;
+      base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+          on_source_initialized) = 0;
 
   // Called by subclasses to record changes to watched paths.
   void NotifyOfChange(const base::FilePath& relative_path, bool error);
@@ -66,13 +70,13 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
  private:
-  void DidInitialize(bool result);
+  void DidInitialize(blink::mojom::FileSystemAccessErrorPtr result);
 
   const FileSystemAccessWatchScope scope_;
 
-  absl::optional<bool> initialization_result_;
-  std::list<base::OnceCallback<void(bool)>> initialization_callbacks_
-      GUARDED_BY_CONTEXT(sequence_checker_);
+  absl::optional<blink::mojom::FileSystemAccessErrorPtr> initialization_result_;
+  std::list<base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>>
+      initialization_callbacks_ GUARDED_BY_CONTEXT(sequence_checker_);
 
   base::ObserverList<RawChangeObserver> observers_
       GUARDED_BY_CONTEXT(sequence_checker_);
diff --git a/content/browser/file_system_access/file_system_access_local_path_watcher.cc b/content/browser/file_system_access/file_system_access_local_path_watcher.cc
index 1879441..602a1b2 100644
--- a/content/browser/file_system_access/file_system_access_local_path_watcher.cc
+++ b/content/browser/file_system_access/file_system_access_local_path_watcher.cc
@@ -8,8 +8,10 @@
 #include "base/files/file_path_watcher.h"
 #include "base/task/bind_post_task.h"
 #include "base/task/thread_pool.h"
+#include "content/browser/file_system_access/file_system_access_error.h"
 #include "content/browser/file_system_access/file_system_access_watcher_manager.h"
 #include "storage/browser/file_system/file_system_url.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-shared.h"
 
 namespace content {
 
@@ -40,12 +42,15 @@
 FileSystemAccessLocalPathWatcher::~FileSystemAccessLocalPathWatcher() = default;
 
 void FileSystemAccessLocalPathWatcher::Initialize(
-    base::OnceCallback<void(bool)> on_source_initialized) {
+    base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+        on_source_initialized) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (scope().IsRecursive() &&
       !base::FilePathWatcher::RecursiveWatchAvailable()) {
-    std::move(on_source_initialized).Run(false);
+    std::move(on_source_initialized)
+        .Run(file_system_access_error::FromStatus(
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError));
     return;
   }
 
@@ -71,7 +76,17 @@
       .WithArgs(
           scope().root_url().path(), std::move(watch_options),
           base::BindPostTaskToCurrentDefault(std::move(on_change_callback)))
-      .Then(std::move(on_source_initialized));
+      .Then(base::BindOnce(
+          [](base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+                 callback,
+             bool result) {
+            std::move(callback).Run(
+                result ? file_system_access_error::Ok()
+                       : file_system_access_error::FromStatus(
+                             blink::mojom::FileSystemAccessStatus::
+                                 kOperationFailed));
+          },
+          std::move(on_source_initialized)));
 }
 
 void FileSystemAccessLocalPathWatcher::OnFilePathChanged(
diff --git a/content/browser/file_system_access/file_system_access_local_path_watcher.h b/content/browser/file_system_access/file_system_access_local_path_watcher.h
index b429292..b8a18f7 100644
--- a/content/browser/file_system_access/file_system_access_local_path_watcher.h
+++ b/content/browser/file_system_access/file_system_access_local_path_watcher.h
@@ -31,7 +31,8 @@
 
   // FileSystemAccessChangeSource:
   void Initialize(
-      base::OnceCallback<void(bool)> on_source_initialized) override;
+      base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+          on_source_initialized) override;
 
  private:
   void OnFilePathChanged(const base::FilePath& changed_path, bool error);
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc
index faa3f12e4..16af9918 100644
--- a/content/browser/file_system_access/file_system_access_manager_impl.cc
+++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
@@ -1017,6 +1017,11 @@
   }
 }
 
+void FileSystemAccessManagerImpl::Clone(
+    mojo::PendingReceiver<storage::mojom::FileSystemAccessContext> receiver) {
+  BindInternalsReceiver(std::move(receiver));
+}
+
 blink::mojom::FileSystemAccessEntryPtr
 FileSystemAccessManagerImpl::CreateFileEntryFromPath(
     const BindingContext& binding_context,
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.h b/content/browser/file_system_access/file_system_access_manager_impl.h
index 2b682805..44761b7 100644
--- a/content/browser/file_system_access/file_system_access_manager_impl.h
+++ b/content/browser/file_system_access/file_system_access_manager_impl.h
@@ -154,6 +154,8 @@
       const std::vector<uint8_t>& bits,
       mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token)
       override;
+  void Clone(mojo::PendingReceiver<storage::mojom::FileSystemAccessContext>
+                 receiver) override;
 
   // FileSystemAccessEntryFactory:
   blink::mojom::FileSystemAccessEntryPtr CreateFileEntryFromPath(
diff --git a/content/browser/file_system_access/file_system_access_observer_browsertest.cc b/content/browser/file_system_access/file_system_access_observer_browsertest.cc
index 63f366a4..dec238d 100644
--- a/content/browser/file_system_access/file_system_access_observer_browsertest.cc
+++ b/content/browser/file_system_access/file_system_access_observer_browsertest.cc
@@ -20,6 +20,58 @@
 
 namespace content {
 
+// Helpful macros to reduce the boilerplate script in the tests below.
+
+// Resolves a promise with a serialized copy of the first `records` fired in the
+// change callback.
+//
+// Notably, several FileSystemChangeRecord fields are not serializable, so tests
+// which need to assert some behavior about the non-serializable fields may
+// overwrite the `onChange` function.
+#define CREATE_PROMISE_AND_RESOLVERS \
+  "let promiseResolve, promiseReject; \
+   let promise = new Promise(function(resolve, reject) { \
+     promiseResolve = resolve; \
+     promiseReject = reject; \
+   }); \
+   async function onChange(records, observer) { \
+     let serializedRecords = records.map(record => { \
+       let info = {}; \
+       info.type = record.type; \
+       info.relativePathComponents = record.relativePathComponents; \
+       return info; \
+     }); \
+     promiseResolve(serializedRecords); \
+   };"
+
+#define START_OBSERVING_LOCAL_FILE \
+  "const [file] = await self.showOpenFilePicker();    \
+   const observer = new FileSystemObserver(onChange);  \
+   await observer.observe(file);"
+
+#define START_OBSERVING_LOCAL_DIRECTORY \
+  "const dir = await self.showDirectoryPicker();    \
+   const observer = new FileSystemObserver(onChange);  \
+   await observer.observe(dir);"
+
+#define START_RECURSIVELY_OBSERVING_LOCAL_DIRECTORY \
+  "const dir = await self.showDirectoryPicker();    \
+   const observer = new FileSystemObserver(onChange);  \
+   await observer.observe(dir, { recursive: true });"
+
+#define WRITE_TO_FILE \
+  "const writable = await file.createWritable();  \
+   await writable.write('blah');                  \
+   await writable.close();"
+
+#define SET_CHANGE_TIMEOUT     \
+  +JsReplace(                  \
+      "setTimeout(() => {      \
+         promiseResolve([]);   \
+       }, $1);                 \
+       return await promise;", \
+      base::Int64ToValue(TestTimeouts::tiny_timeout().InMilliseconds())) +
+
 // TODO(https://crbug.com/1019297): Consider making these WPTs, and adding a
 // lot more of them. For example:
 //   - change types
@@ -82,19 +134,6 @@
     return dir_path;
   }
 
-  bool CreatePromiseAndResolvers() {
-    return ExecJs(shell(),
-                  "(async () => {"
-                  "self.promise = new Promise(function(resolve, reject) {"
-                  "  self.promiseResolve = resolve;"
-                  "  self.promiseReject = reject;"
-                  "});"
-                  "async function onChange(records, observer) {"
-                  "  self.promiseResolve(true);"
-                  "};"
-                  "self.onChange = onChange; })()");
-  }
-
  protected:
   base::ScopedTempDir temp_dir_;
   GURL test_url_;
@@ -160,29 +199,25 @@
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest, ObserveFile) {
   base::FilePath file_path = CreateFileToBePicked();
 
-// `base::FilePatchWatcher` is not implemented on Fuchsia. See
-// https://crbug.com/851641. Instead, just check that attempting to observe a
-// handle does not crash.
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         WRITE_TO_FILE
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto result = EvalJs(shell(), script);
 #if BUILDFLAG(IS_FUCHSIA)
-  auto result = EvalJs(shell(),
-                       "(async () => {"
-                       "const [file] = await self.showOpenFilePicker();"
-                       "const observer = new FileSystemObserver(() => {});"
-                       "await observer.observe(file); })()");
+  // `base::FilePatchWatcher` is not implemented on Fuchsia. See
+  // https://crbug.com/851641. Instead, just check that attempting to observe a
+  // handle does not crash.
   EXPECT_TRUE(result.error.find("did not support") != std::string::npos)
       << result.error;
 #else
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  EXPECT_TRUE(EvalJs(shell(),
-                     "(async () => {"
-                     "const [file] = await self.showOpenFilePicker();"
-                     "const observer = new FileSystemObserver(self.onChange);"
-                     "await observer.observe(file);"
-                     "const writable = await file.createWritable();"
-                     "await writable.write('blah');"
-                     "await writable.close();"
-                     "return await self.promise; })()")
-                  .ExtractBool());
+  auto records = result.ExtractList();
+  EXPECT_THAT(records.GetList(), testing::Not(testing::IsEmpty()));
 #endif  // BUILDFLAG(IS_FUCHSIA)
 }
 
@@ -193,42 +228,42 @@
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest, ObserveFileRename) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  EXPECT_TRUE(EvalJs(shell(),
-                     "(async () => {"
-                     "const [file] = await self.showOpenFilePicker();"
-                     "const observer = new FileSystemObserver(self.onChange);"
-                     "await observer.observe(file);"
-                     "await file.move('newName.txt');"
-                     "return await self.promise; })()")
-                  .ExtractBool());
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         "await file.move('newName.txt');"
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto records = EvalJs(shell(), script).ExtractList();
+  EXPECT_THAT(records.GetList(), testing::Not(testing::IsEmpty()));
 }
 #endif  // !BUILDFLAG(IS_FUCHSIA)
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest, ObserveDirectory) {
   base::FilePath dir_path = CreateDirectoryToBePicked();
 
-// `base::FilePatchWatcher` is not implemented on Fuchsia. See
-// https://crbug.com/851641. Instead, just check that attempting to observe a
-// handle does not crash.
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_DIRECTORY
+         "await dir.getFileHandle('newFile.txt', { create: true });"
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto result = EvalJs(shell(), script);
 #if BUILDFLAG(IS_FUCHSIA)
-  auto result = EvalJs(shell(),
-                       "(async () => {"
-                       "const dir = await self.showDirectoryPicker();"
-                       "const observer = new FileSystemObserver(() => {});"
-                       "await observer.observe(dir); })()");
+  // `base::FilePatchWatcher` is not implemented on Fuchsia. See
+  // https://crbug.com/851641. Instead, just check that attempting to observe a
+  // handle does not crash.
   EXPECT_TRUE(result.error.find("did not support") != std::string::npos)
       << result.error;
 #else
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  EXPECT_TRUE(EvalJs(shell(),
-                     "(async () => {"
-                     "const dir = await self.showDirectoryPicker();"
-                     "const observer = new FileSystemObserver(self.onChange);"
-                     "await observer.observe(dir);"
-                     "await dir.getFileHandle('newFile.txt', { create:true });"
-                     "return await self.promise; })()")
-                  .ExtractBool());
+  auto records = result.ExtractList();
+  EXPECT_THAT(records.GetList(), testing::Not(testing::IsEmpty()));
 #endif  // BUILDFLAG(IS_FUCHSIA)
 }
 
@@ -241,32 +276,29 @@
     base::CreateDirectory(dir_path.AppendASCII("sub1").AppendASCII("sub2"));
   }
 
-// `base::FilePatchWatcher` is not implemented on Fuchsia. See
-// https://crbug.com/851641. Instead, just check that attempting to observe a
-// handle does not crash.
-// Meanwhile, recursive watches are not supported on iOS.
+  // The creation of 'newFile.txt' should trigger a change record.
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_RECURSIVELY_OBSERVING_LOCAL_DIRECTORY
+         "const subDir1 = await dir.getDirectoryHandle('sub1');"
+         "const subDir2 = await subDir1.getDirectoryHandle('sub2');"
+         "await subDir2.getFileHandle('newFile.txt', { create: true });"
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto result = EvalJs(shell(), script);
 #if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_IOS)
-  auto result =
-      EvalJs(shell(),
-             "(async () => {"
-             "const dir = await self.showDirectoryPicker();"
-             "const observer = new FileSystemObserver(() => {});"
-             "await observer.observe(dir, { recursive: true }); })()");
+  // `base::FilePatchWatcher` is not implemented on Fuchsia. See
+  // https://crbug.com/851641. Instead, just check that attempting to observe a
+  // handle does not crash.
+  // Meanwhile, recursive watches are not supported on iOS.
   EXPECT_TRUE(result.error.find("did not support") != std::string::npos)
       << result.error;
 #else
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  EXPECT_TRUE(
-      EvalJs(shell(),
-             "(async () => {"
-             "const dir = await self.showDirectoryPicker();"
-             "const observer = new FileSystemObserver(self.onChange);"
-             "await observer.observe(dir, { recursive: true });"
-             "const subDir1 = await dir.getDirectoryHandle('sub1');"
-             "const subDir2 = await subDir1.getDirectoryHandle('sub2');"
-             "await subDir2.getFileHandle('newFile.txt', { create: true });"
-             "return await self.promise; })()")
-          .ExtractBool());
+  auto records = result.ExtractList();
+  EXPECT_THAT(records.GetList(), testing::Not(testing::IsEmpty()));
 #endif  // BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_IOS)
 }
 
@@ -276,95 +308,86 @@
                        ObserveThenUnobserve) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  // Calling unobserve() with a corresponding observe() should not crash.
-  EXPECT_TRUE(ExecJs(shell(),
-                     "(async () => {"
-                     "const [file] = await self.showOpenFilePicker();"
-                     "const observer = new FileSystemObserver(() => {});"
-                     "await observer.observe(file);"
-                     "observer.unobserve(file); })()"));
+  // Calling unobserve() on an active observation should not crash.
+  const char* script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         "observer.unobserve(file);"
+      "})()";
+  // clang-format on
+  EXPECT_TRUE(ExecJs(shell(), script));
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        ObserveThenUnobserveUnrelated) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  // Calling unobserve() with a handle unrelated to a corresponding observe()
+  // Calling unobserve() with a handle unrelated to any active observations
   // should not crash.
-  EXPECT_TRUE(ExecJs(shell(),
-                     "(async () => {"
-                     "const [file] = await self.showOpenFilePicker();"
-                     "const root = await navigator.storage.getDirectory();"
-                     "const observer = new FileSystemObserver(() => {});"
-                     "await observer.observe(file);"
-                     "observer.unobserve(root); })()"));
+  const char* script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         "const unrelatedDir = await navigator.storage.getDirectory();"
+         "observer.unobserve(unrelatedDir);"
+      "})()";
+  // clang-format on
+  EXPECT_TRUE(ExecJs(shell(), script));
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        NoChangesAfterUnobserve) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  // No changes should be received. The promise should be resolved after the
-  // setTimeout().
-  EXPECT_FALSE(
-      EvalJs(shell(),
-             JsReplace(
-                 "(async () => {"
-                 "const [file] = await self.showOpenFilePicker();"
-                 "const observer = new FileSystemObserver(self.onChange);"
-                 "await observer.observe(file);"
-                 "observer.unobserve(file);"
-                 "const writable = await file.createWritable();"
-                 "await writable.write('blah');"
-                 "await writable.close();"
-                 "setTimeout(() => {"
-                 "  self.promiseResolve(false);"  // No changes received. Good!
-                 "}, $1);"
-                 "return await self.promise; })()",
-                 base::Int64ToValue(
-                     TestTimeouts::tiny_timeout().InMilliseconds())))
-          .ExtractBool());
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         "observer.unobserve(file);"
+         WRITE_TO_FILE
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto records = EvalJs(shell(), script).ExtractList();
+  EXPECT_THAT(records.GetList(), testing::IsEmpty());
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        ObserveThenDisconnect) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  // Calling disconnect() after calling observe() should not crash.
-  EXPECT_TRUE(ExecJs(shell(),
-                     "(async () => {"
-                     "const [file] = await self.showOpenFilePicker();"
-                     "const observer = new FileSystemObserver(() => {});"
-                     "await observer.observe(file);"
-                     "observer.disconnect(); })()"));
+  // Calling disconnect() with active observations should not crash.
+  const char* script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         "observer.disconnect();"
+      "})()";
+  // clang-format on
+  EXPECT_TRUE(ExecJs(shell(), script));
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        NoChangesAfterDisconnect) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  // No changes should be received. The promise should be resolved after the
-  // setTimeout().
-  EXPECT_FALSE(
-      EvalJs(shell(),
-             JsReplace(
-                 "(async () => {"
-                 "const [file] = await self.showOpenFilePicker();"
-                 "const observer = new FileSystemObserver(self.onChange);"
-                 "await observer.observe(file);"
-                 "observer.disconnect();"
-                 "const writable = await file.createWritable();"
-                 "await writable.write('blah');"
-                 "await writable.close();"
-                 "setTimeout(() => {"
-                 "  self.promiseResolve(false);"  // No changes received. Good!
-                 "}, $1);"
-                 "return await self.promise; })()",
-                 base::Int64ToValue(
-                     TestTimeouts::tiny_timeout().InMilliseconds())))
-          .ExtractBool());
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         "observer.disconnect();"
+         WRITE_TO_FILE
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto records = EvalJs(shell(), script).ExtractList();
+  EXPECT_THAT(records.GetList(), testing::IsEmpty());
 }
 
 // TODO(https://crbug.com/1019297): Add a ReObserveAfterUnobserve test once the
@@ -373,160 +396,140 @@
                        ReObserveAfterDisconnect) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  EXPECT_TRUE(EvalJs(shell(),
-                     "(async () => {"
-                     "const [file] = await self.showOpenFilePicker();"
-                     "const observer = new FileSystemObserver(self.onChange);"
-                     "await observer.observe(file);"
-                     "observer.disconnect();"
-                     "await observer.observe(file);"  // Start observing the
-                                                      // file again.
-                     "const writable = await file.createWritable();"
-                     "await writable.write('blah');"
-                     "await writable.close();"  // We should see this change.
-                     "return await self.promise; })()")
-                  .ExtractBool());
+  // We should see changes after re-observing the file.
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         "observer.disconnect();"
+         "await observer.observe(file);"
+         WRITE_TO_FILE
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto records = EvalJs(shell(), script).ExtractList();
+  EXPECT_THAT(records.GetList(), testing::Not(testing::IsEmpty()));
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        ObserveFileReportsModifiedType) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  ASSERT_TRUE(CreatePromiseAndResolvers());
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         WRITE_TO_FILE
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto records = EvalJs(shell(), script).ExtractList();
+  ASSERT_THAT(records.GetList(), testing::Not(testing::IsEmpty()));
   // TODO(https://crbug.com/1425601): Support change types. For now, just
   // confirm that "modified" is plumbed through properly.
-  EXPECT_TRUE(EvalJs(shell(),
-                     "(async () => {"
-                     "async function onChange(records, observer) {"
-                     "  const record = records[0];"
-                     "  promiseResolve(record.type === 'modified');"
-                     "};"
-                     "const [file] = await self.showOpenFilePicker();"
-                     "const observer = new FileSystemObserver(onChange);"
-                     "await observer.observe(file);"
-                     "const writable = await file.createWritable();"
-                     "await writable.write('blah');"
-                     "await writable.close();"
-                     "return await self.promise; })()")
-                  .ExtractBool());
+  EXPECT_THAT(*records.GetList().front().GetDict().FindString("type"),
+              testing::StrEq("modified"));
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        ObserveFileReportsCorrectHandle) {
-  base::FilePath file_path;
-  {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    EXPECT_TRUE(
-        base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
-    EXPECT_TRUE(base::WriteFile(file_path, "observe me"));
-  }
+  base::FilePath file_path = CreateFileToBePicked();
 
-  ui::SelectFileDialog::SetFactory(
-      std::make_unique<FakeSelectFileDialogFactory>(
-          std::vector<base::FilePath>{file_path}));
-  EXPECT_TRUE(NavigateToURL(shell(), test_url_));
-
-  ASSERT_TRUE(CreatePromiseAndResolvers());
   // The `changedHandle` should the same as `root`, which is the same as the
-  // handle passed to `observe()`.
-  EXPECT_TRUE(
-      EvalJs(shell(),
-             "(async () => {"
-             "async function onChange(records, observer) {"
-             "  const record = records[0];"
-             "  promiseResolve(await file.isSameEntry(record.root) &&"
-             "                 await file.isSameEntry(record.changedHandle));"
-             "};"
-             "const [file] = await self.showOpenFilePicker();"
-             "const observer = new FileSystemObserver(onChange);"
-             "await observer.observe(file);"
-             "const writable = await file.createWritable();"
-             "await writable.write('blah');"
-             "await writable.close();"
-             "return await self.promise; })()")
-          .ExtractBool());
+  // handle passed to `observe()` (in this case, `file`).
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         "async function onChange(records, observer) {"
+         "  const record = records[0];"
+         "  promiseResolve(await file.isSameEntry(record.root) &&"
+         "                 await file.isSameEntry(record.changedHandle));"
+         "};"
+         START_OBSERVING_LOCAL_FILE
+         WRITE_TO_FILE
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  EXPECT_TRUE(EvalJs(shell(), script).ExtractBool());
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        ObserveFileReportsCorrectRelativePathComponents) {
   base::FilePath file_path = CreateFileToBePicked();
 
-  ASSERT_TRUE(CreatePromiseAndResolvers());
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_FILE
+         WRITE_TO_FILE
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto records = EvalJs(shell(), script).ExtractList();
+  ASSERT_THAT(records.GetList(), testing::Not(testing::IsEmpty()));
   // The `relativePathComponents` should be an empty array, since the change
   // occurred on the path corresponding to the handle passed to `observe()`.
-  EXPECT_TRUE(
-      EvalJs(shell(),
-             "(async () => {"
-             "async function onChange(records, observer) {"
-             "  const record = records[0];"
-             "  promiseResolve(record.relativePathComponents.length === 0);"
-             "};"
-             "const [file] = await self.showOpenFilePicker();"
-             "const observer = new FileSystemObserver(onChange);"
-             "await observer.observe(file);"
-             "const writable = await file.createWritable();"
-             "await writable.write('blah');"
-             "await writable.close();"
-             "return await self.promise; })()")
-          .ExtractBool());
+  EXPECT_THAT(
+      *records.GetList().front().GetDict().FindList("relativePathComponents"),
+      testing::IsEmpty());
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        ObserveDirectoryReportsCorrectHandle) {
   base::FilePath dir_path = CreateDirectoryToBePicked();
 
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  // TODO(https://crbug.com/1425601): Don't assume the type of the changed
-  // handle is the same as the type of the handle passed into observe().
-  EXPECT_TRUE(
-      EvalJs(shell(),
-             "(async () => {"
-             "async function onChange(records, observer) {"
-             "  const record = records[0];"
-             "  promiseResolve(await dir.isSameEntry(record.root) &&"
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         "async function onChange(records, observer) {"
+         "  const record = records[0];"
+         "  promiseResolve(await dir.isSameEntry(record.root) &&"
   // TODO(https://crbug.com/1425601): Some platforms do not report the modified
   // path. In these cases, `changedHandle` will always be the same as `root`.
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-             "                 await subDir.isSameEntry(record.changedHandle));"
+         "                 await subDir.isSameEntry(record.changedHandle));"
 #else
-             "                 await dir.isSameEntry(record.changedHandle));"
+         "                 await dir.isSameEntry(record.changedHandle));"
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-             "};"
-             "const dir = await self.showDirectoryPicker();"
-             "const observer = new FileSystemObserver(onChange);"
-             "await observer.observe(dir);"
-             "const subDir = await dir.getDirectoryHandle('subdir', { "
-             "create:true });"
-             "return await self.promise; })()")
-          .ExtractBool());
+         "};"
+         START_OBSERVING_LOCAL_DIRECTORY
+         "const subDir = await dir.getDirectoryHandle('sub', { create:true });"
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  EXPECT_TRUE(EvalJs(shell(), script).ExtractBool());
 }
 
 IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverBrowserTest,
                        ObserveDirectoryReportsCorrectRelativePathComponents) {
   base::FilePath dir_path = CreateDirectoryToBePicked();
 
-  ASSERT_TRUE(CreatePromiseAndResolvers());
-  EXPECT_TRUE(
-      EvalJs(shell(),
-             "(async () => {"
-             "async function onChange(records, observer) {"
-             "  const record = records[0];"
+  const std::string script =
+      // clang-format off
+      "(async () => {"
+         CREATE_PROMISE_AND_RESOLVERS
+         START_OBSERVING_LOCAL_DIRECTORY
+         "const subDir = await dir.getDirectoryHandle('sub', { create: true });"
+         SET_CHANGE_TIMEOUT
+      "})()";
+  // clang-format on
+  auto records = EvalJs(shell(), script).ExtractList();
+  ASSERT_THAT(records.GetList(), testing::Not(testing::IsEmpty()));
   // TODO(https://crbug.com/1425601): Some platforms do not report the modified
   // path. In these cases, `relativePathComponents` will always be empty.
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-             "  promiseResolve(record.relativePathComponents.length === 1);"
+  const auto relative_path_component_matcher = testing::SizeIs(1);
 #else
-             "  promiseResolve(record.relativePathComponents.length === 0);"
+  const auto relative_path_component_matcher = testing::IsEmpty();
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-             "};"
-             "const dir = await self.showDirectoryPicker();"
-             "const observer = new FileSystemObserver(onChange);"
-             "await observer.observe(dir);"
-             "const subDir = await dir.getDirectoryHandle('subdir', { "
-             "create:true });"
-             "return await self.promise; })()")
-          .ExtractBool());
+  EXPECT_THAT(
+      *records.GetList().front().GetDict().FindList("relativePathComponents"),
+      relative_path_component_matcher);
 }
 
 #endif  // !BUILDFLAG(IS_FUCHSIA)
diff --git a/content/browser/file_system_access/file_system_access_observer_host.cc b/content/browser/file_system_access/file_system_access_observer_host.cc
index ccd8696..3bcf079 100644
--- a/content/browser/file_system_access/file_system_access_observer_host.cc
+++ b/content/browser/file_system_access/file_system_access_observer_host.cc
@@ -150,14 +150,14 @@
     absl::variant<std::unique_ptr<FileSystemAccessDirectoryHandleImpl>,
                   std::unique_ptr<FileSystemAccessFileHandleImpl>> handle,
     ObserveCallback callback,
-    std::unique_ptr<FileSystemAccessWatcherManager::Observation> observation) {
+    base::expected<std::unique_ptr<FileSystemAccessWatcherManager::Observation>,
+                   blink::mojom::FileSystemAccessErrorPtr>
+        observation_or_error) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!observation) {
-    std::move(callback).Run(
-        file_system_access_error::FromStatus(
-            blink::mojom::FileSystemAccessStatus::kNotSupportedError),
-        mojo::NullReceiver());
+  if (!observation_or_error.has_value()) {
+    std::move(callback).Run(std::move(observation_or_error.error()),
+                            mojo::NullReceiver());
     return;
   }
 
@@ -167,8 +167,8 @@
 
   auto observer_observation =
       std::make_unique<FileSystemAccessObserverObservation>(
-          this, std::move(observation), std::move(observer_remote),
-          std::move(handle));
+          this, std::move(observation_or_error.value()),
+          std::move(observer_remote), std::move(handle));
   observations_.insert(std::move(observer_observation));
 
   std::move(callback).Run(file_system_access_error::Ok(),
diff --git a/content/browser/file_system_access/file_system_access_observer_host.h b/content/browser/file_system_access/file_system_access_observer_host.h
index 4851314..c0bf6ba 100644
--- a/content/browser/file_system_access/file_system_access_observer_host.h
+++ b/content/browser/file_system_access/file_system_access_observer_host.h
@@ -72,7 +72,9 @@
       absl::variant<std::unique_ptr<FileSystemAccessDirectoryHandleImpl>,
                     std::unique_ptr<FileSystemAccessFileHandleImpl>> handle,
       ObserveCallback callback,
-      std::unique_ptr<FileSystemAccessWatcherManager::Observation> observation);
+      base::expected<
+          std::unique_ptr<FileSystemAccessWatcherManager::Observation>,
+          blink::mojom::FileSystemAccessErrorPtr> observation_or_error);
 
   void OnHostReceiverDisconnect();
 
diff --git a/content/browser/file_system_access/file_system_access_watcher_manager.cc b/content/browser/file_system_access/file_system_access_watcher_manager.cc
index 74a3443d..51af152 100644
--- a/content/browser/file_system_access/file_system_access_watcher_manager.cc
+++ b/content/browser/file_system_access/file_system_access_watcher_manager.cc
@@ -17,6 +17,7 @@
 #include "build/buildflag.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "content/browser/file_system_access/file_system_access_change_source.h"
+#include "content/browser/file_system_access/file_system_access_error.h"
 #include "content/browser/file_system_access/file_system_access_manager_impl.h"
 #include "content/browser/file_system_access/file_system_access_observer_host.h"
 #include "content/browser/file_system_access/file_system_access_observer_observation.h"
@@ -24,6 +25,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "storage/browser/file_system/file_system_url.h"
 #include "storage/common/file_system/file_system_types.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-shared.h"
 
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_FUCHSIA)
 #include "content/browser/file_system_access/file_system_access_local_path_watcher.h"
@@ -202,7 +204,8 @@
 
 void FileSystemAccessWatcherManager::EnsureSourceIsInitializedForScope(
     FileSystemAccessWatchScope scope,
-    base::OnceCallback<void(bool)> on_source_initialized) {
+    base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+        on_source_initialized) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // TODO(https://crbug.com/1019297): Handle overlapping scopes and initializing
@@ -219,7 +222,9 @@
     auto owned_change_source = CreateOwnedSourceForScope(scope);
     if (!owned_change_source) {
       // TODO(https://crbug.com/1019297): Watching `scope` is not supported.
-      std::move(on_source_initialized).Run(false);
+      std::move(on_source_initialized)
+          .Run(file_system_access_error::FromStatus(
+              blink::mojom::FileSystemAccessStatus::kNotSupportedError));
       return;
     }
     raw_change_source = owned_change_source.get();
@@ -235,16 +240,20 @@
 
 void FileSystemAccessWatcherManager::DidInitializeSource(
     base::WeakPtr<FileSystemAccessChangeSource> source,
-    base::OnceCallback<void(bool)> on_source_initialized,
-    bool success) {
+    base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+        on_source_initialized,
+    blink::mojom::FileSystemAccessErrorPtr result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!source) {
-    std::move(on_source_initialized).Run(false);
+    // `source` was destroyed as we tried to initialize it. Abort.
+    std::move(on_source_initialized)
+        .Run(file_system_access_error::FromStatus(
+            blink::mojom::FileSystemAccessStatus::kOperationFailed));
     return;
   }
 
-  if (!success) {
+  if (result->status != blink::mojom::FileSystemAccessStatus::kOk) {
     // If we owned this source, remove it. A source which is not initialized
     // will not notify of changes, so there's no use keeping it around.
     //
@@ -258,17 +267,19 @@
         });
   }
 
-  std::move(on_source_initialized).Run(success);
+  std::move(on_source_initialized).Run(std::move(result));
 }
 
 void FileSystemAccessWatcherManager::PrepareObservationForScope(
     FileSystemAccessWatchScope scope,
     GetObservationCallback get_observation_callback,
-    bool success) {
+    blink::mojom::FileSystemAccessErrorPtr source_initialization_result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!success) {
-    std::move(get_observation_callback).Run(nullptr);
+  if (source_initialization_result->status !=
+      blink::mojom::FileSystemAccessStatus::kOk) {
+    std::move(get_observation_callback)
+        .Run(base::unexpected(std::move(source_initialization_result)));
     return;
   }
 
diff --git a/content/browser/file_system_access/file_system_access_watcher_manager.h b/content/browser/file_system_access/file_system_access_watcher_manager.h
index 087cb39..9732b903 100644
--- a/content/browser/file_system_access/file_system_access_watcher_manager.h
+++ b/content/browser/file_system_access/file_system_access_watcher_manager.h
@@ -14,6 +14,7 @@
 #include "base/scoped_multi_source_observation.h"
 #include "base/scoped_observation.h"
 #include "base/sequence_checker.h"
+#include "base/types/expected.h"
 #include "base/types/pass_key.h"
 #include "content/browser/file_system_access/file_system_access_change_source.h"
 #include "content/browser/file_system_access/file_system_access_watch_scope.h"
@@ -22,6 +23,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "storage/browser/file_system/file_system_context.h"
 #include "storage/browser/file_system/file_system_url.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h"
 #include "third_party/blink/public/mojom/file_system_access/file_system_access_observer_host.mojom.h"
 
 namespace content {
@@ -85,8 +87,9 @@
   };
 
   using BindingContext = FileSystemAccessEntryFactory::BindingContext;
-  using GetObservationCallback =
-      base::OnceCallback<void(std::unique_ptr<Observation>)>;
+  using GetObservationCallback = base::OnceCallback<void(
+      base::expected<std::unique_ptr<Observation>,
+                     blink::mojom::FileSystemAccessErrorPtr>)>;
 
   FileSystemAccessWatcherManager(
       FileSystemAccessManagerImpl* manager,
@@ -108,8 +111,8 @@
   // `FileSystemAccessChangeSource` if one does not already cover the scope of
   // the requested observation.
   //
-  // `get_observation_callback` returns an `Observation`, or nullptr if the
-  // given file or directory cannot be watched as requested.
+  // `get_observation_callback` returns an `Observation`, or an appropriate
+  // error if the given file or directory cannot be watched as requested.
   void GetFileObservation(const storage::FileSystemURL& file_url,
                           GetObservationCallback get_observation_callback);
   void GetDirectoryObservation(const storage::FileSystemURL& directory_url,
@@ -153,15 +156,21 @@
   // Attempts to create a change source for `scope` if it does not exist.
   void EnsureSourceIsInitializedForScope(
       FileSystemAccessWatchScope scope,
-      base::OnceCallback<void(bool)> on_source_initialized);
-  void DidInitializeSource(base::WeakPtr<FileSystemAccessChangeSource> source,
-                           base::OnceCallback<void(bool)> on_source_initialized,
-                           bool success);
+      base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+          on_source_initialized);
+  void DidInitializeSource(
+      base::WeakPtr<FileSystemAccessChangeSource> source,
+      base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+          on_source_initialized,
+      blink::mojom::FileSystemAccessErrorPtr result);
 
-  void PrepareObservationForScope(FileSystemAccessWatchScope scope,
-                                  GetObservationCallback callback,
-                                  bool success);
+  void PrepareObservationForScope(
+      FileSystemAccessWatchScope scope,
+      GetObservationCallback callback,
+      blink::mojom::FileSystemAccessErrorPtr source_initialization_result);
 
+  // Creates and returns a new (uninitialized) change source for the given
+  // scope, or nullptr if watching this scope is not supported.
   std::unique_ptr<FileSystemAccessChangeSource> CreateOwnedSourceForScope(
       FileSystemAccessWatchScope scope);
 
diff --git a/content/browser/file_system_access/file_system_access_watcher_manager_unittest.cc b/content/browser/file_system_access/file_system_access_watcher_manager_unittest.cc
index ca4fc850..ec6e442b 100644
--- a/content/browser/file_system_access/file_system_access_watcher_manager_unittest.cc
+++ b/content/browser/file_system_access/file_system_access_watcher_manager_unittest.cc
@@ -32,6 +32,7 @@
 #include "storage/browser/test/test_file_system_context.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-shared.h"
 
 namespace content {
 
@@ -110,9 +111,11 @@
   ~FakeChangeSource() override = default;
 
   // FileSystemAccessChangeSource:
-  void Initialize(base::OnceCallback<void(bool)> on_initialized) override {
+  void Initialize(
+      base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr)>
+          on_initialized) override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    std::move(on_initialized).Run(initialization_result_);
+    std::move(on_initialized).Run(initialization_result_->Clone());
   }
 
   void Signal(base::FilePath relative_path, bool error) {
@@ -120,13 +123,19 @@
     NotifyOfChange(std::move(relative_path), error);
   }
 
-  void set_initialization_result(bool result) {
+  void set_initialization_result(
+      blink::mojom::FileSystemAccessErrorPtr result) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    initialization_result_ = result;
+    initialization_result_ = std::move(result);
   }
 
  private:
-  bool initialization_result_ GUARDED_BY_CONTEXT(sequence_checker_) = true;
+  blink::mojom::FileSystemAccessErrorPtr initialization_result_
+      GUARDED_BY_CONTEXT(sequence_checker_) =
+          blink::mojom::FileSystemAccessError::New(
+              blink::mojom::FileSystemAccessStatus::kOk,
+              base::File::FILE_OK,
+              "");
 };
 
 }  // namespace
@@ -197,15 +206,18 @@
   EXPECT_FALSE(watcher_manager().HasSourcesForTesting());
 
   {
-    base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+    base::test::TestFuture<base::expected<
+        std::unique_ptr<Observation>, blink::mojom::FileSystemAccessErrorPtr>>
+        get_observation_future;
     watcher_manager().GetDirectoryObservation(
         dir_url,
         /*is_recursive=*/false, get_observation_future.GetCallback());
-    ASSERT_TRUE(get_observation_future.Get());
+    ASSERT_TRUE(get_observation_future.Get().has_value());
 
     // An observation should have been created.
     auto observation = get_observation_future.Take();
-    EXPECT_TRUE(watcher_manager().HasObservationForTesting(observation.get()));
+    EXPECT_TRUE(
+        watcher_manager().HasObservationForTesting(observation.value().get()));
 
     // A source should have been created to cover the scope of the observation.
     EXPECT_TRUE(watcher_manager().HasSourcesForTesting());
@@ -245,12 +257,14 @@
   EXPECT_TRUE(watcher_manager().HasSourceForTesting(&source));
 
   // Attempting to observe a scope covered by `source` will use `source`.
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetFileObservation(file_url,
                                        get_observation_future.GetCallback());
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
 
@@ -273,13 +287,19 @@
   watcher_manager().RegisterSource(&source);
   EXPECT_TRUE(watcher_manager().HasSourceForTesting(&source));
 
-  source.set_initialization_result(false);
+  source.set_initialization_result(blink::mojom::FileSystemAccessError::New(
+      blink::mojom::FileSystemAccessStatus::kOperationFailed,
+      base::File::FILE_OK, ""));
 
   // Attempting to observe a scope covered by `source` will use `source`.
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetFileObservation(file_url,
                                        get_observation_future.GetCallback());
-  EXPECT_FALSE(get_observation_future.Get());
+  ASSERT_FALSE(get_observation_future.Get().has_value());
+  EXPECT_EQ(get_observation_future.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kOperationFailed);
 
   // TODO(https://crbug.com/1019297): Determine what should happen on failure to
   // initialize a source, then add better test coverage.
@@ -296,13 +316,15 @@
   EXPECT_TRUE(watcher_manager().HasSourceForTesting(&source));
 
   // Attempting to observe a scope covered by `source` will use `source`.
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetFileObservation(file_url,
                                        get_observation_future.GetCallback());
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
   {
-    ChangeAccumulator accumulator(get_observation_future.Take());
+    ChangeAccumulator accumulator(get_observation_future.Take().value());
     EXPECT_TRUE(
         watcher_manager().HasObservationForTesting(accumulator.observation()));
 
@@ -326,10 +348,14 @@
       GURL("filesystem:http://chromium.org/temporary/i/has/a.bucket"));
 
   // Attempting to observe the given file will fail.
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetFileObservation(temporary_url,
                                        get_observation_future.GetCallback());
-  EXPECT_FALSE(get_observation_future.Get());
+  ASSERT_FALSE(get_observation_future.Get().has_value());
+  EXPECT_EQ(get_observation_future.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
 }
 
 // TODO(https://crbug.com/1019297): Add tests covering more edge cases regarding
@@ -354,12 +380,14 @@
   watcher_manager().RegisterSource(&source_for_dir);
   EXPECT_TRUE(watcher_manager().HasSourceForTesting(&source_for_dir));
 
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetFileObservation(file_url,
                                        get_observation_future.GetCallback());
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
 
@@ -391,23 +419,26 @@
   watcher_manager().RegisterSource(&source);
   EXPECT_TRUE(watcher_manager().HasSourceForTesting(&source));
 
-  base::test::TestFuture<std::unique_ptr<Observation>>
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
       get_dir_observation_future;
   watcher_manager().GetDirectoryObservation(
       dir_url, /*is_recursive=*/true, get_dir_observation_future.GetCallback());
-  EXPECT_TRUE(get_dir_observation_future.Get());
+  EXPECT_TRUE(get_dir_observation_future.Get().has_value());
 
-  ChangeAccumulator dir_accumulator(get_dir_observation_future.Take());
+  ChangeAccumulator dir_accumulator(get_dir_observation_future.Take().value());
   EXPECT_TRUE(watcher_manager().HasObservationForTesting(
       dir_accumulator.observation()));
 
-  base::test::TestFuture<std::unique_ptr<Observation>>
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
       get_file_observation_future;
   watcher_manager().GetFileObservation(
       file_url, get_file_observation_future.GetCallback());
-  EXPECT_TRUE(get_file_observation_future.Get());
+  EXPECT_TRUE(get_file_observation_future.Get().has_value());
 
-  ChangeAccumulator file_accumulator(get_file_observation_future.Take());
+  ChangeAccumulator file_accumulator(
+      get_file_observation_future.Take().value());
   EXPECT_TRUE(watcher_manager().HasObservationForTesting(
       file_accumulator.observation()));
 
@@ -438,12 +469,14 @@
   EXPECT_TRUE(watcher_manager().HasSourceForTesting(&source));
 
   // Attempting to observe a scope covered by `source` will use `source`.
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetFileObservation(file_url,
                                        get_observation_future.GetCallback());
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
 
@@ -467,12 +500,14 @@
   EXPECT_TRUE(watcher_manager().HasSourceForTesting(&source));
 
   // Attempting to observe a scope covered by `source` will use `source`.
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetDirectoryObservation(
       dir_url, /*is_recursive=*/true, get_observation_future.GetCallback());
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
 
@@ -503,17 +538,21 @@
   auto file_path = dir_path.AppendASCII("foo");
   base::WriteFile(file_path, "watch me");
 
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetDirectoryObservation(
       dir_url,
       /*is_recursive=*/false, get_observation_future.GetCallback());
 // Watching the local file system is not supported on Android or Fuchsia.
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
-  EXPECT_FALSE(get_observation_future.Get());
+  ASSERT_FALSE(get_observation_future.Get().has_value());
+  EXPECT_EQ(get_observation_future.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
 #else
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
   // Constructing an observation registers it with the manager.
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
 
@@ -545,17 +584,21 @@
   auto file_path = dir_path.AppendASCII("subdir").AppendASCII("foo");
   base::WriteFile(file_path, "watch me");
 
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetDirectoryObservation(
       dir_url,
       /*is_recursive=*/false, get_observation_future.GetCallback());
   // Watching the local file system is not supported on Android or Fuchsia.
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
-  EXPECT_FALSE(get_observation_future.Get());
+  ASSERT_FALSE(get_observation_future.Get().has_value());
+  EXPECT_EQ(get_observation_future.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
 #else
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
   EXPECT_TRUE(watcher_manager().HasSourcesForTesting());
@@ -582,18 +625,22 @@
   auto file_path = dir_path.AppendASCII("subdir").AppendASCII("foo");
   base::WriteFile(file_path, "watch me");
 
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetDirectoryObservation(
       dir_url,
       /*is_recursive=*/true, get_observation_future.GetCallback());
   // Watching the local file system is not supported on Android or Fuchsia.
   // Recursive watching of the local file system is not supported on iOS.
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_IOS)
-  EXPECT_FALSE(get_observation_future.Get());
+  ASSERT_FALSE(get_observation_future.Get().has_value());
+  EXPECT_EQ(get_observation_future.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
 #else
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
   EXPECT_TRUE(watcher_manager().HasSourcesForTesting());
@@ -626,16 +673,20 @@
   // Create the file to be watched.
   base::WriteFile(file_path, "watch me");
 
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetFileObservation(file_url,
                                        get_observation_future.GetCallback());
   // Watching the local file system is not supported on Android or Fuchsia.
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
-  EXPECT_FALSE(get_observation_future.Get());
+  ASSERT_FALSE(get_observation_future.Get().has_value());
+  EXPECT_EQ(get_observation_future.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
 #else
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
 
@@ -659,8 +710,9 @@
   // Create the file to be watched.
   base::WriteFile(file_path, "watch me");
 
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future1,
-      get_observation_future2, get_observation_future3;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future1, get_observation_future2, get_observation_future3;
   watcher_manager().GetFileObservation(file_url,
                                        get_observation_future1.GetCallback());
   watcher_manager().GetFileObservation(file_url,
@@ -669,17 +721,23 @@
                                        get_observation_future3.GetCallback());
   // Watching the local file system is not supported on Android or Fuchsia.
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
-  EXPECT_FALSE(get_observation_future1.Get());
-  EXPECT_FALSE(get_observation_future2.Get());
-  EXPECT_FALSE(get_observation_future3.Get());
+  ASSERT_FALSE(get_observation_future1.Get().has_value());
+  ASSERT_FALSE(get_observation_future2.Get().has_value());
+  ASSERT_FALSE(get_observation_future3.Get().has_value());
+  EXPECT_EQ(get_observation_future1.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
+  EXPECT_EQ(get_observation_future2.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
+  EXPECT_EQ(get_observation_future3.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
 #else
-  ASSERT_TRUE(get_observation_future1.Get());
-  ASSERT_TRUE(get_observation_future2.Get());
-  ASSERT_TRUE(get_observation_future3.Get());
+  ASSERT_TRUE(get_observation_future1.Get().has_value());
+  ASSERT_TRUE(get_observation_future2.Get().has_value());
+  ASSERT_TRUE(get_observation_future3.Get().has_value());
 
-  ChangeAccumulator accumulator1(get_observation_future1.Take());
-  ChangeAccumulator accumulator2(get_observation_future2.Take());
-  ChangeAccumulator accumulator3(get_observation_future3.Take());
+  ChangeAccumulator accumulator1(get_observation_future1.Take().value());
+  ChangeAccumulator accumulator2(get_observation_future2.Take().value());
+  ChangeAccumulator accumulator3(get_observation_future3.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator1.observation()));
   EXPECT_TRUE(
@@ -705,16 +763,20 @@
   auto file_url = manager_->CreateFileSystemURLFromPath(
       FileSystemAccessEntryFactory::PathType::kLocal, file_path);
 
-  base::test::TestFuture<std::unique_ptr<Observation>> get_observation_future;
+  base::test::TestFuture<base::expected<std::unique_ptr<Observation>,
+                                        blink::mojom::FileSystemAccessErrorPtr>>
+      get_observation_future;
   watcher_manager().GetFileObservation(file_url,
                                        get_observation_future.GetCallback());
   // Watching the local file system is not supported on Android or Fuchsia.
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
-  EXPECT_FALSE(get_observation_future.Get());
+  ASSERT_FALSE(get_observation_future.Get().has_value());
+  EXPECT_EQ(get_observation_future.Get().error()->status,
+            blink::mojom::FileSystemAccessStatus::kNotSupportedError);
 #else
-  ASSERT_TRUE(get_observation_future.Get());
+  ASSERT_TRUE(get_observation_future.Get().has_value());
 
-  ChangeAccumulator accumulator(get_observation_future.Take());
+  ChangeAccumulator accumulator(get_observation_future.Take().value());
   EXPECT_TRUE(
       watcher_manager().HasObservationForTesting(accumulator.observation()));
 
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
index a22118f..5c12e79d 100644
--- a/content/browser/indexed_db/database_impl.cc
+++ b/content/browser/indexed_db/database_impl.cc
@@ -16,7 +16,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/indexed_db/indexed_db_callback_helpers.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
-#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
 #include "content/browser/indexed_db/transaction_impl.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
@@ -44,20 +43,16 @@
 
 // static
 mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase>
-DatabaseImpl::CreateAndBind(std::unique_ptr<IndexedDBConnection> connection,
-                            IndexedDBDispatcherHost* dispatcher_host) {
+DatabaseImpl::CreateAndBind(std::unique_ptr<IndexedDBConnection> connection) {
   mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_remote;
   mojo::MakeSelfOwnedAssociatedReceiver(
-      base::WrapUnique(
-          new DatabaseImpl(std::move(connection), dispatcher_host)),
+      base::WrapUnique(new DatabaseImpl(std::move(connection))),
       pending_remote.InitWithNewEndpointAndPassReceiver());
   return pending_remote;
 }
 
-DatabaseImpl::DatabaseImpl(std::unique_ptr<IndexedDBConnection> connection,
-                           IndexedDBDispatcherHost* dispatcher_host)
-    : dispatcher_host_(dispatcher_host),
-      connection_(std::move(connection)) {
+DatabaseImpl::DatabaseImpl(std::unique_ptr<IndexedDBConnection> connection)
+    : connection_(std::move(connection)) {
   DCHECK(connection_);
 }
 
@@ -209,8 +204,7 @@
 
   transaction->ScheduleTask(BindWeakOperation(
       &IndexedDBDatabase::GetOperation, connection_->database()->AsWeakPtr(),
-      dispatcher_host_->AsWeakPtr(), object_store_id, index_id,
-      std::make_unique<IndexedDBKeyRange>(key_range),
+      object_store_id, index_id, std::make_unique<IndexedDBKeyRange>(key_range),
       key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
       std::move(aborting_callback)));
 }
@@ -274,8 +268,7 @@
 
   transaction->ScheduleTask(BindWeakOperation(
       &IndexedDBDatabase::GetAllOperation, connection_->database()->AsWeakPtr(),
-      dispatcher_host_->AsWeakPtr(), object_store_id, index_id,
-      std::make_unique<IndexedDBKeyRange>(key_range),
+      object_store_id, index_id, std::make_unique<IndexedDBKeyRange>(key_range),
       key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
       max_count, std::move(aborting_callback)));
 }
@@ -422,7 +415,7 @@
   transaction->ScheduleTask(
       BindWeakOperation(&IndexedDBDatabase::OpenCursorOperation,
                         connection_->database()->AsWeakPtr(), std::move(params),
-                        GetBucketLocator(), dispatcher_host_->AsWeakPtr()));
+                        GetBucketLocator()));
 }
 
 void DatabaseImpl::Count(int64_t transaction_id,
diff --git a/content/browser/indexed_db/database_impl.h b/content/browser/indexed_db/database_impl.h
index 5c6ba5e..e8b1fd2d 100644
--- a/content/browser/indexed_db/database_impl.h
+++ b/content/browser/indexed_db/database_impl.h
@@ -27,19 +27,16 @@
 
 namespace content {
 class IndexedDBConnection;
-class IndexedDBDispatcherHost;
 
 class DatabaseImpl : public blink::mojom::IDBDatabase {
  public:
   static mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> CreateAndBind(
-      std::unique_ptr<IndexedDBConnection> connection,
-      IndexedDBDispatcherHost* dispatcher_host);
+      std::unique_ptr<IndexedDBConnection> connection);
 
   ~DatabaseImpl() override;
 
  private:
-  DatabaseImpl(std::unique_ptr<IndexedDBConnection> connection,
-               IndexedDBDispatcherHost* dispatcher_host);
+  explicit DatabaseImpl(std::unique_ptr<IndexedDBConnection> connection);
 
   DatabaseImpl(const DatabaseImpl&) = delete;
   DatabaseImpl& operator=(const DatabaseImpl&) = delete;
@@ -125,9 +122,6 @@
   const storage::BucketInfo& GetBucketInfo();
   storage::BucketLocator GetBucketLocator();
 
-  // This raw pointer is safe because all DatabaseImpl instances are owned by
-  // an IndexedDBDispatcherHost.
-  raw_ptr<IndexedDBDispatcherHost> dispatcher_host_;
   std::unique_ptr<IndexedDBConnection> connection_;
 
   SEQUENCE_CHECKER(sequence_checker_);
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc
index 018a6c0c..fd153c85 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -39,13 +39,15 @@
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_iterator.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction.h"
 #include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
+#include "components/services/storage/public/mojom/file_system_access_context.mojom.h"
 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
+#include "content/browser/indexed_db/indexed_db_bucket_context.h"
+#include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_data_format_version.h"
 #include "content/browser/indexed_db/indexed_db_database_error.h"
 #include "content/browser/indexed_db/indexed_db_external_object.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
 #include "content/browser/indexed_db/indexed_db_reporting.h"
 #include "content/browser/indexed_db/indexed_db_value.h"
@@ -939,23 +941,17 @@
 
 IndexedDBBackingStore::IndexedDBBackingStore(
     Mode backing_store_mode,
-    TransactionalLevelDBFactory* transactional_leveldb_factory,
     const storage::BucketLocator& bucket_locator,
     const base::FilePath& blob_path,
     std::unique_ptr<TransactionalLevelDBDatabase> db,
-    storage::mojom::BlobStorageContext* blob_storage_context,
-    storage::mojom::FileSystemAccessContext* file_system_access_context,
     std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
     BlobFilesCleanedCallback blob_files_cleaned,
     ReportOutstandingBlobsCallback report_outstanding_blobs,
     scoped_refptr<base::SequencedTaskRunner> idb_task_runner)
     : backing_store_mode_(backing_store_mode),
-      transactional_leveldb_factory_(transactional_leveldb_factory),
       bucket_locator_(bucket_locator),
       blob_path_(backing_store_mode == Mode::kInMemory ? base::FilePath()
                                                        : blob_path),
-      blob_storage_context_(blob_storage_context),
-      file_system_access_context_(file_system_access_context),
       filesystem_proxy_(std::move(filesystem_proxy)),
       origin_identifier_(ComputeOriginIdentifier(bucket_locator)),
       idb_task_runner_(std::move(idb_task_runner)),
@@ -1449,7 +1445,9 @@
     blink::IndexedDBDatabaseMetadata& metadata) {
   // TODO(jsbell): Don't persist metadata if open fails. http://crbug.com/395472
   std::unique_ptr<LevelDBDirectTransaction> transaction =
-      db_->class_factory()->CreateLevelDBDirectTransaction(db_.get());
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBDirectTransaction(db_.get());
 
   int64_t row_id = 0;
   Status s = indexed_db::GetNewDatabaseId(transaction.get(), &row_id);
@@ -2305,7 +2303,9 @@
   bool all_blobs = blob_number == DatabaseMetaDataKey::kAllBlobsNumber;
   DCHECK(all_blobs || DatabaseMetaDataKey::IsValidBlobNumber(blob_number));
   std::unique_ptr<LevelDBDirectTransaction> transaction =
-      transactional_leveldb_factory_->CreateLevelDBDirectTransaction(db_.get());
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBDirectTransaction(db_.get());
 
   BlobJournalType active_blob_journal, recovery_journal;
   if (!GetActiveBlobJournal(transaction.get(), &active_blob_journal).ok())
@@ -2437,7 +2437,9 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!committing_transaction_count_);
   std::unique_ptr<LevelDBDirectTransaction> journal_transaction =
-      transactional_leveldb_factory_->CreateLevelDBDirectTransaction(db_.get());
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBDirectTransaction(db_.get());
   BlobJournalType journal;
 
   Status s = GetBlobJournal(level_db_key, journal_transaction.get(), &journal);
@@ -3834,9 +3836,6 @@
     blink::mojom::IDBTransactionDurability durability,
     blink::mojom::IDBTransactionMode mode)
     : backing_store_(std::move(backing_store)),
-      transactional_leveldb_factory_(
-          backing_store_ ? backing_store_->transactional_leveldb_factory_.get()
-                         : nullptr),
       durability_(durability),
       mode_(mode) {
   // `Default` should have already been converted to the bucket's setting.
@@ -3858,10 +3857,13 @@
   DCHECK(!transaction_.get());
   TRACE_EVENT0("IndexedDB", "IndexedDBBackingStore::Transaction::Begin");
 
-  transaction_ = transactional_leveldb_factory_->CreateLevelDBTransaction(
-      backing_store_->db_.get(),
-      backing_store_->db_->scopes()->CreateScope(
-          std::move(locks), std::vector<LevelDBScopes::EmptyRange>()));
+  transaction_ =
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBTransaction(
+              backing_store_->db_.get(),
+              backing_store_->db_->scopes()->CreateScope(
+                  std::move(locks), std::vector<LevelDBScopes::EmptyRange>()));
 
   // If incognito, this snapshots blobs just as the above transaction_
   // constructor snapshots the leveldb.
@@ -4017,8 +4019,9 @@
     return Status::OK();
 
   std::unique_ptr<LevelDBDirectTransaction> direct_txn =
-      transactional_leveldb_factory_->CreateLevelDBDirectTransaction(
-          backing_store_->db_.get());
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBDirectTransaction(backing_store_->db_.get());
 
   int64_t next_blob_number = -1;
   bool result = indexed_db::GetBlobNumberGeneratorCurrentNumber(
@@ -4219,8 +4222,9 @@
     // Read the persisted states of the recovery/live blob journals,
     // so that they can be updated correctly by the transaction.
     std::unique_ptr<LevelDBDirectTransaction> journal_transaction =
-        transactional_leveldb_factory_->CreateLevelDBDirectTransaction(
-            backing_store_->db_.get());
+        IndexedDBClassFactory::Get()
+            ->transactional_leveldb_factory()
+            .CreateLevelDBDirectTransaction(backing_store_->db_.get());
     s = GetRecoveryBlobJournal(journal_transaction.get(), &recovery_journal);
     if (!s.ok())
       return s;
@@ -4295,8 +4299,9 @@
   }
 
   std::unique_ptr<LevelDBDirectTransaction> update_journal_transaction =
-      transactional_leveldb_factory_->CreateLevelDBDirectTransaction(
-          backing_store_->db_.get());
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBDirectTransaction(backing_store_->db_.get());
   UpdateRecoveryBlobJournal(update_journal_transaction.get(),
                             saved_recovery_journal);
   s = update_journal_transaction->Commit();
@@ -4343,9 +4348,6 @@
 
   write_state_.emplace(num_objects_to_write, std::move(callback));
 
-  storage::mojom::BlobStorageContext* blob_storage_context =
-      backing_store_->blob_storage_context_;
-
   auto write_result_callback = base::BindRepeating(
       [](base::WeakPtr<Transaction> transaction,
          storage::mojom::WriteBlobToFileResult result) {
@@ -4407,12 +4409,13 @@
                               ? absl::nullopt
                               : absl::make_optional(entry.last_modified());
 #endif
-          blob_storage_context->WriteBlobToFile(
-              std::move(pending_blob),
-              backing_store_->GetBlobFileName(database_id_,
-                                              entry.blob_number()),
-              IndexedDBBackingStore::ShouldSyncOnCommit(durability_),
-              last_modified, write_result_callback);
+          backing_store_->bucket_context_->blob_storage_context()
+              ->WriteBlobToFile(
+                  std::move(pending_blob),
+                  backing_store_->GetBlobFileName(database_id_,
+                                                  entry.blob_number()),
+                  IndexedDBBackingStore::ShouldSyncOnCommit(durability_),
+                  last_modified, write_result_callback);
           break;
         }
         case IndexedDBExternalObject::ObjectType::kFileSystemAccessHandle: {
@@ -4427,31 +4430,34 @@
           entry.file_system_access_token_remote()->Clone(
               token_clone.InitWithNewPipeAndPassReceiver());
 
-          backing_store_->file_system_access_context_->SerializeHandle(
-              std::move(token_clone),
-              base::BindOnce(
-                  [](base::WeakPtr<Transaction> transaction,
-                     IndexedDBExternalObject* object,
-                     base::OnceCallback<void(
-                         storage::mojom::WriteBlobToFileResult)> callback,
-                     const std::vector<uint8_t>& serialized_token) {
-                    // `object` is owned by `transaction`, so make sure
-                    // `transaction` is still valid before doing anything else.
-                    if (!transaction)
-                      return;
-                    if (serialized_token.empty()) {
-                      std::move(callback).Run(
-                          storage::mojom::WriteBlobToFileResult::kError);
-                      return;
-                    }
-                    object->set_serialized_file_system_access_handle(
-                        serialized_token);
-                    std::move(callback).Run(
-                        storage::mojom::WriteBlobToFileResult::kSuccess);
-                  },
-                  weak_ptr_factory_.GetWeakPtr(),
-                  base::UnsafeDanglingUntriaged(&entry),
-                  write_result_callback));
+          backing_store_->bucket_context_->file_system_access_context()
+              ->SerializeHandle(
+                  std::move(token_clone),
+                  base::BindOnce(
+                      [](base::WeakPtr<Transaction> transaction,
+                         IndexedDBExternalObject* object,
+                         base::OnceCallback<void(
+                             storage::mojom::WriteBlobToFileResult)> callback,
+                         const std::vector<uint8_t>& serialized_token) {
+                        // `object` is owned by `transaction`, so make sure
+                        // `transaction` is still valid before doing anything
+                        // else.
+                        if (!transaction) {
+                          return;
+                        }
+                        if (serialized_token.empty()) {
+                          std::move(callback).Run(
+                              storage::mojom::WriteBlobToFileResult::kError);
+                          return;
+                        }
+                        object->set_serialized_file_system_access_handle(
+                            serialized_token);
+                        std::move(callback).Run(
+                            storage::mojom::WriteBlobToFileResult::kSuccess);
+                      },
+                      weak_ptr_factory_.GetWeakPtr(),
+                      base::UnsafeDanglingUntriaged(&entry),
+                      write_result_callback));
           break;
         }
       }
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h
index 17a8883..9b382f1 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -29,8 +29,6 @@
 #include "components/services/storage/indexed_db/locks/partitioned_lock.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h"
-#include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h"
-#include "components/services/storage/public/mojom/file_system_access_context.mojom-forward.h"
 #include "content/browser/indexed_db/indexed_db.h"
 #include "content/browser/indexed_db/indexed_db_external_object.h"
 #include "content/browser/indexed_db/indexed_db_external_object_storage.h"
@@ -59,7 +57,6 @@
 class IndexedDBActiveBlobRegistry;
 class LevelDBWriteBatch;
 class TransactionalLevelDBDatabase;
-class TransactionalLevelDBFactory;
 class TransactionalLevelDBIterator;
 class TransactionalLevelDBTransaction;
 struct IndexedDBValue;
@@ -213,8 +210,6 @@
     base::WeakPtr<IndexedDBBackingStore> backing_store_
         GUARDED_BY_CONTEXT(sequence_checker_);
 
-    const raw_ptr<TransactionalLevelDBFactory> transactional_leveldb_factory_;
-
     scoped_refptr<TransactionalLevelDBTransaction> transaction_
         GUARDED_BY_CONTEXT(sequence_checker_);
 
@@ -387,12 +382,9 @@
 
   IndexedDBBackingStore(
       Mode backing_store_mode,
-      TransactionalLevelDBFactory* transactional_leveldb_factory,
       const storage::BucketLocator& bucket_locator,
       const base::FilePath& blob_path,
       std::unique_ptr<TransactionalLevelDBDatabase> db,
-      storage::mojom::BlobStorageContext* blob_storage_context,
-      storage::mojom::FileSystemAccessContext* file_system_access_context,
       std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
       BlobFilesCleanedCallback blob_files_cleaned,
       ReportOutstandingBlobsCallback report_outstanding_blobs,
@@ -662,6 +654,10 @@
  protected:
   friend class IndexedDBBucketContext;
 
+  void set_bucket_context(IndexedDBBucketContext* bucket_context) {
+    bucket_context_ = bucket_context;
+  }
+
   leveldb::Status AnyDatabaseContainsBlobs(bool* blobs_exist);
 
   // A helper function for V4 schema migration.
@@ -730,20 +726,13 @@
   // Can run a journal cleaning job if one is pending.
   void DidCommitTransaction();
 
+  // Owns `this`. Should be initialized shortly after construction.
+  raw_ptr<IndexedDBBucketContext> bucket_context_ = nullptr;
+
   const Mode backing_store_mode_;
-  const raw_ptr<TransactionalLevelDBFactory> transactional_leveldb_factory_;
   const storage::BucketLocator bucket_locator_;
   const base::FilePath blob_path_;
 
-  // IndexedDB can store blobs and File System Access handles. These mojo
-  // interfaces are used to make this possible by communicating with the
-  // relevant subsystems.
-  // Raw pointers are safe because the bindings are owned by
-  // IndexedDBContextImpl.
-  const raw_ptr<storage::mojom::BlobStorageContext> blob_storage_context_;
-  const raw_ptr<storage::mojom::FileSystemAccessContext>
-      file_system_access_context_;
-
   // Filesystem proxy to use for file operations.  nullptr if in memory.
   const std::unique_ptr<storage::FilesystemProxy> filesystem_proxy_;
 
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
index cd90e918..220ceb1 100644
--- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -74,23 +74,17 @@
  public:
   TestableIndexedDBBackingStore(
       IndexedDBBackingStore::Mode backing_store_mode,
-      TransactionalLevelDBFactory* leveldb_factory,
       const storage::BucketLocator& bucket_locator,
       const base::FilePath& blob_path,
       std::unique_ptr<TransactionalLevelDBDatabase> db,
-      storage::mojom::BlobStorageContext* blob_storage_context,
-      storage::mojom::FileSystemAccessContext* file_system_access_context,
       std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
       BlobFilesCleanedCallback blob_files_cleaned,
       ReportOutstandingBlobsCallback report_outstanding_blobs,
       scoped_refptr<base::SequencedTaskRunner> idb_task_runner)
       : IndexedDBBackingStore(backing_store_mode,
-                              leveldb_factory,
                               bucket_locator,
                               blob_path,
                               std::move(db),
-                              blob_storage_context,
-                              file_system_access_context,
                               std::move(filesystem_proxy),
                               std::move(blob_files_cleaned),
                               std::move(report_outstanding_blobs),
@@ -125,15 +119,9 @@
 // TestableIndexedDBBackingStore subclass.
 class TestIDBFactory : public IndexedDBFactory {
  public:
-  explicit TestIDBFactory(
-      IndexedDBContextImpl* idb_context,
-      storage::mojom::BlobStorageContext* blob_storage_context,
-      storage::mojom::FileSystemAccessContext* file_system_access_context)
+  explicit TestIDBFactory(IndexedDBContextImpl* idb_context)
       : IndexedDBFactory(idb_context,
-                         IndexedDBClassFactory::Get(),
-                         base::DefaultClock::GetInstance()),
-        blob_storage_context_(blob_storage_context),
-        file_system_access_context_(file_system_access_context) {}
+                         base::DefaultClock::GetInstance()) {}
 
   TestIDBFactory(const TestIDBFactory&) = delete;
   TestIDBFactory& operator=(const TestIDBFactory&) = delete;
@@ -143,12 +131,9 @@
  protected:
   std::unique_ptr<IndexedDBBackingStore> CreateBackingStore(
       IndexedDBBackingStore::Mode backing_store_mode,
-      TransactionalLevelDBFactory* leveldb_factory,
       const storage::BucketLocator& bucket_locator,
       const base::FilePath& blob_path,
       std::unique_ptr<TransactionalLevelDBDatabase> db,
-      storage::mojom::BlobStorageContext*,
-      storage::mojom::FileSystemAccessContext*,
       std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
       IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned,
       IndexedDBBackingStore::ReportOutstandingBlobsCallback
@@ -158,15 +143,10 @@
     // than the versions that were passed in to this method. This way tests can
     // use a different context from what is stored in the IndexedDBContext.
     return std::make_unique<TestableIndexedDBBackingStore>(
-        backing_store_mode, leveldb_factory, bucket_locator, blob_path,
-        std::move(db), blob_storage_context_, file_system_access_context_,
+        backing_store_mode, bucket_locator, blob_path, std::move(db),
         std::move(filesystem_proxy), std::move(blob_files_cleaned),
         std::move(report_outstanding_blobs), std::move(idb_task_runner));
   }
-
- private:
-  raw_ptr<storage::mojom::BlobStorageContext> blob_storage_context_;
-  raw_ptr<storage::mojom::FileSystemAccessContext> file_system_access_context_;
 };
 
 struct BlobWrite {
@@ -221,6 +201,10 @@
         base::BindOnce(std::move(callback),
                        storage::mojom::WriteBlobToFileResult::kSuccess));
   }
+  void Clone(mojo::PendingReceiver<::storage::mojom::BlobStorageContext>
+                 receiver) override {
+    receivers_.Add(this, std::move(receiver));
+  }
 
   const std::vector<BlobWrite>& writes() { return writes_; }
   void ClearWrites() { writes_.clear(); }
@@ -232,6 +216,7 @@
  private:
   std::vector<BlobWrite> writes_;
   bool write_files_to_disk_ = false;
+  mojo::ReceiverSet<::storage::mojom::BlobStorageContext> receivers_;
 };
 
 class FakeFileSystemAccessTransferToken
@@ -280,6 +265,11 @@
     NOTREACHED();
   }
 
+  void Clone(mojo::PendingReceiver<::storage::mojom::FileSystemAccessContext>
+                 receiver) override {
+    receivers_.Add(this, std::move(receiver));
+  }
+
   const std::vector<
       mojo::Remote<::blink::mojom::FileSystemAccessTransferToken>>&
   writes() {
@@ -290,6 +280,7 @@
  private:
   std::vector<mojo::Remote<::blink::mojom::FileSystemAccessTransferToken>>
       writes_;
+  mojo::ReceiverSet<::storage::mojom::FileSystemAccessContext> receivers_;
 };
 
 class IndexedDBBackingStoreTest : public testing::Test {
@@ -313,12 +304,18 @@
         quota_manager_.get(),
         base::SingleThreadTaskRunner::GetCurrentDefault());
 
+    mojo::PendingRemote<storage::mojom::BlobStorageContext>
+        blob_storage_context;
+    blob_context_->Clone(blob_storage_context.InitWithNewPipeAndPassReceiver());
+
+    mojo::PendingRemote<storage::mojom::FileSystemAccessContext> fsa_context;
+    file_system_access_context_->Clone(
+        fsa_context.InitWithNewPipeAndPassReceiver());
+
     idb_context_ = base::MakeRefCounted<IndexedDBContextImpl>(
         temp_dir_.GetPath(), quota_manager_proxy_,
-        base::DefaultClock::GetInstance(),
-        /*blob_storage_context=*/mojo::NullRemote(),
-        /*file_system_access_context=*/mojo::NullRemote(),
-        base::SequencedTaskRunner::GetCurrentDefault(),
+        base::DefaultClock::GetInstance(), std::move(blob_storage_context),
+        std::move(fsa_context), base::SequencedTaskRunner::GetCurrentDefault(),
         base::SequencedTaskRunner::GetCurrentDefault());
 
     // Needed to get the QuotaClient bound.
@@ -348,9 +345,7 @@
     bucket_info.name = storage::kDefaultBucketName;
     auto bucket_locator = bucket_info.ToBucketLocator();
 
-    idb_factory_ = std::make_unique<TestIDBFactory>(
-        idb_context_.get(), blob_context_.get(),
-        file_system_access_context_.get());
+    idb_factory_ = std::make_unique<TestIDBFactory>(idb_context_.get());
 
     leveldb::Status s;
     std::tie(bucket_context_handle_, s, std::ignore, data_loss_info_,
diff --git a/content/browser/indexed_db/indexed_db_bucket_context.cc b/content/browser/indexed_db/indexed_db_bucket_context.cc
index 7463016..8a1ad7e 100644
--- a/content/browser/indexed_db/indexed_db_bucket_context.cc
+++ b/content/browser/indexed_db/indexed_db_bucket_context.cc
@@ -14,10 +14,17 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/rand_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/thread_pool.h"
+#include "base/trace_event/base_tracing.h"
+#include "base/uuid.h"
+#include "build/build_config.h"
+#include "components/services/storage/filesystem_proxy_factory.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction.h"
+#include "content/browser/indexed_db/file_stream_reader_to_data_pipe.h"
 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
@@ -29,6 +36,8 @@
 #include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
 #include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "net/base/net_errors.h"
+#include "storage/browser/file_system/file_stream_reader.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 
@@ -105,6 +114,139 @@
 
 }  // namespace
 
+// BlobDataItemReader implementation providing a BlobDataItem -> file adapter.
+class IndexedDBDataItemReader : public storage::mojom::BlobDataItemReader {
+ public:
+  IndexedDBDataItemReader(
+      const base::FilePath& file_path,
+      base::Time expected_modification_time,
+      base::OnceClosure release_callback,
+      base::OnceCallback<void(const base::FilePath&)>
+          on_last_receiver_disconnected,
+      scoped_refptr<base::TaskRunner> file_task_runner,
+      scoped_refptr<base::TaskRunner> io_task_runner,
+      mojo::PendingReceiver<storage::mojom::BlobDataItemReader>
+          initial_receiver)
+      : file_path_(file_path),
+        expected_modification_time_(std::move(expected_modification_time)),
+        release_callback_(std::move(release_callback)),
+        on_last_receiver_disconnected_(
+            std::move(on_last_receiver_disconnected)),
+        file_task_runner_(std::move(file_task_runner)),
+        io_task_runner_(std::move(io_task_runner)) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    DCHECK(file_task_runner_);
+    DCHECK(io_task_runner_);
+
+    AddReader(std::move(initial_receiver));
+
+    // The `BlobStorageContext` will disconnect when the blob is no longer
+    // referenced.
+    receivers_.set_disconnect_handler(
+        base::BindRepeating(&IndexedDBDataItemReader::OnClientDisconnected,
+                            base::Unretained(this)));
+  }
+
+  IndexedDBDataItemReader(const IndexedDBDataItemReader&) = delete;
+  IndexedDBDataItemReader& operator=(const IndexedDBDataItemReader&) = delete;
+
+  ~IndexedDBDataItemReader() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    std::move(release_callback_).Run();
+  }
+
+  void AddReader(mojo::PendingReceiver<BlobDataItemReader> receiver) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    DCHECK(receiver.is_valid());
+
+    receivers_.Add(this, std::move(receiver));
+  }
+
+  void Read(uint64_t offset,
+            uint64_t length,
+            mojo::ScopedDataPipeProducerHandle pipe,
+            ReadCallback callback) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+    auto reader = storage::FileStreamReader::CreateForIndexedDBDataItemReader(
+        file_task_runner_.get(), file_path_, storage::CreateFilesystemProxy(),
+        offset, expected_modification_time_);
+    auto adapter = std::make_unique<FileStreamReaderToDataPipe>(
+        std::move(reader), std::move(pipe));
+    auto* raw_adapter = adapter.get();
+
+    // Have the adapter (owning the reader) be owned by the result callback.
+    auto current_task_runner = base::SequencedTaskRunner::GetCurrentDefault();
+    auto result_callback = base::BindOnce(
+        [](std::unique_ptr<FileStreamReaderToDataPipe> reader,
+           scoped_refptr<base::SequencedTaskRunner> task_runner,
+           ReadCallback callback, int result) {
+          // |callback| is expected to be run on the original sequence
+          // that called this Read function, so post it back.
+          task_runner->PostTask(FROM_HERE,
+                                base::BindOnce(std::move(callback), result));
+        },
+        std::move(adapter), std::move(current_task_runner),
+        std::move(callback));
+
+    // On Windows, all async file IO needs to be done on the io thread.
+    // Do this on all platforms for consistency, even if not necessary on posix.
+    io_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            [](FileStreamReaderToDataPipe* adapter, uint64_t length,
+               base::OnceCallback<void(int)> result_callback) {
+              adapter->Start(std::move(result_callback), length);
+            },
+            // |raw_adapter| is owned by |result_callback|.
+            base::Unretained(raw_adapter), length, std::move(result_callback)));
+  }
+
+  void ReadSideData(ReadSideDataCallback callback) override {
+    // This type should never have side data.
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    std::move(callback).Run(net::ERR_NOT_IMPLEMENTED, mojo_base::BigBuffer());
+  }
+
+ private:
+  void OnClientDisconnected() {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    if (!receivers_.empty()) {
+      return;
+    }
+
+    std::move(on_last_receiver_disconnected_).Run(file_path_);
+    // `this` is deleted.
+  }
+
+  mojo::ReceiverSet<storage::mojom::BlobDataItemReader> receivers_;
+
+  base::FilePath file_path_;
+  base::Time expected_modification_time_;
+
+  // Called on destruction. TODO(estade): can this be combined with
+  // `on_last_receiver_disconnected_`?
+  base::OnceClosure release_callback_;
+
+  // Called when the last receiver is disconnected. Will destroy `this`.
+  base::OnceCallback<void(const base::FilePath&)>
+      on_last_receiver_disconnected_;
+
+  // There are a lot of task runners in this class:
+  // * IndexedDBDataItemReader runs on the same sequence as
+  // `IndexedDBBucketContext`.
+  // * LocalFileStreamReader wants its own |file_task_runner_| to run
+  //   various asynchronous file operations on.
+  // * net::FileStream (used by LocalFileStreamReader) needs to be run
+  //   on an IO thread for asynchronous file operations (on Windows), which
+  //   is done by passing in an |io_task_runner| to do this.
+  // TODO(estade): can these be simplified?
+  scoped_refptr<base::TaskRunner> file_task_runner_;
+  scoped_refptr<base::TaskRunner> io_task_runner_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
 constexpr const base::TimeDelta
     IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow;
 constexpr const base::TimeDelta
@@ -128,22 +270,32 @@
     storage::BucketInfo bucket_info,
     bool persist_for_incognito,
     base::Clock* clock,
-    TransactionalLevelDBFactory* transactional_leveldb_factory,
     std::unique_ptr<PartitionedLockManager> lock_manager,
     Delegate&& delegate,
     std::unique_ptr<IndexedDBBackingStore> backing_store,
     scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
+    scoped_refptr<base::TaskRunner> io_task_runner,
+    mojo::PendingRemote<storage::mojom::BlobStorageContext>
+        blob_storage_context,
+    mojo::PendingRemote<storage::mojom::FileSystemAccessContext>
+        file_system_access_context,
     InstanceClosure initialize_closure)
     : bucket_info_(std::move(bucket_info)),
       persist_for_incognito_(persist_for_incognito),
       clock_(clock),
-      transactional_leveldb_factory_(transactional_leveldb_factory),
       lock_manager_(std::move(lock_manager)),
       backing_store_(std::move(backing_store)),
       quota_manager_proxy_(std::move(quota_manager_proxy)),
+      file_task_runner_(base::ThreadPool::CreateTaskRunner(
+          {base::MayBlock(), base::TaskPriority::USER_VISIBLE})),
+      io_task_runner_(std::move(io_task_runner)),
+      blob_storage_context_(std::move(blob_storage_context)),
+      file_system_access_context_(std::move(file_system_access_context)),
       delegate_(std::move(delegate)) {
   DCHECK(clock_);
 
+  backing_store_->set_bucket_context(this);
+
   if (!initialize_closure) {
     base::Time now = clock_->Now();
     initialize_closure =
@@ -267,6 +419,82 @@
          (1 - bucket_space_age / kBucketSpaceCacheTimeLimit);
 }
 
+void IndexedDBBucketContext::CreateAllExternalObjects(
+    const std::vector<IndexedDBExternalObject>& objects,
+    std::vector<blink::mojom::IDBExternalObjectPtr>* mojo_objects) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  TRACE_EVENT0("IndexedDB", "IndexedDBBucketContext::CreateAllExternalObjects");
+
+  DCHECK_EQ(objects.size(), mojo_objects->size());
+  if (objects.empty()) {
+    return;
+  }
+
+  for (size_t i = 0; i < objects.size(); ++i) {
+    auto& blob_info = objects[i];
+    auto& mojo_object = (*mojo_objects)[i];
+
+    switch (blob_info.object_type()) {
+      case IndexedDBExternalObject::ObjectType::kBlob:
+      case IndexedDBExternalObject::ObjectType::kFile: {
+        DCHECK(mojo_object->is_blob_or_file());
+        auto& output_info = mojo_object->get_blob_or_file();
+
+        auto receiver = output_info->blob.InitWithNewPipeAndPassReceiver();
+        if (blob_info.is_remote_valid()) {
+          output_info->uuid = blob_info.uuid();
+          blob_info.Clone(std::move(receiver));
+          continue;
+        }
+
+        auto element = storage::mojom::BlobDataItem::New();
+        // TODO(enne): do we have to handle unknown size here??
+        element->size = blob_info.size();
+        element->side_data_size = 0;
+        element->content_type = base::UTF16ToUTF8(blob_info.type());
+        element->type = storage::mojom::BlobDataItemType::kIndexedDB;
+
+        base::Time last_modified;
+        // Android doesn't seem to consistently be able to set file modification
+        // times. https://crbug.com/1045488
+#if !BUILDFLAG(IS_ANDROID)
+        last_modified = blob_info.last_modified();
+#endif
+        BindFileReader(blob_info.indexed_db_file_path(), last_modified,
+                       blob_info.release_callback(),
+                       element->reader.InitWithNewPipeAndPassReceiver());
+
+        // Write results to output_info.
+        output_info->uuid = base::Uuid::GenerateRandomV4().AsLowercaseString();
+
+        blob_storage_context_->RegisterFromDataItem(
+            std::move(receiver), output_info->uuid, std::move(element));
+        break;
+      }
+      case IndexedDBExternalObject::ObjectType::kFileSystemAccessHandle: {
+        DCHECK(mojo_object->is_file_system_access_token());
+
+        mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken>
+            mojo_token;
+
+        if (blob_info.is_file_system_access_remote_valid()) {
+          blob_info.file_system_access_token_remote()->Clone(
+              mojo_token.InitWithNewPipeAndPassReceiver());
+        } else {
+          DCHECK(!blob_info.serialized_file_system_access_handle().empty());
+          file_system_access_context_->DeserializeHandle(
+              bucket_info_.storage_key,
+              blob_info.serialized_file_system_access_handle(),
+              mojo_token.InitWithNewPipeAndPassReceiver());
+        }
+        mojo_object->get_file_system_access_token() = std::move(mojo_token);
+        break;
+      }
+    }
+  }
+}
+
 std::tuple<IndexedDBBucketContext::RunTasksResult, leveldb::Status>
 IndexedDBBucketContext::RunTasks() {
   task_run_scheduled_ = false;
@@ -454,8 +682,9 @@
       &IndexedDBBucketContext::SetInternalState, earliest_global_sweep_time_,
       earliest_global_compaction_time_));
   std::unique_ptr<LevelDBDirectTransaction> txn =
-      transactional_leveldb_factory_->CreateLevelDBDirectTransaction(
-          backing_store_->db());
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBDirectTransaction(backing_store_->db());
   s = indexed_db::SetEarliestSweepTime(txn.get(),
                                        GenerateNextBucketSweepTime(now));
   // TODO(dmurph): Log this or report to UMA.
@@ -498,8 +727,9 @@
       &IndexedDBBucketContext::SetInternalState, earliest_global_sweep_time_,
       earliest_global_compaction_time_));
   std::unique_ptr<LevelDBDirectTransaction> txn =
-      transactional_leveldb_factory_->CreateLevelDBDirectTransaction(
-          backing_store_->db());
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBDirectTransaction(backing_store_->db());
   s = indexed_db::SetEarliestCompactionTime(
       txn.get(), GenerateNextBucketCompactionTime(now));
   // TODO(dmurph): Log this or report to UMA.
@@ -515,4 +745,32 @@
   return true;
 }
 
+void IndexedDBBucketContext::BindFileReader(
+    const base::FilePath& path,
+    base::Time expected_modification_time,
+    base::OnceClosure release_callback,
+    mojo::PendingReceiver<storage::mojom::BlobDataItemReader> receiver) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(receiver.is_valid());
+  DCHECK(file_task_runner_);
+
+  auto itr = file_reader_map_.find(path);
+  if (itr != file_reader_map_.end()) {
+    itr->second->AddReader(std::move(receiver));
+    return;
+  }
+
+  auto reader = std::make_unique<IndexedDBDataItemReader>(
+      path, expected_modification_time, std::move(release_callback),
+      base::BindOnce(&IndexedDBBucketContext::RemoveBoundReaders,
+                     weak_factory_.GetWeakPtr()),
+      file_task_runner_, io_task_runner_, std::move(receiver));
+  file_reader_map_.insert({path, std::move(reader)});
+}
+
+void IndexedDBBucketContext::RemoveBoundReaders(const base::FilePath& path) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  file_reader_map_.erase(path);
+}
+
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_bucket_context.h b/content/browser/indexed_db/indexed_db_bucket_context.h
index 9064a6d..2f5eeb3 100644
--- a/content/browser/indexed_db/indexed_db_bucket_context.h
+++ b/content/browser/indexed_db/indexed_db_bucket_context.h
@@ -22,9 +22,13 @@
 #include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
 #include "components/services/storage/public/cpp/buckets/bucket_info.h"
 #include "components/services/storage/public/cpp/quota_error_or.h"
+#include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
+#include "components/services/storage/public/mojom/file_system_access_context.mojom.h"
 #include "content/browser/indexed_db/indexed_db_bucket_context_handle.h"
+#include "content/browser/indexed_db/indexed_db_external_object.h"
 #include "content/browser/indexed_db/indexed_db_task_helper.h"
 #include "content/common/content_export.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 #include "third_party/leveldatabase/src/include/leveldb/status.h"
 
 namespace storage {
@@ -34,9 +38,9 @@
 namespace content {
 class IndexedDBBackingStore;
 class IndexedDBDatabase;
+class IndexedDBDataItemReader;
 class IndexedDBFactory;
 class IndexedDBPreCloseTaskQueue;
-class TransactionalLevelDBFactory;
 
 constexpr const char kIDBCloseImmediatelySwitch[] = "idb-close-immediately";
 
@@ -153,11 +157,15 @@
       storage::BucketInfo bucket_info,
       bool persist_for_incognito,
       base::Clock* clock,
-      TransactionalLevelDBFactory* transactional_leveldb_factory,
       std::unique_ptr<PartitionedLockManager> lock_manager,
       Delegate&& delegate,
       std::unique_ptr<IndexedDBBackingStore> backing_store,
       scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
+      scoped_refptr<base::TaskRunner> io_task_runner,
+      mojo::PendingRemote<storage::mojom::BlobStorageContext>
+          blob_storage_context,
+      mojo::PendingRemote<storage::mojom::FileSystemAccessContext>
+          file_system_access_context,
       InstanceClosure initialization_closure);
 
   IndexedDBBucketContext(const IndexedDBBucketContext&) = delete;
@@ -195,6 +203,12 @@
       int64_t space_requested,
       base::OnceCallback<void(bool)> disk_space_check_callback);
 
+  // Create external objects from |objects| and store the results in
+  // |mojo_objects|. |mojo_objects| must be the same length as |objects|.
+  void CreateAllExternalObjects(
+      const std::vector<IndexedDBExternalObject>& objects,
+      std::vector<blink::mojom::IDBExternalObjectPtr>* mojo_objects);
+
   const storage::BucketInfo& bucket_info() { return bucket_info_; }
   storage::BucketLocator bucket_locator() {
     return bucket_info_.ToBucketLocator();
@@ -242,6 +256,13 @@
     return quota_manager_proxy_.get();
   }
 
+  storage::mojom::BlobStorageContext* blob_storage_context() {
+    return blob_storage_context_.get();
+  }
+  storage::mojom::FileSystemAccessContext* file_system_access_context() {
+    return file_system_access_context_.get();
+  }
+
  private:
   friend IndexedDBFactory;
   friend IndexedDBBucketContextHandle;
@@ -297,6 +318,15 @@
   // since `bucket_space_remaining_timestamp_`.
   int64_t GetBucketSpaceToAllot();
 
+  // Bind `receiver` to read from the file at `path`.
+  void BindFileReader(
+      const base::FilePath& path,
+      base::Time expected_modification_time,
+      base::OnceClosure release_callback,
+      mojo::PendingReceiver<storage::mojom::BlobDataItemReader> receiver);
+  // Removes all readers for this file path.
+  void RemoveBoundReaders(const base::FilePath& path);
+
   SEQUENCE_CHECKER(sequence_checker_);
 
   storage::BucketInfo bucket_info_;
@@ -311,7 +341,6 @@
   bool has_blobs_outstanding_ = false;
   bool skip_closing_sequence_ = false;
   const raw_ptr<base::Clock> clock_;
-  const raw_ptr<TransactionalLevelDBFactory> transactional_leveldb_factory_;
 
   bool running_tasks_ = false;
   bool task_run_scheduled_ = false;
@@ -342,6 +371,20 @@
   // manager.
   base::TimeTicks bucket_space_remaining_timestamp_;
 
+  // Members in the following block are used for `CreateAllExternalObjects`.
+  // Shared task runner used to read blob files on.
+  const scoped_refptr<base::TaskRunner> file_task_runner_;
+  // Shared task runner used for async I/O while reading blob files.
+  const scoped_refptr<base::TaskRunner> io_task_runner_;
+  // Mojo connection to `BlobStorageContext`, which runs on the IO thread.
+  mojo::Remote<storage::mojom::BlobStorageContext> blob_storage_context_;
+  // Mojo connection to `FileSystemAccessContextImpl`, which runs on the UI
+  // thread.
+  mojo::Remote<storage::mojom::FileSystemAccessContext>
+      file_system_access_context_;
+  std::map<base::FilePath, std::unique_ptr<IndexedDBDataItemReader>>
+      file_reader_map_;
+
   std::unique_ptr<IndexedDBPreCloseTaskQueue> pre_close_task_queue_;
 
   Delegate delegate_;
diff --git a/content/browser/indexed_db/indexed_db_bucket_context_unittest.cc b/content/browser/indexed_db/indexed_db_bucket_context_unittest.cc
index e760c0d..e459fe2b 100644
--- a/content/browser/indexed_db/indexed_db_bucket_context_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_bucket_context_unittest.cc
@@ -48,11 +48,12 @@
         blink::mojom::StorageType::kTemporary);
     bucket_context_ = std::make_unique<IndexedDBBucketContext>(
         bucket_info, false, base::DefaultClock::GetInstance(),
-        &IndexedDBClassFactory::Get()->transactional_leveldb_factory(),
         std::make_unique<PartitionedLockManager>(),
         IndexedDBBucketContext::Delegate(),
         std::make_unique<IndexedDBFakeBackingStore>(), quota_manager_proxy_,
-        base::DoNothing());
+        /*io_task_runner=*/base::SequencedTaskRunner::GetCurrentDefault(),
+        /*blob_storage_context=*/mojo::NullRemote(),
+        /*file_system_access_context=*/mojo::NullRemote(), base::DoNothing());
   }
 
   void SetQuotaLeft(int64_t quota_manager_response) {
diff --git a/content/browser/indexed_db/indexed_db_class_factory.cc b/content/browser/indexed_db/indexed_db_class_factory.cc
index e60939a4..491e7162 100644
--- a/content/browser/indexed_db/indexed_db_class_factory.cc
+++ b/content/browser/indexed_db/indexed_db_class_factory.cc
@@ -8,14 +8,15 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
+#include "components/services/storage/filesystem_proxy_factory.h"
 #include "components/services/storage/indexed_db/leveldb/leveldb_factory.h"
 #include "components/services/storage/indexed_db/scopes/leveldb_scope.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
 #include "content/browser/indexed_db/indexed_db_reporting.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "third_party/leveldatabase/env_chromium.h"
 #include "third_party/leveldatabase/leveldb_chrome.h"
 #include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
 
@@ -32,22 +33,19 @@
   return transactional_leveldb_factory.get();
 }
 }  // namespace
-static IndexedDBClassFactory::GetterCallback* s_factory_getter;
+
 static ::base::LazyInstance<IndexedDBClassFactory>::Leaky s_factory =
     LAZY_INSTANCE_INITIALIZER;
 
-void IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(GetterCallback* cb) {
-  s_factory_getter = cb;
-}
-
 // static
 IndexedDBClassFactory* IndexedDBClassFactory::Get() {
-  if (s_factory_getter)
-    return (*s_factory_getter)();
-  else
-    return s_factory.Pointer();
+  return s_factory.Pointer();
 }
 
+IndexedDBClassFactory::IndexedDBClassFactory()
+    : leveldb_factory_(GetDefaultLevelDBFactory()),
+      transactional_leveldb_factory_(GetDefaultTransactionalLevelDBFactory()) {}
+
 // static
 leveldb_env::Options IndexedDBClassFactory::GetLevelDBOptions() {
   static const leveldb::FilterPolicy* kIDBFilterPolicy =
@@ -60,25 +58,19 @@
   // For info about the troubles we've run into with this parameter, see:
   // https://crbug.com/227313#c11
   options.max_open_files = 80;
-  options.env = IndexedDBLevelDBEnv::Get();
   options.block_cache = leveldb_chrome::GetSharedWebBlockCache();
   options.on_get_error = base::BindRepeating(
       indexed_db::ReportLevelDBError, "WebCore.IndexedDB.LevelDBReadErrors");
   options.on_write_error = base::BindRepeating(
       indexed_db::ReportLevelDBError, "WebCore.IndexedDB.LevelDBWriteErrors");
+
+  static base::NoDestructor<leveldb_env::ChromiumEnv> g_leveldb_env(
+      "LevelDBEnv.IDB");
+  options.env = g_leveldb_env.get();
+
   return options;
 }
 
-IndexedDBClassFactory::IndexedDBClassFactory()
-    : IndexedDBClassFactory(GetDefaultLevelDBFactory(),
-                            GetDefaultTransactionalLevelDBFactory()) {}
-
-IndexedDBClassFactory::IndexedDBClassFactory(
-    LevelDBFactory* leveldb_factory,
-    TransactionalLevelDBFactory* transactional_leveldb_factory)
-    : leveldb_factory_(leveldb_factory),
-      transactional_leveldb_factory_(transactional_leveldb_factory) {}
-
 LevelDBFactory& IndexedDBClassFactory::leveldb_factory() {
   return *leveldb_factory_;
 }
@@ -87,26 +79,13 @@
   return *transactional_leveldb_factory_;
 }
 
-std::unique_ptr<IndexedDBDatabase>
-IndexedDBClassFactory::CreateIndexedDBDatabase(
-    const std::u16string& name,
-    IndexedDBBucketContext& bucket_context,
-    const IndexedDBDatabase::Identifier& unique_identifier) {
-  return base::WrapUnique(
-      new IndexedDBDatabase(name, bucket_context, this, unique_identifier));
-}
-
-std::unique_ptr<IndexedDBTransaction>
-IndexedDBClassFactory::CreateIndexedDBTransaction(
-    int64_t id,
-    IndexedDBConnection* connection,
-    const std::set<int64_t>& scope,
-    blink::mojom::IDBTransactionMode mode,
-    IndexedDBBucketContextHandle bucket_context,
-    IndexedDBBackingStore::Transaction* backing_store_transaction) {
-  return base::WrapUnique(new IndexedDBTransaction(id, connection, scope, mode,
-                                                   std::move(bucket_context),
-                                                   backing_store_transaction));
+void IndexedDBClassFactory::SetTransactionalLevelDBFactoryForTesting(
+    TransactionalLevelDBFactory* factory) {
+  if (factory) {
+    transactional_leveldb_factory_ = factory;
+  } else {
+    transactional_leveldb_factory_ = GetDefaultTransactionalLevelDBFactory();
+  }
 }
 
 void IndexedDBClassFactory::SetLevelDBFactoryForTesting(
diff --git a/content/browser/indexed_db/indexed_db_class_factory.h b/content/browser/indexed_db/indexed_db_class_factory.h
index 45ed26d..4851b8b 100644
--- a/content/browser/indexed_db/indexed_db_class_factory.h
+++ b/content/browser/indexed_db/indexed_db_class_factory.h
@@ -5,77 +5,36 @@
 #ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CLASS_FACTORY_H_
 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CLASS_FACTORY_H_
 
-#include <stdint.h>
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include "base/functional/callback.h"
 #include "base/lazy_instance.h"
 #include "base/memory/raw_ptr.h"
-#include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
-#include "content/browser/indexed_db/indexed_db_backing_store.h"
-#include "content/browser/indexed_db/indexed_db_database.h"
-#include "content/browser/indexed_db/indexed_db_task_helper.h"
-#include "content/browser/indexed_db/indexed_db_transaction.h"
 #include "content/common/content_export.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 #include "third_party/leveldatabase/env_chromium.h"
-#include "third_party/leveldatabase/src/include/leveldb/status.h"
 
 namespace content {
-class IndexedDBBackingStore;
-class IndexedDBConnection;
-class IndexedDBTransaction;
 class LevelDBFactory;
 class TransactionalLevelDBFactory;
 
-// Use this factory to create some IndexedDB objects. Exists solely to
-// facilitate tests which sometimes need to inject mock objects into the system.
-// TODO(dmurph): Remove this class in favor of dependency injection. This makes
-// it really hard to iterate on the system.
+// This singleton holds onto LevelDB factories which can be replaced with
+// testing versions to facilitate mocking out of LevelDB objects and operations.
+// TODO(estade): all LevelDB dependencies should be tucked away behind
+// `IndexedDBBackingStore`.
 class CONTENT_EXPORT IndexedDBClassFactory {
  public:
-  typedef IndexedDBClassFactory* GetterCallback();
-  // Used to report irrecoverable backend errors. The second argument can be
-  // null.
-  using ErrorCallback =
-      base::RepeatingCallback<void(leveldb::Status, const char*)>;
-
   static IndexedDBClassFactory* Get();
 
-  static void SetIndexedDBClassFactoryGetter(GetterCallback* cb);
-
   // Visible for testing.
   static leveldb_env::Options GetLevelDBOptions();
 
-  virtual LevelDBFactory& leveldb_factory();
-  virtual TransactionalLevelDBFactory& transactional_leveldb_factory();
+  LevelDBFactory& leveldb_factory();
+  TransactionalLevelDBFactory& transactional_leveldb_factory();
 
-  // Returns a database that is newly constructed, but which has uninitialized
-  // metadata.
-  virtual std::unique_ptr<IndexedDBDatabase> CreateIndexedDBDatabase(
-      const std::u16string& name,
-      IndexedDBBucketContext& bucket_context,
-      const IndexedDBDatabase::Identifier& unique_identifier);
-
-  virtual std::unique_ptr<IndexedDBTransaction> CreateIndexedDBTransaction(
-      int64_t id,
-      IndexedDBConnection* connection,
-      const std::set<int64_t>& scope,
-      blink::mojom::IDBTransactionMode mode,
-      IndexedDBBucketContextHandle bucket_context,
-      IndexedDBBackingStore::Transaction* backing_store_transaction);
-
+  void SetTransactionalLevelDBFactoryForTesting(
+      TransactionalLevelDBFactory* factory);
   void SetLevelDBFactoryForTesting(LevelDBFactory* leveldb_factory);
 
  protected:
   IndexedDBClassFactory();
-  IndexedDBClassFactory(
-      LevelDBFactory* leveldb_factory,
-      TransactionalLevelDBFactory* transactional_leveldb_factory);
-  virtual ~IndexedDBClassFactory() = default;
+  ~IndexedDBClassFactory() = default;
   friend struct base::LazyInstanceTraitsBase<IndexedDBClassFactory>;
 
   raw_ptr<LevelDBFactory> leveldb_factory_;
diff --git a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index 49e10fe..8e694d6 100644
--- a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -19,7 +19,6 @@
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/leveldatabase/env_chromium.h"
@@ -43,22 +42,21 @@
   ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
   const base::FilePath path = temp_directory.GetPath();
 
-  DefaultTransactionalLevelDBFactory transactional_leveldb_factory;
   auto task_runner = base::SequencedTaskRunner::GetCurrentDefault();
-  std::unique_ptr<IndexedDBBackingStore> backing_store = std::make_unique<
-      IndexedDBBackingStore>(
-      IndexedDBBackingStore::Mode::kInMemory, &transactional_leveldb_factory,
-      bucket_locator, path,
-      transactional_leveldb_factory.CreateLevelDBDatabase(
-          FakeLevelDBFactory::GetBrokenLevelDB(
-              leveldb::Status::IOError("It's broken!"), path),
-          nullptr, task_runner.get(),
-          TransactionalLevelDBDatabase::kDefaultMaxOpenIteratorsPerDatabase),
-      /*blob_storage_context=*/nullptr,
-      /*file_system_access_context=*/nullptr,
-      /*filesystem_proxy=*/nullptr,
-      IndexedDBBackingStore::BlobFilesCleanedCallback(),
-      IndexedDBBackingStore::ReportOutstandingBlobsCallback(), task_runner);
+  std::unique_ptr<IndexedDBBackingStore> backing_store =
+      std::make_unique<IndexedDBBackingStore>(
+          IndexedDBBackingStore::Mode::kInMemory, bucket_locator, path,
+          IndexedDBClassFactory::Get()
+              ->transactional_leveldb_factory()
+              .CreateLevelDBDatabase(
+                  FakeLevelDBFactory::GetBrokenLevelDB(
+                      leveldb::Status::IOError("It's broken!"), path),
+                  nullptr, task_runner.get(),
+                  TransactionalLevelDBDatabase::
+                      kDefaultMaxOpenIteratorsPerDatabase),
+          /*filesystem_proxy=*/nullptr,
+          IndexedDBBackingStore::BlobFilesCleanedCallback(),
+          IndexedDBBackingStore::ReportOutstandingBlobsCallback(), task_runner);
   leveldb::Status s = backing_store->Initialize(false);
   EXPECT_FALSE(s.ok());
   ASSERT_TRUE(temp_directory.Delete());
@@ -75,7 +73,6 @@
   const base::FilePath path = temp_directory.GetPath();
   auto task_runner = base::SequencedTaskRunner::GetCurrentDefault();
 
-  DefaultTransactionalLevelDBFactory transactional_leveldb_factory;
   std::array<leveldb::Status, 4> errors = {
       MakeIOError("some filename", "some message", leveldb_env::kNewLogger,
                   base::File::FILE_ERROR_NO_SPACE),
@@ -86,19 +83,20 @@
       MakeIOError("some filename", "some message", leveldb_env::kNewLogger,
                   base::File::FILE_ERROR_FAILED)};
   for (leveldb::Status error_status : errors) {
-    std::unique_ptr<IndexedDBBackingStore> backing_store = std::make_unique<
-        IndexedDBBackingStore>(
-        IndexedDBBackingStore::Mode::kInMemory, &transactional_leveldb_factory,
-        bucket_locator, path,
-        transactional_leveldb_factory.CreateLevelDBDatabase(
-            FakeLevelDBFactory::GetBrokenLevelDB(error_status, path), nullptr,
-            task_runner.get(),
-            TransactionalLevelDBDatabase::kDefaultMaxOpenIteratorsPerDatabase),
-        /*blob_storage_context=*/nullptr,
-        /*file_system_access_context=*/nullptr,
-        /*filesystem_proxy=*/nullptr,
-        IndexedDBBackingStore::BlobFilesCleanedCallback(),
-        IndexedDBBackingStore::ReportOutstandingBlobsCallback(), task_runner);
+    std::unique_ptr<IndexedDBBackingStore> backing_store =
+        std::make_unique<IndexedDBBackingStore>(
+            IndexedDBBackingStore::Mode::kInMemory, bucket_locator, path,
+            IndexedDBClassFactory::Get()
+                ->transactional_leveldb_factory()
+                .CreateLevelDBDatabase(
+                    FakeLevelDBFactory::GetBrokenLevelDB(error_status, path),
+                    nullptr, task_runner.get(),
+                    TransactionalLevelDBDatabase::
+                        kDefaultMaxOpenIteratorsPerDatabase),
+            /*filesystem_proxy=*/nullptr,
+            IndexedDBBackingStore::BlobFilesCleanedCallback(),
+            IndexedDBBackingStore::ReportOutstandingBlobsCallback(),
+            task_runner);
     leveldb::Status s = backing_store->Initialize(false);
     ASSERT_TRUE(s.IsIOError());
   }
diff --git a/content/browser/indexed_db/indexed_db_connection.cc b/content/browser/indexed_db/indexed_db_connection.cc
index 6317187..160b65ad 100644
--- a/content/browser/indexed_db/indexed_db_connection.cc
+++ b/content/browser/indexed_db/indexed_db_connection.cc
@@ -12,7 +12,6 @@
 #include "base/trace_event/base_tracing.h"
 #include "components/services/storage/privileged/mojom/indexed_db_client_state_checker.mojom-forward.h"
 #include "content/browser/indexed_db/indexed_db_bucket_context.h"
-#include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
 #include "content/browser/indexed_db/indexed_db_database_error.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
@@ -31,7 +30,6 @@
 
 IndexedDBConnection::IndexedDBConnection(
     IndexedDBBucketContext& bucket_context,
-    IndexedDBClassFactory* indexed_db_class_factory,
     base::WeakPtr<IndexedDBDatabase> database,
     base::RepeatingClosure on_version_change_ignored,
     base::OnceCallback<void(IndexedDBConnection*)> on_close,
@@ -39,7 +37,6 @@
     scoped_refptr<IndexedDBClientStateCheckerWrapper> client_state_checker)
     : id_(g_next_indexed_db_connection_id++),
       bucket_context_handle_(bucket_context),
-      indexed_db_class_factory_(indexed_db_class_factory),
       database_(std::move(database)),
       on_version_change_ignored_(std::move(on_version_change_ignored)),
       on_close_(std::move(on_close)),
@@ -121,10 +118,8 @@
     IndexedDBBackingStore::Transaction* backing_store_transaction) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CHECK_EQ(GetTransaction(id), nullptr) << "Duplicate transaction id." << id;
-  std::unique_ptr<IndexedDBTransaction> transaction =
-      indexed_db_class_factory_->CreateIndexedDBTransaction(
-          id, this, scope, mode, bucket_context_handle_,
-          backing_store_transaction);
+  auto transaction = std::make_unique<IndexedDBTransaction>(
+      id, this, scope, mode, bucket_context_handle_, backing_store_transaction);
   IndexedDBTransaction* transaction_ptr = transaction.get();
   transactions_[id] = std::move(transaction);
   return transaction_ptr;
diff --git a/content/browser/indexed_db/indexed_db_connection.h b/content/browser/indexed_db/indexed_db_connection.h
index 57219e5..0947e5c5 100644
--- a/content/browser/indexed_db/indexed_db_connection.h
+++ b/content/browser/indexed_db/indexed_db_connection.h
@@ -29,7 +29,6 @@
  public:
   IndexedDBConnection(
       IndexedDBBucketContext& bucket_context,
-      IndexedDBClassFactory* indexed_db_class_factory,
       base::WeakPtr<IndexedDBDatabase> database,
       base::RepeatingClosure on_version_change_ignored,
       base::OnceCallback<void(IndexedDBConnection*)> on_close,
@@ -108,7 +107,6 @@
 
   // Keeps the factory for this bucket alive.
   IndexedDBBucketContextHandle bucket_context_handle_;
-  const raw_ptr<IndexedDBClassFactory> indexed_db_class_factory_;
 
   base::WeakPtr<IndexedDBDatabase> database_;
   base::RepeatingClosure on_version_change_ignored_;
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc
index 8afb7c6..247dd91b 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -64,8 +64,6 @@
 #include "third_party/zlib/google/zip.h"
 #include "url/origin.h"
 
-using storage::DatabaseUtil;
-
 namespace content {
 
 namespace {
@@ -76,10 +74,6 @@
   return s_factory.Pointer();
 }
 
-static IndexedDBClassFactory* GetTestIDBClassFactory() {
-  return GetTestClassFactory();
-}
-
 bool IsAllowedPath(const std::vector<base::FilePath>& allowed_paths,
                    const base::FilePath& candidate_path) {
   for (const base::FilePath& allowed_path : allowed_paths) {
@@ -127,7 +121,8 @@
                      base::TaskPriority::USER_VISIBLE,
                      // BLOCK_SHUTDOWN to support clearing session-only storage.
                      base::TaskShutdownBehavior::BLOCK_SHUTDOWN}))),
-      dispatcher_host_(this, std::move(io_task_runner)),
+      io_task_runner_(std::move(io_task_runner)),
+      dispatcher_host_(this),
       base_data_path_(base_data_path.empty() ? base::FilePath()
                                              : base_data_path),
       force_keep_session_state_(false),
@@ -807,6 +802,7 @@
 
 void IndexedDBContextImpl::BindMockFailureSingletonForTesting(
     mojo::PendingReceiver<storage::mojom::MockFailureInjector> receiver) {
+  IndexedDBTransaction::DisableInactivityTimeoutForTesting();  // IN-TEST
   // Lazily instantiate the GetTestClassFactory.
   if (!mock_failure_injector_.has_value())
     mock_failure_injector_.emplace(GetTestClassFactory());
@@ -814,12 +810,11 @@
   // TODO(enne): this should really not be a static setter.
   CHECK(!mock_failure_injector_->is_bound());
   GetTestClassFactory()->Reset();
-  IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(GetTestIDBClassFactory);
+  IndexedDBClassFactory::Get()
+      ->SetTransactionalLevelDBFactoryForTesting(  // IN-TEST
+          GetTestClassFactory());
 
   mock_failure_injector_->Bind(std::move(receiver));
-  mock_failure_injector_->set_disconnect_handler(base::BindOnce([]() {
-    IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(nullptr);
-  }));
 }
 
 void IndexedDBContextImpl::GetDatabaseKeysForTesting(
@@ -830,8 +825,7 @@
 IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
   if (!indexeddb_factory_.get()) {
-    indexeddb_factory_ = std::make_unique<IndexedDBFactory>(
-        this, IndexedDBClassFactory::Get(), clock_);
+    indexeddb_factory_ = std::make_unique<IndexedDBFactory>(this, clock_);
   }
   return indexeddb_factory_.get();
 }
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h
index 16b36bb..489c2b18 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -64,7 +64,6 @@
       scoped_refptr<IndexedDBContextImpl>&& context);
 
   // If `base_data_path` is empty, nothing will be saved to disk.
-  // `task_runner` is optional, and only set during testing.
   // This is *not* called on the IDBTaskRunner, unlike most other functions.
   IndexedDBContextImpl(
       const base::FilePath& base_data_path,
@@ -162,8 +161,13 @@
 
   int64_t GetBucketDiskUsage(const storage::BucketLocator& bucket_locator);
 
-  // This getter is thread-safe.
-  base::SequencedTaskRunner* IDBTaskRunner() { return idb_task_runner_.get(); }
+  const scoped_refptr<base::SequencedTaskRunner>& IDBTaskRunner() {
+    return idb_task_runner_;
+  }
+
+  const scoped_refptr<base::TaskRunner>& IOTaskRunner() {
+    return io_task_runner_;
+  }
 
   // Methods called by IndexedDBFactory or IndexedDBDispatcherHost for
   // quota support.
@@ -299,6 +303,7 @@
       std::vector<storage::QuotaErrorOr<storage::BucketInfo>> bucket_infos);
 
   const scoped_refptr<base::SequencedTaskRunner> idb_task_runner_;
+  const scoped_refptr<base::TaskRunner> io_task_runner_;
   IndexedDBDispatcherHost dispatcher_host_;
 
   // Bound and accessed on the `idb_task_runner_`.
diff --git a/content/browser/indexed_db/indexed_db_cursor.cc b/content/browser/indexed_db/indexed_db_cursor.cc
index fa67b53..a08151d 100644
--- a/content/browser/indexed_db/indexed_db_cursor.cc
+++ b/content/browser/indexed_db/indexed_db_cursor.cc
@@ -52,11 +52,10 @@
     std::unique_ptr<IndexedDBBackingStore::Cursor> cursor,
     indexed_db::CursorType cursor_type,
     blink::mojom::IDBTaskType task_type,
-    IndexedDBDispatcherHost& dispatcher_host,
     base::WeakPtr<IndexedDBTransaction> transaction,
     mojo::PendingAssociatedRemote<blink::mojom::IDBCursor>& pending_remote) {
   auto instance = base::WrapUnique(new IndexedDBCursor(
-      std::move(cursor), cursor_type, task_type, dispatcher_host, transaction));
+      std::move(cursor), cursor_type, task_type, transaction));
   IndexedDBCursor* instance_ptr = instance.get();
   mojo::MakeSelfOwnedAssociatedReceiver(
       std::move(instance), pending_remote.InitWithNewEndpointAndPassReceiver());
@@ -67,7 +66,6 @@
     std::unique_ptr<IndexedDBBackingStore::Cursor> cursor,
     indexed_db::CursorType cursor_type,
     blink::mojom::IDBTaskType task_type,
-    IndexedDBDispatcherHost& dispatcher_host,
     base::WeakPtr<IndexedDBTransaction> transaction)
     : bucket_locator_(transaction->BackingStoreTransaction()
                           ->backing_store()
@@ -75,7 +73,6 @@
       task_type_(task_type),
       cursor_type_(cursor_type),
       transaction_(std::move(transaction)),
-      dispatcher_host_(&dispatcher_host),
       cursor_(std::move(cursor)) {
   TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("IndexedDB", "IndexedDBCursor::open", this);
 }
@@ -140,8 +137,8 @@
   if (value) {
     mojo_value = IndexedDBValue::ConvertAndEraseValue(value);
     external_objects.swap(value->external_objects);
-    dispatcher_host_->CreateAllExternalObjects(
-        bucket_locator_, external_objects, &mojo_value->external_objects);
+    transaction_->bucket_context()->CreateAllExternalObjects(
+        external_objects, &mojo_value->external_objects);
   } else {
     mojo_value = blink::mojom::IDBValue::New();
   }
@@ -219,8 +216,8 @@
   if (value) {
     mojo_value = IndexedDBValue::ConvertAndEraseValue(value);
     external_objects.swap(value->external_objects);
-    dispatcher_host_->CreateAllExternalObjects(
-        bucket_locator_, external_objects, &mojo_value->external_objects);
+    transaction_->bucket_context()->CreateAllExternalObjects(
+        external_objects, &mojo_value->external_objects);
   } else {
     mojo_value = blink::mojom::IDBValue::New();
   }
@@ -341,9 +338,8 @@
   for (size_t i = 0; i < found_values.size(); ++i) {
     mojo_values.push_back(
         IndexedDBValue::ConvertAndEraseValue(&found_values[i]));
-    dispatcher_host_->CreateAllExternalObjects(
-        bucket_locator_, found_values[i].external_objects,
-        &mojo_values[i]->external_objects);
+    transaction_->bucket_context()->CreateAllExternalObjects(
+        found_values[i].external_objects, &mojo_values[i]->external_objects);
   }
 
   std::move(callback).Run(blink::mojom::IDBCursorResult::NewValues(
diff --git a/content/browser/indexed_db/indexed_db_cursor.h b/content/browser/indexed_db/indexed_db_cursor.h
index 20a1b2cfa..3a7c803 100644
--- a/content/browser/indexed_db/indexed_db_cursor.h
+++ b/content/browser/indexed_db/indexed_db_cursor.h
@@ -14,6 +14,8 @@
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "content/browser/indexed_db/indexed_db_database.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-forward.h"
 
 namespace storage {
@@ -29,7 +31,6 @@
       std::unique_ptr<IndexedDBBackingStore::Cursor> cursor,
       indexed_db::CursorType cursor_type,
       blink::mojom::IDBTaskType task_type,
-      IndexedDBDispatcherHost& dispatcher_host,
       base::WeakPtr<IndexedDBTransaction> transaction,
       mojo::PendingAssociatedRemote<blink::mojom::IDBCursor>& pending_remote);
 
@@ -63,7 +64,6 @@
   IndexedDBCursor(std::unique_ptr<IndexedDBBackingStore::Cursor> cursor,
                   indexed_db::CursorType cursor_type,
                   blink::mojom::IDBTaskType task_type,
-                  IndexedDBDispatcherHost& dispatcher_host,
                   base::WeakPtr<IndexedDBTransaction> transaction);
 
   leveldb::Status ContinueOperation(
@@ -87,8 +87,6 @@
   // We rely on the transaction calling Close() to clear this.
   base::WeakPtr<IndexedDBTransaction> transaction_;
 
-  raw_ptr<IndexedDBDispatcherHost> dispatcher_host_;
-
   // Must be destroyed before transaction_.
   std::unique_ptr<IndexedDBBackingStore::Cursor> cursor_;
   // Must be destroyed before transaction_.
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index 08cc9e6a..7405c8e 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -33,7 +33,6 @@
 #include "content/browser/indexed_db/indexed_db_bucket_context.h"
 #include "content/browser/indexed_db/indexed_db_bucket_context_handle.h"
 #include "content/browser/indexed_db/indexed_db_callback_helpers.h"
-#include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_cursor.h"
@@ -70,15 +69,14 @@
 
 std::vector<blink::mojom::IDBReturnValuePtr> CreateMojoValues(
     std::vector<IndexedDBReturnValue>& found_values,
-    IndexedDBDispatcherHost* dispatcher_host,
-    const storage::BucketLocator& bucket_locator) {
+    IndexedDBBucketContext& bucket_context) {
   std::vector<blink::mojom::IDBReturnValuePtr> mojo_values;
   mojo_values.reserve(found_values.size());
   for (size_t i = 0; i < found_values.size(); ++i) {
     mojo_values.push_back(
         IndexedDBReturnValue::ConvertReturnValue(&found_values[i]));
-    dispatcher_host->CreateAllExternalObjects(
-        bucket_locator, found_values[i].external_objects,
+    bucket_context.CreateAllExternalObjects(
+        found_values[i].external_objects,
         &mojo_values[i]->value->external_objects);
   }
   return mojo_values;
@@ -144,7 +142,6 @@
 
 IndexedDBDatabase::IndexedDBDatabase(const std::u16string& name,
                                      IndexedDBBucketContext& bucket_context,
-                                     IndexedDBClassFactory* class_factory,
                                      const Identifier& unique_identifier)
     : metadata_(name,
                 kInvalidId,
@@ -152,7 +149,6 @@
                 kInvalidId),
       identifier_(unique_identifier),
       bucket_context_(bucket_context),
-      class_factory_(class_factory),
       connection_coordinator_(this, bucket_context) {}
 
 IndexedDBDatabase::~IndexedDBDatabase() = default;
@@ -734,7 +730,6 @@
 }
 
 Status IndexedDBDatabase::GetOperation(
-    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
     int64_t object_store_id,
     int64_t index_id,
     std::unique_ptr<IndexedDBKeyRange> key_range,
@@ -760,13 +755,6 @@
   const IndexedDBKey* key;
 
   Status s = Status::OK();
-  if (!dispatcher_host) {
-    std::move(callback).Run(blink::mojom::IDBDatabaseGetResult::NewErrorResult(
-        CreateIDBErrorPtr(blink::mojom::IDBException::kUnknownError,
-                          "Unknown error", transaction)));
-    return s;
-  }
-
   std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
   if (key_range->IsOnlyKey()) {
     key = &key_range->lower();
@@ -845,9 +833,8 @@
 
     blink::mojom::IDBReturnValuePtr mojo_value =
         IndexedDBReturnValue::ConvertReturnValue(&value);
-    dispatcher_host->CreateAllExternalObjects(
-        bucket_locator(), value.external_objects,
-        &mojo_value->value->external_objects);
+    bucket_context_->CreateAllExternalObjects(
+        value.external_objects, &mojo_value->value->external_objects);
     std::move(callback).Run(
         blink::mojom::IDBDatabaseGetResult::NewValue(std::move(mojo_value)));
     return s;
@@ -899,9 +886,8 @@
 
   blink::mojom::IDBReturnValuePtr mojo_value =
       IndexedDBReturnValue::ConvertReturnValue(&value);
-  dispatcher_host->CreateAllExternalObjects(
-      bucket_locator(), value.external_objects,
-      &mojo_value->value->external_objects);
+  bucket_context_->CreateAllExternalObjects(
+      value.external_objects, &mojo_value->value->external_objects);
   std::move(callback).Run(
       blink::mojom::IDBDatabaseGetResult::NewValue(std::move(mojo_value)));
   return s;
@@ -913,7 +899,6 @@
               "kIDBMaxMessageOverhead is more than INT32_MAX");
 
 Status IndexedDBDatabase::GetAllOperation(
-    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
     int64_t object_store_id,
     int64_t index_id,
     std::unique_ptr<IndexedDBKeyRange> key_range,
@@ -941,13 +926,6 @@
       metadata_.object_stores[object_store_id];
 
   Status s = Status::OK();
-  if (!dispatcher_host) {
-    result_sink->OnError(
-        CreateIDBErrorPtr(blink::mojom::IDBException::kUnknownError,
-                          "Unknown error", transaction));
-    return s;
-  }
-
   std::unique_ptr<IndexedDBBackingStore::Cursor> cursor;
 
   if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
@@ -1053,8 +1031,8 @@
       }
     } else {
       if (found_values.size() >= max_values_before_sending) {
-        result_sink->ReceiveValues(CreateMojoValues(
-            found_values, dispatcher_host.get(), bucket_locator()));
+        result_sink->ReceiveValues(
+            CreateMojoValues(found_values, bucket_context_.get()));
         found_values.clear();
       }
     }
@@ -1066,8 +1044,8 @@
     }
   } else {
     if (!found_values.empty()) {
-      result_sink->ReceiveValues(CreateMojoValues(
-          found_values, dispatcher_host.get(), bucket_locator()));
+      result_sink->ReceiveValues(
+          CreateMojoValues(found_values, bucket_context_.get()));
     }
   }
   return s;
@@ -1268,20 +1246,10 @@
 Status IndexedDBDatabase::OpenCursorOperation(
     std::unique_ptr<OpenCursorOperationParams> params,
     const storage::BucketLocator& bucket_locator,
-    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
     IndexedDBTransaction* transaction) {
   TRACE_EVENT1("IndexedDB", "IndexedDBDatabase::OpenCursorOperation", "txn.id",
                transaction->id());
 
-  Status s;
-  if (!dispatcher_host) {
-    std::move(params->callback)
-        .Run(blink::mojom::IDBDatabaseOpenCursorResult::NewErrorResult(
-            CreateIDBErrorPtr(blink::mojom::IDBException::kUnknownError,
-                              "Dispatcher not connected.", transaction)));
-    return s;
-  }
-
   if (!IsObjectStoreIdAndMaybeIndexIdInMetadata(params->object_store_id,
                                                 params->index_id)) {
     return leveldb::Status::InvalidArgument(
@@ -1295,6 +1263,7 @@
   if (params->task_type == blink::mojom::IDBTaskType::Preemptive)
     transaction->AddPreemptiveEvent();
 
+  Status s;
   std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
   if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
     if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
@@ -1335,7 +1304,7 @@
   mojo::PendingAssociatedRemote<blink::mojom::IDBCursor> pending_remote;
   IndexedDBCursor* cursor = IndexedDBCursor::CreateAndBind(
       std::move(backing_store_cursor), params->cursor_type, params->task_type,
-      *dispatcher_host, transaction->AsWeakPtr(), pending_remote);
+      transaction->AsWeakPtr(), pending_remote);
   transaction->RegisterOpenCursor(cursor);
 
   blink::mojom::IDBValuePtr mojo_value;
@@ -1346,7 +1315,7 @@
   }
 
   if (mojo_value) {
-    dispatcher_host->CreateAllExternalObjects(bucket_locator, external_objects,
+    bucket_context_->CreateAllExternalObjects(external_objects,
                                               &mojo_value->external_objects);
   }
 
@@ -1533,11 +1502,6 @@
     blink::mojom::kIDBMaxMessageSize <= IPC::Channel::kMaximumMessageSize,
     "kIDBMaxMessageSize is bigger than IPC::Channel::kMaximumMessageSize");
 
-size_t IndexedDBDatabase::GetUsableMessageSizeInBytes() const {
-  return blink::mojom::kIDBMaxMessageSize -
-         blink::mojom::kIDBMaxMessageOverhead;
-}
-
 void IndexedDBDatabase::CallUpgradeTransactionStartedForTesting(
     int64_t old_version) {
   connection_coordinator_.OnUpgradeTransactionStarted(old_version);
@@ -1558,14 +1522,13 @@
 std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
     scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
     scoped_refptr<IndexedDBClientStateCheckerWrapper> client_state_checker) {
-  std::unique_ptr<IndexedDBConnection> connection =
-      std::make_unique<IndexedDBConnection>(
-          *bucket_context_, class_factory_, weak_factory_.GetWeakPtr(),
-          base::BindRepeating(&IndexedDBDatabase::VersionChangeIgnored,
-                              weak_factory_.GetWeakPtr()),
-          base::BindOnce(&IndexedDBDatabase::ConnectionClosed,
-                         weak_factory_.GetWeakPtr()),
-          database_callbacks, std::move(client_state_checker));
+  auto connection = std::make_unique<IndexedDBConnection>(
+      *bucket_context_, weak_factory_.GetWeakPtr(),
+      base::BindRepeating(&IndexedDBDatabase::VersionChangeIgnored,
+                          weak_factory_.GetWeakPtr()),
+      base::BindOnce(&IndexedDBDatabase::ConnectionClosed,
+                     weak_factory_.GetWeakPtr()),
+      database_callbacks, std::move(client_state_checker));
   connections_.insert(connection.get());
   return connection;
 }
diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h
index 2e2fe3da..0ae3fff3 100644
--- a/content/browser/indexed_db/indexed_db_database.h
+++ b/content/browser/indexed_db/indexed_db_database.h
@@ -46,7 +46,6 @@
 
 namespace content {
 class IndexedDBBucketContext;
-class IndexedDBClassFactory;
 class IndexedDBConnection;
 class IndexedDBDatabaseCallbacks;
 class IndexedDBTransaction;
@@ -64,6 +63,10 @@
   static const int64_t kInvalidId = 0;
   static const int64_t kMinimumIndexId = 30;
 
+  IndexedDBDatabase(const std::u16string& name,
+                    IndexedDBBucketContext& bucket_context,
+                    const Identifier& unique_identifier);
+
   IndexedDBDatabase(const IndexedDBDatabase&) = delete;
   IndexedDBDatabase& operator=(const IndexedDBDatabase&) = delete;
 
@@ -185,7 +188,6 @@
                                  std::u16string old_name);
 
   leveldb::Status GetOperation(
-      base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
       int64_t object_store_id,
       int64_t index_id,
       std::unique_ptr<blink::IndexedDBKeyRange> key_range,
@@ -194,7 +196,6 @@
       IndexedDBTransaction* transaction);
 
   leveldb::Status GetAllOperation(
-      base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
       int64_t object_store_id,
       int64_t index_id,
       std::unique_ptr<blink::IndexedDBKeyRange> key_range,
@@ -248,7 +249,6 @@
   leveldb::Status OpenCursorOperation(
       std::unique_ptr<OpenCursorOperationParams> params,
       const storage::BucketLocator& bucket_locator,
-      base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
       IndexedDBTransaction* transaction);
 
   leveldb::Status CountOperation(
@@ -299,18 +299,7 @@
   friend class IndexedDBConnectionCoordinator::OpenRequest;
   friend class IndexedDBConnectionCoordinator::DeleteRequest;
 
-  IndexedDBDatabase(const std::u16string& name,
-                    IndexedDBBucketContext& bucket_context,
-                    IndexedDBClassFactory* class_factory,
-                    const Identifier& unique_identifier);
-
-  // May be overridden in tests.
-  virtual size_t GetUsableMessageSizeInBytes() const;
-
  private:
-  friend class MockBrowserTestIndexedDBClassFactory;
-  friend class IndexedDBClassFactory;
-
   FRIEND_TEST_ALL_PREFIXES(IndexedDBDatabaseTest, OpenDeleteClear);
 
   void CallUpgradeTransactionStartedForTesting(int64_t old_version);
@@ -369,8 +358,6 @@
   // The object that owns `this`.
   raw_ref<IndexedDBBucketContext> bucket_context_;
 
-  const raw_ptr<IndexedDBClassFactory> class_factory_;
-
   int64_t transaction_count_ = 0;
 
   list_set<IndexedDBConnection*> connections_;
diff --git a/content/browser/indexed_db/indexed_db_database_callbacks.cc b/content/browser/indexed_db/indexed_db_database_callbacks.cc
index 303715b..ca34662 100644
--- a/content/browser/indexed_db/indexed_db_database_callbacks.cc
+++ b/content/browser/indexed_db/indexed_db_database_callbacks.cc
@@ -10,7 +10,6 @@
 #include "base/task/sequenced_task_runner.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_database_error.h"
-#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc
index 6bf8dce..1c3bde5 100644
--- a/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -83,13 +83,14 @@
 
     bucket_context_ = std::make_unique<IndexedDBBucketContext>(
         storage::BucketInfo(), false, base::DefaultClock::GetInstance(),
-        &IndexedDBClassFactory::Get()->transactional_leveldb_factory(),
         std::make_unique<PartitionedLockManager>(), std::move(delegate),
         std::make_unique<IndexedDBFakeBackingStore>(), quota_manager_proxy_,
-        base::DoNothing());
+        /*io_task_runner=*/base::SequencedTaskRunner::GetCurrentDefault(),
+        /*blob_storage_context=*/mojo::NullRemote(),
+        /*file_system_access_context=*/mojo::NullRemote(), base::DoNothing());
 
-    db_ = IndexedDBClassFactory::Get()->CreateIndexedDBDatabase(
-        u"db", *bucket_context_, IndexedDBDatabase::Identifier());
+    db_ = std::make_unique<IndexedDBDatabase>(u"db", *bucket_context_,
+                                              IndexedDBDatabase::Identifier());
   }
 
   void RunTasksForDatabase(bool async) {
@@ -211,7 +212,6 @@
  public:
   MockFactoryClient()
       : IndexedDBFactoryClient(
-            nullptr,
             mojo::NullAssociatedRemote(),
             base::SingleThreadTaskRunner::GetCurrentDefault()) {}
   ~MockFactoryClient() override = default;
@@ -494,13 +494,14 @@
 
     bucket_context_ = std::make_unique<IndexedDBBucketContext>(
         storage::BucketInfo(), false, base::DefaultClock::GetInstance(),
-        &IndexedDBClassFactory::Get()->transactional_leveldb_factory(),
         std::make_unique<PartitionedLockManager>(), std::move(delegate),
         std::make_unique<IndexedDBFakeBackingStore>(), quota_manager_proxy_,
-        base::DoNothing());
+        /*io_task_runner=*/base::SequencedTaskRunner::GetCurrentDefault(),
+        /*blob_storage_context=*/mojo::NullRemote(),
+        /*file_system_access_context=*/mojo::NullRemote(), base::DoNothing());
 
-    db_ = IndexedDBClassFactory::Get()->CreateIndexedDBDatabase(
-        u"db", *bucket_context_, IndexedDBDatabase::Identifier());
+    db_ = std::make_unique<IndexedDBDatabase>(u"db", *bucket_context_,
+                                              IndexedDBDatabase::Identifier());
 
     callbacks_ = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>();
     const int64_t transaction_id = 1;
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 3ca29e7..8d357db 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -8,168 +8,18 @@
 
 #include "base/files/file_path.h"
 #include "base/functional/bind.h"
-#include "base/memory/raw_ptr.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/process/process.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/task/sequenced_task_runner.h"
-#include "base/task/task_runner.h"
-#include "base/task/thread_pool.h"
-#include "base/time/time.h"
-#include "base/trace_event/base_tracing.h"
-#include "base/uuid.h"
-#include "build/build_config.h"
-#include "components/services/storage/filesystem_proxy_factory.h"
-#include "content/browser/indexed_db/file_stream_reader_to_data_pipe.h"
-#include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
 #include "content/browser/indexed_db/indexed_db_factory.h"
 #include "content/browser/indexed_db/indexed_db_factory_client.h"
 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
 #include "content/browser/indexed_db/transaction_impl.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "net/base/net_errors.h"
-#include "storage/browser/blob/blob_impl.h"
-#include "storage/browser/database/database_util.h"
-#include "storage/browser/file_system/file_stream_reader.h"
-#include "third_party/blink/public/common/storage_key/storage_key.h"
 
 namespace content {
 
-// BlobDataItemReader implementation providing a BlobDataItem -> file adapter.
-class IndexedDBDataItemReader : public storage::mojom::BlobDataItemReader {
- public:
-  IndexedDBDataItemReader(
-      IndexedDBDispatcherHost* host,
-      const base::FilePath& file_path,
-      base::Time expected_modification_time,
-      base::RepeatingClosure release_callback,
-      scoped_refptr<base::TaskRunner> file_task_runner,
-      scoped_refptr<base::TaskRunner> io_task_runner,
-      mojo::PendingReceiver<storage::mojom::BlobDataItemReader>
-          initial_receiver)
-      : host_(host),
-        file_path_(file_path),
-        expected_modification_time_(std::move(expected_modification_time)),
-        release_callback_(std::move(release_callback)),
-        file_task_runner_(std::move(file_task_runner)),
-        io_task_runner_(std::move(io_task_runner)) {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    DCHECK(host);
-    DCHECK(file_task_runner_);
-
-    AddReader(std::move(initial_receiver));
-
-    // Unretained(this) is safe because |this| owns |receivers_|.
-    receivers_.set_disconnect_handler(
-        base::BindRepeating(&IndexedDBDataItemReader::OnClientDisconnected,
-                            base::Unretained(this)));
-  }
-
-  IndexedDBDataItemReader(const IndexedDBDataItemReader&) = delete;
-  IndexedDBDataItemReader& operator=(const IndexedDBDataItemReader&) = delete;
-
-  ~IndexedDBDataItemReader() override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    release_callback_.Run();
-  }
-
-  void AddReader(mojo::PendingReceiver<BlobDataItemReader> receiver) {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    DCHECK(receiver.is_valid());
-
-    receivers_.Add(this, std::move(receiver));
-  }
-
-  void Read(uint64_t offset,
-            uint64_t length,
-            mojo::ScopedDataPipeProducerHandle pipe,
-            ReadCallback callback) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-    auto reader = storage::FileStreamReader::CreateForIndexedDBDataItemReader(
-        file_task_runner_.get(), file_path_, storage::CreateFilesystemProxy(),
-        offset, expected_modification_time_);
-    auto adapter = std::make_unique<FileStreamReaderToDataPipe>(
-        std::move(reader), std::move(pipe));
-    auto* raw_adapter = adapter.get();
-
-    // Have the adapter (owning the reader) be owned by the result callback.
-    auto current_task_runner = base::SequencedTaskRunner::GetCurrentDefault();
-    auto result_callback = base::BindOnce(
-        [](std::unique_ptr<FileStreamReaderToDataPipe> reader,
-           scoped_refptr<base::SequencedTaskRunner> task_runner,
-           ReadCallback callback, int result) {
-          // |callback| is expected to be run on the original sequence
-          // that called this Read function, so post it back.
-          task_runner->PostTask(FROM_HERE,
-                                base::BindOnce(std::move(callback), result));
-        },
-        std::move(adapter), std::move(current_task_runner),
-        std::move(callback));
-
-    // On Windows, all async file IO needs to be done on the io thread.
-    // Do this on all platforms for consistency, even if not necessary on posix.
-    io_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            [](FileStreamReaderToDataPipe* adapter, uint64_t length,
-               base::OnceCallback<void(int)> result_callback) {
-              adapter->Start(std::move(result_callback), length);
-            },
-            // |raw_adapter| is owned by |result_callback|.
-            base::Unretained(raw_adapter), length, std::move(result_callback)));
-  }
-
-  void ReadSideData(ReadSideDataCallback callback) override {
-    // This type should never have side data.
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    std::move(callback).Run(net::ERR_NOT_IMPLEMENTED, mojo_base::BigBuffer());
-  }
-
- private:
-  void OnClientDisconnected() {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    if (!receivers_.empty())
-      return;
-
-    host_->RemoveBoundReaders(file_path_);
-    // |this| is likely deleted at this point.
-  }
-
-  mojo::ReceiverSet<storage::mojom::BlobDataItemReader> receivers_;
-
-  // |this| is owned by |host|, so this raw "client pointer" is safe.
-  raw_ptr<IndexedDBDispatcherHost> host_;
-
-  base::FilePath file_path_;
-  base::Time expected_modification_time_;
-  base::RepeatingClosure release_callback_;
-
-  // There are a lot of task runners in this class:
-  // * IndexedDBDataItemReader itself needs to run on the IDB sequence.
-  //   This is because releasing a ref needs to be done synchronously when
-  //   the mojo interface connection is broken to avoid racing with adding
-  //   refs, and the active blob registry is on the IDB sequence.
-  // * LocalFileStreamReader wants its own |file_task_runner_| to run
-  //   various asynchronous file operations on.
-  // * net::FileStream (used by LocalFileStreamReader) needs to be run
-  //   on an IO thread for asynchronous file operations (on Windows), which
-  //   is done by passing in an |io_task_runner| to do this.
-  scoped_refptr<base::TaskRunner> file_task_runner_;
-  scoped_refptr<base::TaskRunner> io_task_runner_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-};
-
 IndexedDBDispatcherHost::IndexedDBDispatcherHost(
-    IndexedDBContextImpl* indexed_db_context,
-    scoped_refptr<base::TaskRunner> io_task_runner)
-    : indexed_db_context_(indexed_db_context),
-      io_task_runner_(std::move(io_task_runner)),
-      file_task_runner_(base::ThreadPool::CreateTaskRunner(
-          {base::MayBlock(), base::TaskPriority::USER_VISIBLE})) {
+    IndexedDBContextImpl* indexed_db_context)
+    : indexed_db_context_(indexed_db_context) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
   DCHECK(indexed_db_context_);
 }
@@ -201,18 +51,6 @@
   receivers_.Add(this, std::move(pending_receiver), std::move(context));
 }
 
-storage::mojom::BlobStorageContext*
-IndexedDBDispatcherHost::mojo_blob_storage_context() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return indexed_db_context_->blob_storage_context();
-}
-
-storage::mojom::FileSystemAccessContext*
-IndexedDBDispatcherHost::file_system_access_context() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return indexed_db_context_->file_system_access_context();
-}
-
 void IndexedDBDispatcherHost::GetDatabaseInfo(
     GetDatabaseInfoCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -251,15 +89,14 @@
 
   // Return error if failed to retrieve bucket from the QuotaManager.
   if (!bucket) {
-    IndexedDBFactoryClient(AsWeakPtr(), std::move(pending_factory_client),
-                           IDBTaskRunner())
+    IndexedDBFactoryClient(std::move(pending_factory_client), IDBTaskRunner())
         .OnError(IndexedDBDatabaseError(
             blink::mojom::IDBException::kUnknownError, u"Internal error."));
     return;
   }
 
   auto callbacks = std::make_unique<IndexedDBFactoryClient>(
-      AsWeakPtr(), std::move(pending_factory_client), IDBTaskRunner());
+      std::move(pending_factory_client), IDBTaskRunner());
   auto database_callbacks = base::MakeRefCounted<IndexedDBDatabaseCallbacks>(
       indexed_db_context_, std::move(database_callbacks_remote),
       IDBTaskRunner());
@@ -294,126 +131,22 @@
 
   // Return error if failed to retrieve bucket from the QuotaManager.
   if (!bucket) {
-    IndexedDBFactoryClient(AsWeakPtr(), std::move(pending_factory_client),
-                           IDBTaskRunner())
+    IndexedDBFactoryClient(std::move(pending_factory_client), IDBTaskRunner())
         .OnError(IndexedDBDatabaseError(
             blink::mojom::IDBException::kUnknownError, u"Internal error."));
     return;
   }
 
   auto factory_client = std::make_unique<IndexedDBFactoryClient>(
-      AsWeakPtr(), std::move(pending_factory_client), IDBTaskRunner());
+      std::move(pending_factory_client), IDBTaskRunner());
   base::FilePath indexed_db_path =
       indexed_db_context_->GetDataPath(bucket->ToBucketLocator());
   indexed_db_context_->GetIDBFactory()->DeleteDatabase(
       name, std::move(factory_client), *bucket, indexed_db_path, force_close);
 }
 
-void IndexedDBDispatcherHost::BindFileReader(
-    const base::FilePath& path,
-    base::Time expected_modification_time,
-    base::RepeatingClosure release_callback,
-    mojo::PendingReceiver<storage::mojom::BlobDataItemReader> receiver) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(receiver.is_valid());
-  DCHECK(file_task_runner_);
-
-  auto itr = file_reader_map_.find(path);
-  if (itr != file_reader_map_.end()) {
-    itr->second->AddReader(std::move(receiver));
-    return;
-  }
-
-  auto reader = std::make_unique<IndexedDBDataItemReader>(
-      this, path, expected_modification_time, std::move(release_callback),
-      file_task_runner_, io_task_runner_, std::move(receiver));
-  file_reader_map_.insert({path, std::move(reader)});
-}
-
-void IndexedDBDispatcherHost::RemoveBoundReaders(const base::FilePath& path) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  file_reader_map_.erase(path);
-}
-
-void IndexedDBDispatcherHost::CreateAllExternalObjects(
-    const storage::BucketLocator& bucket_locator,
-    const std::vector<IndexedDBExternalObject>& objects,
-    std::vector<blink::mojom::IDBExternalObjectPtr>* mojo_objects) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  TRACE_EVENT0("IndexedDB",
-               "IndexedDBDispatcherHost::CreateAllExternalObjects");
-
-  DCHECK_EQ(objects.size(), mojo_objects->size());
-  if (objects.empty())
-    return;
-
-  for (size_t i = 0; i < objects.size(); ++i) {
-    auto& blob_info = objects[i];
-    auto& mojo_object = (*mojo_objects)[i];
-
-    switch (blob_info.object_type()) {
-      case IndexedDBExternalObject::ObjectType::kBlob:
-      case IndexedDBExternalObject::ObjectType::kFile: {
-        DCHECK(mojo_object->is_blob_or_file());
-        auto& output_info = mojo_object->get_blob_or_file();
-
-        auto receiver = output_info->blob.InitWithNewPipeAndPassReceiver();
-        if (blob_info.is_remote_valid()) {
-          output_info->uuid = blob_info.uuid();
-          blob_info.Clone(std::move(receiver));
-          continue;
-        }
-
-        auto element = storage::mojom::BlobDataItem::New();
-        // TODO(enne): do we have to handle unknown size here??
-        element->size = blob_info.size();
-        element->side_data_size = 0;
-        element->content_type = base::UTF16ToUTF8(blob_info.type());
-        element->type = storage::mojom::BlobDataItemType::kIndexedDB;
-
-        base::Time last_modified;
-        // Android doesn't seem to consistently be able to set file modification
-        // times. https://crbug.com/1045488
-#if !BUILDFLAG(IS_ANDROID)
-        last_modified = blob_info.last_modified();
-#endif
-        BindFileReader(blob_info.indexed_db_file_path(), last_modified,
-                       blob_info.release_callback(),
-                       element->reader.InitWithNewPipeAndPassReceiver());
-
-        // Write results to output_info.
-        output_info->uuid = base::Uuid::GenerateRandomV4().AsLowercaseString();
-
-        mojo_blob_storage_context()->RegisterFromDataItem(
-            std::move(receiver), output_info->uuid, std::move(element));
-        break;
-      }
-      case IndexedDBExternalObject::ObjectType::kFileSystemAccessHandle: {
-        DCHECK(mojo_object->is_file_system_access_token());
-
-        mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken>
-            mojo_token;
-
-        if (blob_info.is_file_system_access_remote_valid()) {
-          blob_info.file_system_access_token_remote()->Clone(
-              mojo_token.InitWithNewPipeAndPassReceiver());
-        } else {
-          DCHECK(!blob_info.serialized_file_system_access_handle().empty());
-          file_system_access_context()->DeserializeHandle(
-              bucket_locator.storage_key,
-              blob_info.serialized_file_system_access_handle(),
-              mojo_token.InitWithNewPipeAndPassReceiver());
-        }
-        mojo_object->get_file_system_access_token() = std::move(mojo_token);
-        break;
-      }
-    }
-  }
-}
-
 base::SequencedTaskRunner* IndexedDBDispatcherHost::IDBTaskRunner() const {
-  return indexed_db_context_->IDBTaskRunner();
+  return indexed_db_context_->IDBTaskRunner().get();
 }
 
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h
index 844dfb2c..efb96b9f 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -18,24 +18,20 @@
 #include "components/services/storage/privileged/mojom/indexed_db_client_state_checker.mojom.h"
 #include "components/services/storage/public/cpp/buckets/bucket_info.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
-#include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h"
-#include "components/services/storage/public/mojom/file_system_access_context.mojom-forward.h"
 #include "content/browser/indexed_db/indexed_db_client_state_checker_wrapper.h"
-#include "content/browser/indexed_db/indexed_db_external_object.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/unique_associated_receiver_set.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 
 namespace base {
 class SequencedTaskRunner;
-class TaskRunner;
 }  // namespace base
 
 namespace content {
 class IndexedDBContextImpl;
-class IndexedDBDataItemReader;
 
 // All calls but the constructor (including destruction) must
 // happen on the IDB sequenced task runner.
@@ -65,9 +61,7 @@
     scoped_refptr<IndexedDBClientStateCheckerWrapper> client_state_checker;
   };
 
-  explicit IndexedDBDispatcherHost(
-      IndexedDBContextImpl* indexed_db_context,
-      scoped_refptr<base::TaskRunner> io_task_runner);
+  explicit IndexedDBDispatcherHost(IndexedDBContextImpl* indexed_db_context);
 
   IndexedDBDispatcherHost(const IndexedDBDispatcherHost&) = delete;
   IndexedDBDispatcherHost& operator=(const IndexedDBDispatcherHost&) = delete;
@@ -86,28 +80,9 @@
     return weak_factory_.GetWeakPtr();
   }
 
-  // Bind this receiver to read from this given file.
-  void BindFileReader(
-      const base::FilePath& path,
-      base::Time expected_modification_time,
-      base::RepeatingClosure release_callback,
-      mojo::PendingReceiver<storage::mojom::BlobDataItemReader> receiver);
-  // Removes all readers for this file path.
-  void RemoveBoundReaders(const base::FilePath& path);
-
-  // Create external objects from |objects| and store the results in
-  // |mojo_objects|.  |mojo_objects| must be the same length as |objects|.
-  void CreateAllExternalObjects(
-      const storage::BucketLocator& bucket_locator,
-      const std::vector<IndexedDBExternalObject>& objects,
-      std::vector<blink::mojom::IDBExternalObjectPtr>* mojo_objects);
-
  private:
   friend class IndexedDBDispatcherHostTest;
 
-  storage::mojom::BlobStorageContext* mojo_blob_storage_context();
-  storage::mojom::FileSystemAccessContext* file_system_access_context();
-
   // blink::mojom::IDBFactory implementation:
   void GetDatabaseInfo(GetDatabaseInfoCallback callback) override;
   void Open(mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient>
@@ -131,18 +106,10 @@
   // rewriter to see that |.get()| needs to be appended.
   RAW_PTR_EXCLUSION IndexedDBContextImpl* indexed_db_context_;
 
-  // Shared task runner used for async I/O while reading blob files.
-  const scoped_refptr<base::TaskRunner> io_task_runner_;
-  // Shared task runner used to read blob files on.
-  const scoped_refptr<base::TaskRunner> file_task_runner_;
-
   mojo::ReceiverSet<blink::mojom::IDBFactory,
                     IndexedDBDispatcherHost::ReceiverContext>
       receivers_;
 
-  std::map<base::FilePath, std::unique_ptr<IndexedDBDataItemReader>>
-      file_reader_map_;
-
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<IndexedDBDispatcherHost> weak_factory_{this};
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
index 848047f..c084c7b 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -29,7 +29,6 @@
 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
 #include "content/browser/indexed_db/indexed_db_factory.h"
 #include "content/browser/indexed_db/indexed_db_factory_client.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
 #include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h"
 #include "content/browser/indexed_db/mock_mojo_indexed_db_factory_client.h"
diff --git a/content/browser/indexed_db/indexed_db_external_object.cc b/content/browser/indexed_db/indexed_db_external_object.cc
index e84335ce..3f67ad3 100644
--- a/content/browser/indexed_db/indexed_db_external_object.cc
+++ b/content/browser/indexed_db/indexed_db_external_object.cc
@@ -41,7 +41,7 @@
       }
       case ObjectType::kFileSystemAccessHandle:
         // Contents of token will be filled in later by
-        // IndexedDBDispatcherHost::CreateAllExternalObjects.
+        // IndexedDBBucketContext::CreateAllExternalObjects.
         mojo_objects->push_back(
             blink::mojom::IDBExternalObject::NewFileSystemAccessToken(
                 mojo::NullRemote()));
diff --git a/content/browser/indexed_db/indexed_db_external_object.h b/content/browser/indexed_db/indexed_db_external_object.h
index 4256d69..90e22f6 100644
--- a/content/browser/indexed_db/indexed_db_external_object.h
+++ b/content/browser/indexed_db/indexed_db_external_object.h
@@ -29,7 +29,7 @@
 
   // Partially converts a list of |objects| to their mojo representation. The
   // mojo representation won't be complete until later
-  // IndexedDBDispatcherHost::CreateAllExternalObjects is also called with the
+  // IndexedDBBucketContext::CreateAllExternalObjects is also called with the
   // same parameters.
   static void ConvertToMojo(
       const std::vector<IndexedDBExternalObject>& objects,
diff --git a/content/browser/indexed_db/indexed_db_factory.cc b/content/browser/indexed_db/indexed_db_factory.cc
index f1fca22..7e85ad7 100644
--- a/content/browser/indexed_db/indexed_db_factory.cc
+++ b/content/browser/indexed_db/indexed_db_factory.cc
@@ -45,6 +45,7 @@
 #include "content/browser/indexed_db/indexed_db_bucket_context.h"
 #include "content/browser/indexed_db/indexed_db_bucket_context_handle.h"
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
+#include "content/browser/indexed_db/indexed_db_client_state_checker_wrapper.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_data_format_version.h"
@@ -54,6 +55,7 @@
 #include "content/browser/indexed_db/indexed_db_reporting.h"
 #include "content/browser/indexed_db/indexed_db_task_helper.h"
 #include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h"
+#include "content/browser/indexed_db/indexed_db_transaction.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 #include "third_party/leveldatabase/env_chromium.h"
 
@@ -170,13 +172,10 @@
 
 IndexedDBFactory::IndexedDBFactory(
     IndexedDBContextImpl* context,
-    IndexedDBClassFactory* indexed_db_class_factory,
     base::Clock* clock)
     : context_(context),
-      class_factory_(indexed_db_class_factory),
       clock_(clock) {
   DCHECK(context);
-  DCHECK(indexed_db_class_factory);
   DCHECK(clock);
   base::trace_event::MemoryDumpManager::GetInstance()
       ->RegisterDumpProviderWithSequencedTaskRunner(
@@ -269,18 +268,9 @@
                                        std::move(client_state_checker));
     return;
   }
-  std::unique_ptr<IndexedDBDatabase> database =
-      class_factory_->CreateIndexedDBDatabase(
-          name, *bucket_context_handle.bucket_context(),
-          std::move(unique_identifier));
-  if (!database.get()) {
-    error = IndexedDBDatabaseError(
-        blink::mojom::IDBException::kUnknownError,
-        u"Internal error creating database backend for indexedDB.open.");
-    connection->factory_client->OnError(error);
-    return;
-  }
-
+  auto database = std::make_unique<IndexedDBDatabase>(
+      name, *bucket_context_handle.bucket_context(),
+      std::move(unique_identifier));
   // The database must be added before the schedule call, as the
   // CreateDatabaseDeleteClosure can be called synchronously.
   auto* database_ptr = database.get();
@@ -351,17 +341,9 @@
     return;
   }
 
-  std::unique_ptr<IndexedDBDatabase> database =
-      class_factory_->CreateIndexedDBDatabase(
-          name, *bucket_context_handle.bucket_context(), unique_identifier);
-  if (!database.get()) {
-    error = IndexedDBDatabaseError(blink::mojom::IDBException::kUnknownError,
-                                   u"Internal error creating database backend "
-                                   u"for indexedDB.deleteDatabase.");
-    factory_client->OnError(error);
-    return;
-  }
-
+  auto database = std::make_unique<IndexedDBDatabase>(
+      name, *bucket_context_handle.bucket_context(),
+      std::move(unique_identifier));
   base::WeakPtr<IndexedDBDatabase> database_ptr =
       bucket_context_handle->AddDatabase(name, std::move(database))
           ->AsWeakPtr();
@@ -412,7 +394,7 @@
   const base::FilePath file_path =
       path_base.Append(indexed_db::GetLevelDBFileName(bucket_locator));
   leveldb::Status s =
-      class_factory_->leveldb_factory().DestroyLevelDB(file_path);
+      IndexedDBClassFactory::Get()->leveldb_factory().DestroyLevelDB(file_path);
   DLOG_IF(ERROR, !s.ok()) << "Unable to delete backing store: " << s.ToString();
 }
 
@@ -751,12 +733,27 @@
   bucket_delegate.for_each_bucket_context = base::BindRepeating(
       &IndexedDBFactory::ForEachBucketContext, weak_factory_.GetWeakPtr());
 
+  mojo::PendingRemote<storage::mojom::BlobStorageContext> blob_storage_context;
+  // May be null in unit tests.
+  if (context_->blob_storage_context()) {
+    context_->blob_storage_context()->Clone(
+        blob_storage_context.InitWithNewPipeAndPassReceiver());
+  }
+
+  mojo::PendingRemote<storage::mojom::FileSystemAccessContext> fsa_context;
+  // May be null in unit tests.
+  if (context_->file_system_access_context()) {
+    context_->file_system_access_context()->Clone(
+        fsa_context.InitWithNewPipeAndPassReceiver());
+  }
+
   auto bucket_context = std::make_unique<IndexedDBBucketContext>(
       bucket,
       /*persist_for_incognito=*/is_incognito_and_in_memory, clock_,
-      &class_factory_->transactional_leveldb_factory(), std::move(lock_manager),
-      std::move(bucket_delegate), std::move(backing_store),
-      context_->quota_manager_proxy(), for_each_bucket_context_);
+      std::move(lock_manager), std::move(bucket_delegate),
+      std::move(backing_store), context_->quota_manager_proxy(),
+      context_->IOTaskRunner(), std::move(blob_storage_context),
+      std::move(fsa_context), for_each_bucket_context_);
 
   it = bucket_contexts_.emplace(bucket_locator.id, std::move(bucket_context))
            .first;
@@ -767,23 +764,18 @@
 
 std::unique_ptr<IndexedDBBackingStore> IndexedDBFactory::CreateBackingStore(
     IndexedDBBackingStore::Mode backing_store_mode,
-    TransactionalLevelDBFactory* transactional_leveldb_factory,
     const storage::BucketLocator& bucket_locator,
     const base::FilePath& blob_path,
     std::unique_ptr<TransactionalLevelDBDatabase> db,
-    storage::mojom::BlobStorageContext* blob_storage_context,
-    storage::mojom::FileSystemAccessContext* file_system_access_context,
     std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
     IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned,
     IndexedDBBackingStore::ReportOutstandingBlobsCallback
         report_outstanding_blobs,
     scoped_refptr<base::SequencedTaskRunner> idb_task_runner) {
   return std::make_unique<IndexedDBBackingStore>(
-      backing_store_mode, transactional_leveldb_factory, bucket_locator,
-      blob_path, std::move(db), blob_storage_context,
-      file_system_access_context, std::move(filesystem_proxy),
-      std::move(blob_files_cleaned), std::move(report_outstanding_blobs),
-      std::move(idb_task_runner));
+      backing_store_mode, bucket_locator, blob_path, std::move(db),
+      std::move(filesystem_proxy), std::move(blob_files_cleaned),
+      std::move(report_outstanding_blobs), std::move(idb_task_runner));
 }
 std::tuple<std::unique_ptr<IndexedDBBackingStore>,
            leveldb::Status,
@@ -830,7 +822,8 @@
           {"IndexedDB (database was corrupt): ", corruption_message});
       // This is a special case where we want to make sure the database is
       // deleted, so we try to delete again.
-      status = class_factory_->leveldb_factory().DestroyLevelDB(database_path);
+      status = IndexedDBClassFactory::Get()->leveldb_factory().DestroyLevelDB(
+          database_path);
 
       if (UNLIKELY(!status.ok())) {
         LOG(ERROR) << "Unable to delete backing store: " << status.ToString();
@@ -848,7 +841,7 @@
     size_t write_buffer_size = leveldb_env::WriteBufferSize(
         base::SysInfo::AmountOfTotalDiskSpace(database_path));
     std::tie(database_state, status, is_disk_full) =
-        class_factory_->leveldb_factory().OpenLevelDBState(
+        IndexedDBClassFactory::Get()->leveldb_factory().OpenLevelDBState(
             database_path, create_if_missing, write_buffer_size);
     if (UNLIKELY(!status.ok())) {
       if (!status.IsNotFound()) {
@@ -876,10 +869,12 @@
 
   // Create the TransactionalLevelDBDatabase wrapper.
   std::unique_ptr<TransactionalLevelDBDatabase> database =
-      class_factory_->transactional_leveldb_factory().CreateLevelDBDatabase(
-          std::move(database_state), std::move(scopes),
-          context_->IDBTaskRunner(),
-          TransactionalLevelDBDatabase::kDefaultMaxOpenIteratorsPerDatabase);
+      IndexedDBClassFactory::Get()
+          ->transactional_leveldb_factory()
+          .CreateLevelDBDatabase(std::move(database_state), std::move(scopes),
+                                 context_->IDBTaskRunner(),
+                                 TransactionalLevelDBDatabase::
+                                     kDefaultMaxOpenIteratorsPerDatabase);
 
   bool are_schemas_known = false;
   std::tie(are_schemas_known, status) = AreSchemasKnown(database.get());
@@ -908,9 +903,7 @@
       is_incognito_and_in_memory ? IndexedDBBackingStore::Mode::kInMemory
                                  : IndexedDBBackingStore::Mode::kOnDisk;
   std::unique_ptr<IndexedDBBackingStore> backing_store = CreateBackingStore(
-      backing_store_mode, &class_factory_->transactional_leveldb_factory(),
-      bucket_locator, blob_path, std::move(database),
-      context_->blob_storage_context(), context_->file_system_access_context(),
+      backing_store_mode, bucket_locator, blob_path, std::move(database),
       std::move(filesystem_proxy),
       base::BindRepeating(&IndexedDBFactory::BlobFilesCleaned,
                           weak_factory_.GetWeakPtr(), bucket_locator),
diff --git a/content/browser/indexed_db/indexed_db_factory.h b/content/browser/indexed_db/indexed_db_factory.h
index 7b1ee877..c57dec52 100644
--- a/content/browser/indexed_db/indexed_db_factory.h
+++ b/content/browser/indexed_db/indexed_db_factory.h
@@ -47,16 +47,14 @@
 
 namespace content {
 class IndexedDBBucketContextHandle;
-class IndexedDBClassFactory;
+class IndexedDBClientStateCheckerWrapper;
 class IndexedDBContextImpl;
 class IndexedDBDatabase;
-class TransactionalLevelDBFactory;
 class TransactionalLevelDBDatabase;
 
 class CONTENT_EXPORT IndexedDBFactory : base::trace_event::MemoryDumpProvider {
  public:
   IndexedDBFactory(IndexedDBContextImpl* context,
-                   IndexedDBClassFactory* indexed_db_class_factory,
                    base::Clock* clock);
 
   IndexedDBFactory(const IndexedDBFactory&) = delete;
@@ -142,12 +140,9 @@
   // Used by unittests to allow subclassing of IndexedDBBackingStore.
   virtual std::unique_ptr<IndexedDBBackingStore> CreateBackingStore(
       IndexedDBBackingStore::Mode backing_store_mode,
-      TransactionalLevelDBFactory* leveldb_factory,
       const storage::BucketLocator& bucket_locator,
       const base::FilePath& blob_path,
       std::unique_ptr<TransactionalLevelDBDatabase> db,
-      storage::mojom::BlobStorageContext* blob_storage_context,
-      storage::mojom::FileSystemAccessContext* file_system_access_context,
       std::unique_ptr<storage::FilesystemProxy> filesystem_proxy,
       IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned,
       IndexedDBBackingStore::ReportOutstandingBlobsCallback
@@ -209,7 +204,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
   // Raw pointer is safe because IndexedDBContextImpl owns this object.
   raw_ptr<IndexedDBContextImpl> context_;
-  const raw_ptr<IndexedDBClassFactory> class_factory_;
   const raw_ptr<base::Clock> clock_;
 
   IndexedDBBucketContext::InstanceClosure for_each_bucket_context_;
diff --git a/content/browser/indexed_db/indexed_db_factory_client.cc b/content/browser/indexed_db/indexed_db_factory_client.cc
index 4cabb01..6442b51 100644
--- a/content/browser/indexed_db/indexed_db_factory_client.cc
+++ b/content/browser/indexed_db/indexed_db_factory_client.cc
@@ -84,12 +84,10 @@
 }  // namespace
 
 IndexedDBFactoryClient::IndexedDBFactoryClient(
-    base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
     mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient>
         pending_client,
     scoped_refptr<base::SequencedTaskRunner> idb_runner)
     : data_loss_(blink::mojom::IDBDataLoss::None),
-      dispatcher_host_(std::move(dispatcher_host)),
       idb_runner_(std::move(idb_runner)) {
   DCHECK(idb_runner_->RunsTasksInCurrentSequence());
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -114,10 +112,6 @@
   if (!remote_) {
     return;
   }
-  if (!dispatcher_host_) {
-    OnConnectionError();
-    return;
-  }
   remote_->Error(error.code(), error.message());
   complete_ = true;
 }
@@ -132,10 +126,6 @@
 
   sent_blocked_ = true;
 
-  if (!dispatcher_host_) {
-    OnConnectionError();
-    return;
-  }
   if (remote_) {
     remote_->Blocked(existing_version);
   }
@@ -158,14 +148,9 @@
   if (!remote_) {
     return;
   }
-  if (!dispatcher_host_) {
-    OnConnectionError();
-    return;
-  }
 
   mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending =
-      DatabaseImpl::CreateAndBind(std::move(wrapper.connection_),
-                                  dispatcher_host_.get());
+      DatabaseImpl::CreateAndBind(std::move(wrapper.connection_));
   remote_->UpgradeNeeded(std::move(pending), old_version, data_loss_info.status,
                          data_loss_info.message, metadata);
 }
@@ -189,15 +174,11 @@
   if (!remote_) {
     return;
   }
-  if (!dispatcher_host_) {
-    OnConnectionError();
-    return;
-  }
 
   mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_remote;
   if (wrapper.connection_) {
-    pending_remote = DatabaseImpl::CreateAndBind(std::move(wrapper.connection_),
-                                                 dispatcher_host_.get());
+    pending_remote =
+        DatabaseImpl::CreateAndBind(std::move(wrapper.connection_));
   }
   remote_->OpenSuccess(std::move(pending_remote), metadata);
   complete_ = true;
@@ -210,10 +191,6 @@
   if (!remote_) {
     return;
   }
-  if (!dispatcher_host_) {
-    OnConnectionError();
-    return;
-  }
   remote_->DeleteSuccess(old_version);
   complete_ = true;
 }
@@ -221,7 +198,6 @@
 void IndexedDBFactoryClient::OnConnectionError() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   remote_.reset();
-  dispatcher_host_ = nullptr;
 }
 
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_factory_client.h b/content/browser/indexed_db/indexed_db_factory_client.h
index 9d321fe..814fe014 100644
--- a/content/browser/indexed_db/indexed_db_factory_client.h
+++ b/content/browser/indexed_db/indexed_db_factory_client.h
@@ -14,7 +14,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "content/browser/indexed_db/indexed_db_database_error.h"
-#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
@@ -40,7 +39,6 @@
 class CONTENT_EXPORT IndexedDBFactoryClient {
  public:
   IndexedDBFactoryClient(
-      base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
       mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient>
           pending_client,
       scoped_refptr<base::SequencedTaskRunner> idb_runner);
@@ -84,7 +82,6 @@
   // The "blocked" event should be sent at most once per request.
   bool sent_blocked_ = false;
 
-  base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host_;
   scoped_refptr<base::SequencedTaskRunner> idb_runner_;
   mojo::AssociatedRemote<blink::mojom::IDBFactoryClient> remote_;
 
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 7431a2a..24894e5 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -36,7 +36,6 @@
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_data_format_version.h"
 #include "content/browser/indexed_db/indexed_db_factory.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
 #include "content/browser/indexed_db/indexed_db_transaction.h"
 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
@@ -1036,8 +1035,7 @@
 class LookingForQuotaErrorMockFactoryClient : public IndexedDBFactoryClient {
  public:
   LookingForQuotaErrorMockFactoryClient()
-      : IndexedDBFactoryClient(nullptr,
-                               mojo::NullAssociatedRemote(),
+      : IndexedDBFactoryClient(mojo::NullAssociatedRemote(),
                                base::SequencedTaskRunner::GetCurrentDefault()) {
   }
   ~LookingForQuotaErrorMockFactoryClient() override = default;
@@ -1058,8 +1056,7 @@
 };
 
 TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) {
-  FakeLevelDBFactory fake_ldb_factory(
-      IndexedDBClassFactory::GetLevelDBOptions(), "indexed-db");
+  FakeLevelDBFactory fake_ldb_factory({}, "indexed-db");
   fake_ldb_factory.EnqueueNextOpenLevelDBStateResult(
       nullptr, leveldb::Status::IOError("Disk is full."), true);
   SetUpContextWithFactories(&fake_ldb_factory,
@@ -1069,7 +1066,8 @@
       std::make_unique<LookingForQuotaErrorMockFactoryClient>();
   auto dummy_database_callbacks =
       base::MakeRefCounted<IndexedDBDatabaseCallbacks>(
-          nullptr, mojo::NullAssociatedRemote(), context()->IDBTaskRunner());
+          nullptr, mojo::NullAssociatedRemote(),
+          context()->IDBTaskRunner().get());
   const blink::StorageKey storage_key =
       blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
   auto bucket_locator = storage::BucketLocator();
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/content/browser/indexed_db/indexed_db_fake_backing_store.cc
index e197588..1864be3 100644
--- a/content/browser/indexed_db/indexed_db_fake_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -13,7 +13,6 @@
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 
 namespace content {
@@ -23,11 +22,6 @@
 using blink::IndexedDBKeyRange;
 using leveldb::Status;
 
-TransactionalLevelDBFactory* GetTransactionalLevelDBFactory() {
-  static base::NoDestructor<DefaultTransactionalLevelDBFactory> factory;
-  return factory.get();
-}
-
 const storage::BucketLocator GetBucketLocator(blink::StorageKey storage_key) {
   auto bucket_locator = storage::BucketLocator();
   bucket_locator.storage_key = storage_key;
@@ -38,14 +32,11 @@
 
 IndexedDBFakeBackingStore::IndexedDBFakeBackingStore()
     : IndexedDBBackingStore(IndexedDBBackingStore::Mode::kInMemory,
-                            GetTransactionalLevelDBFactory(),
                             storage::BucketLocator(GetBucketLocator(
                                 blink::StorageKey::CreateFromStringForTesting(
                                     "http://localhost:81"))),
                             base::FilePath(),
                             std::unique_ptr<TransactionalLevelDBDatabase>(),
-                            /*blob_storage_context=*/nullptr,
-                            /*file_system_access_context=*/nullptr,
                             std::make_unique<storage::FilesystemProxy>(
                                 storage::FilesystemProxy::UNRESTRICTED,
                                 base::FilePath()),
@@ -57,14 +48,11 @@
     ReportOutstandingBlobsCallback report_outstanding_blobs,
     scoped_refptr<base::SequencedTaskRunner> task_runner)
     : IndexedDBBackingStore(IndexedDBBackingStore::Mode::kOnDisk,
-                            GetTransactionalLevelDBFactory(),
                             storage::BucketLocator(GetBucketLocator(
                                 blink::StorageKey::CreateFromStringForTesting(
                                     "http://localhost:81"))),
                             base::FilePath(),
                             std::unique_ptr<TransactionalLevelDBDatabase>(),
-                            /*blob_storage_context=*/nullptr,
-                            /*file_system_access_context=*/nullptr,
                             std::make_unique<storage::FilesystemProxy>(
                                 storage::FilesystemProxy::UNRESTRICTED,
                                 base::FilePath()),
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index 01365ab7..0af4a3b 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -236,46 +236,69 @@
   into->insert(into->end(), p, p + sizeof(value));
 }
 
-void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
+// Return value is true iff successful.
+[[nodiscard]] bool EncodeIDBKeyRecursively(const IndexedDBKey& value,
+                                           std::string* into,
+                                           size_t recursion_level) {
+  // The recursion level is enforced in the renderer (in V8). If this check
+  // fails, it suggests a compromised renderer.
+  if (recursion_level > IndexedDBKey::kMaximumDepth) {
+    return false;
+  }
+
   size_t previous_size = into->size();
   switch (value.type()) {
     case blink::mojom::IDBKeyType::Array: {
       EncodeByte(kIndexedDBKeyArrayTypeByte, into);
       size_t length = value.array().size();
       EncodeVarInt(length, into);
-      for (size_t i = 0; i < length; ++i)
-        EncodeIDBKey(value.array()[i], into);
+      for (size_t i = 0; i < length; ++i) {
+        if (!EncodeIDBKeyRecursively(value.array()[i], into,
+                                     1 + recursion_level)) {
+          return false;
+        }
+      }
       DCHECK_GT(into->size(), previous_size);
-      return;
+      return true;
     }
     case blink::mojom::IDBKeyType::Binary:
       EncodeByte(kIndexedDBKeyBinaryTypeByte, into);
       EncodeBinary(value.binary(), into);
       DCHECK_GT(into->size(), previous_size);
-      return;
+      return true;
     case blink::mojom::IDBKeyType::String:
       EncodeByte(kIndexedDBKeyStringTypeByte, into);
       EncodeStringWithLength(value.string(), into);
       DCHECK_GT(into->size(), previous_size);
-      return;
+      return true;
     case blink::mojom::IDBKeyType::Date:
       EncodeByte(kIndexedDBKeyDateTypeByte, into);
       EncodeDouble(value.date(), into);
       DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
-      return;
+      return true;
     case blink::mojom::IDBKeyType::Number:
       EncodeByte(kIndexedDBKeyNumberTypeByte, into);
       EncodeDouble(value.number(), into);
       DCHECK_EQ(9u, static_cast<size_t>(into->size() - previous_size));
-      return;
+      return true;
     case blink::mojom::IDBKeyType::None:
     case blink::mojom::IDBKeyType::Invalid:
     case blink::mojom::IDBKeyType::Min:
     default:
-      NOTREACHED_NORETURN();
+      return false;
   }
 }
 
+// This function must be a thin wrapper around `MaybeEncodeIDBKey` to ensure
+// comprehensive test coverage.
+void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
+  CHECK(MaybeEncodeIDBKey(value, into));
+}
+
+bool MaybeEncodeIDBKey(const IndexedDBKey& value, std::string* into) {
+  return EncodeIDBKeyRecursively(value, into, 0);
+}
+
 void EncodeSortableIDBKey(const IndexedDBKey& value, std::string* into) {
   size_t previous_size = into->size();
   switch (value.type()) {
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.h b/content/browser/indexed_db/indexed_db_leveldb_coding.h
index 448dfe5c..d3683c9d 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -56,8 +56,15 @@
 CONTENT_EXPORT void EncodeBinary(base::span<const uint8_t> value,
                                  std::string* into);
 CONTENT_EXPORT void EncodeDouble(double value, std::string* into);
+// This version will CHECK if encoding fails. This is generally preferred to
+// handling an error.
 CONTENT_EXPORT void EncodeIDBKey(const blink::IndexedDBKey& value,
                                  std::string* into);
+// This version will return `true` on success. It exists so tests can run
+// without crashing.
+[[nodiscard]] CONTENT_EXPORT bool MaybeEncodeIDBKey(
+    const blink::IndexedDBKey& value,
+    std::string* into);
 // This function creates a byte stream that can be directly compared to other
 // byte streams on a byte-by-byte basis and retain semantic ordering. This
 // enables the value to be stored as a SQLite blob without a specialized
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding_encodeidbkey_fuzzer.cc b/content/browser/indexed_db/indexed_db_leveldb_coding_encodeidbkey_fuzzer.cc
index 21366d7..eee7b3a 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding_encodeidbkey_fuzzer.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding_encodeidbkey_fuzzer.cc
@@ -46,10 +46,19 @@
 // Parse |fuzzed_data| to create an IndexedDBKey. This method takes uses the
 // first byte to determine the type of key to create. The remaining bytes in
 // |fuzzed_data| will be consumed differently depending on the type of key.
-IndexedDBKey CreateKey(FuzzedDataProvider* fuzzed_data) {
-  // If there is no more data to use, return a |None| type key.
-  if (fuzzed_data->remaining_bytes() < 1)
-    return IndexedDBKey(IDBKeyType::None);
+IndexedDBKey CreateKey(FuzzedDataProvider* fuzzed_data,
+                       size_t recursion_level = 0) {
+  // Avoid a stack overflow by enforcing this limit. The added buffer here is to
+  // allow this fuzzer to verify behavior for when the generated key is too
+  // deep.
+  if (recursion_level > IndexedDBKey::kMaximumDepth + 5) {
+    fuzzed_data->ConsumeRemainingBytes<uint8_t>();
+  }
+
+  // If there is no more data to use, return a made-up key.
+  if (fuzzed_data->remaining_bytes() < 1) {
+    return IndexedDBKey(1.0, IDBKeyType::Number);
+  }
 
   auto key_type = GetIDBKeyType(fuzzed_data->ConsumeIntegral<uint8_t>());
 
@@ -59,9 +68,9 @@
       // bytes to consume. Then, create the final key to return with this array.
       IndexedDBKey::KeyArray key_array;
       while (fuzzed_data->remaining_bytes() > 0) {
-        key_array.push_back(CreateKey(fuzzed_data));
+        key_array.push_back(CreateKey(fuzzed_data, 1 + recursion_level));
       }
-      return IndexedDBKey(key_array);
+      return IndexedDBKey(std::move(key_array));
     }
     // For keys of type |Binary| and |String|, consume sizeof(size_t) bytes to
     // determine the maximum length of the string to create.
@@ -95,13 +104,12 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   FuzzedDataProvider fuzzed_data(data, size);
   auto key = CreateKey(&fuzzed_data);
-  // We try to catch invalid keys upstream of `EncodeIDBKey`. Should one slip
-  // through, `EncodeIDBKey` will CHECK.
-  if (!key.IsValid()) {
+  // Encoding fails if the key is invalid or if the recursion depth is too much.
+  // In prod, either of these cases will CHECK, but here we fail gracefully.
+  std::string result;
+  if (!content::MaybeEncodeIDBKey(key, &result)) {
     return 0;
   }
-  std::string result;
-  content::EncodeIDBKey(key, &result);
 
   // Ensure that |result| can be decoded back into the original key.
   auto decoded_key = std::make_unique<IndexedDBKey>();
diff --git a/content/browser/indexed_db/indexed_db_leveldb_env.cc b/content/browser/indexed_db/indexed_db_leveldb_env.cc
deleted file mode 100644
index 20aa0a1..0000000
--- a/content/browser/indexed_db/indexed_db_leveldb_env.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
-
-#include "base/no_destructor.h"
-#include "components/services/storage/filesystem_proxy_factory.h"
-
-namespace content {
-
-IndexedDBLevelDBEnv::IndexedDBLevelDBEnv()
-    : ChromiumEnv("LevelDBEnv.IDB", storage::CreateFilesystemProxy()) {}
-
-IndexedDBLevelDBEnv* IndexedDBLevelDBEnv::Get() {
-  static base::NoDestructor<IndexedDBLevelDBEnv> g_leveldb_env;
-  return g_leveldb_env.get();
-}
-
-}  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_leveldb_env.h b/content/browser/indexed_db/indexed_db_leveldb_env.h
deleted file mode 100644
index 8d5004f..0000000
--- a/content/browser/indexed_db/indexed_db_leveldb_env.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_ENV_H_
-#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_ENV_H_
-
-#include <tuple>
-
-#include "base/no_destructor.h"
-#include "content/common/content_export.h"
-#include "third_party/leveldatabase/env_chromium.h"
-
-namespace content {
-
-// The leveldb::Env used by the Indexed DB backend.
-class IndexedDBLevelDBEnv : public leveldb_env::ChromiumEnv {
- public:
-  CONTENT_EXPORT static IndexedDBLevelDBEnv* Get();
-
- private:
-  friend class base::NoDestructor<IndexedDBLevelDBEnv>;
-  IndexedDBLevelDBEnv();
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_ENV_H_
diff --git a/content/browser/indexed_db/indexed_db_leveldb_env_unittest.cc b/content/browser/indexed_db/indexed_db_leveldb_env_unittest.cc
deleted file mode 100644
index e4653396..0000000
--- a/content/browser/indexed_db/indexed_db_leveldb_env_unittest.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
-
-#include <utility>
-
-#include "base/files/file_path.h"
-#include "components/services/storage/indexed_db/leveldb/leveldb_factory.h"
-#include "components/services/storage/indexed_db/leveldb/leveldb_state.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/leveldatabase/env_chromium.h"
-#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
-#include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
-
-namespace content {
-namespace indexed_db {
-namespace {
-leveldb_env::Options GetLevelDBOptions() {
-  static const leveldb::FilterPolicy* kFilterPolicy =
-      leveldb::NewBloomFilterPolicy(10);
-  leveldb_env::Options options;
-  options.comparator = leveldb::BytewiseComparator();
-  options.paranoid_checks = true;
-  options.filter_policy = kFilterPolicy;
-  options.compression = leveldb::kSnappyCompression;
-  options.env = IndexedDBLevelDBEnv::Get();
-  return options;
-}
-
-TEST(IndexedDBLevelDBEnvTest, TestInMemory) {
-  DefaultLevelDBFactory default_factory(GetLevelDBOptions(),
-                                        "test-in-memory-db");
-  scoped_refptr<LevelDBState> state;
-  std::tie(state, std::ignore, std::ignore) = default_factory.OpenLevelDBState(
-      base::FilePath(), leveldb::BytewiseComparator(),
-      /* create_if_missing=*/true);
-  EXPECT_TRUE(state);
-  EXPECT_TRUE(state->in_memory_env());
-}
-
-}  // namespace
-}  // namespace indexed_db
-}  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_leveldb_operations.cc b/content/browser/indexed_db/indexed_db_leveldb_operations.cc
index 18722c8..c0bf23404 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_operations.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_operations.cc
@@ -19,7 +19,6 @@
 #include "components/services/storage/public/cpp/constants.h"
 #include "content/browser/indexed_db/indexed_db_data_format_version.h"
 #include "content/browser/indexed_db/indexed_db_data_loss_info.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "content/browser/indexed_db/indexed_db_reporting.h"
 #include "storage/common/database/database_identifier.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
diff --git a/content/browser/indexed_db/indexed_db_reporting.cc b/content/browser/indexed_db/indexed_db_reporting.cc
index 3a900570..e34f0771 100644
--- a/content/browser/indexed_db/indexed_db_reporting.cc
+++ b/content/browser/indexed_db/indexed_db_reporting.cc
@@ -10,8 +10,8 @@
 #include "base/strings/strcat.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
+#include "third_party/leveldatabase/env_chromium.h"
 
 namespace content {
 namespace indexed_db {
diff --git a/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc b/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
index 31ad1aa..68a93d1 100644
--- a/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
@@ -20,7 +20,6 @@
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h"
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/browser/indexed_db/indexed_db_transaction.cc b/content/browser/indexed_db/indexed_db_transaction.cc
index 1d70138..02e72d6 100644
--- a/content/browser/indexed_db/indexed_db_transaction.cc
+++ b/content/browser/indexed_db/indexed_db_transaction.cc
@@ -50,6 +50,8 @@
 }
 
 const int64_t kInactivityTimeoutPeriodSeconds = 60;
+// Disabled in some tests.
+bool g_inactivity_timeout_enabled = true;
 
 // Used for UMA metrics - do not change values.
 enum UmaIDBException {
@@ -283,6 +285,11 @@
   bucket_context_->delegate().on_tasks_available.Run();
 }
 
+// static
+void IndexedDBTransaction::DisableInactivityTimeoutForTesting() {
+  g_inactivity_timeout_enabled = false;
+}
+
 leveldb::Status IndexedDBTransaction::BlobWriteComplete(
     BlobWriteResult result,
     storage::mojom::WriteBlobToFileResult error) {
@@ -532,8 +539,9 @@
   // block other transactions, so don't time those out.
   if (!HasPendingTasks() &&
       mode_ != blink::mojom::IDBTransactionMode::ReadOnly &&
-      state_ == STARTED) {
-    timeout_timer_.Start(FROM_HERE, GetInactivityTimeout(),
+      state_ == STARTED && g_inactivity_timeout_enabled) {
+    timeout_timer_.Start(FROM_HERE,
+                         base::Seconds(kInactivityTimeoutPeriodSeconds),
                          base::BindOnce(&IndexedDBTransaction::Timeout,
                                         ptr_factory_.GetWeakPtr()));
   }
@@ -541,10 +549,6 @@
   return {RunTasksResult::kNotFinished, leveldb::Status::OK()};
 }
 
-base::TimeDelta IndexedDBTransaction::GetInactivityTimeout() const {
-  return base::Seconds(kInactivityTimeoutPeriodSeconds);
-}
-
 void IndexedDBTransaction::Timeout() {
   leveldb::Status result = Abort(
       IndexedDBDatabaseError(blink::mojom::IDBException::kTimeoutError,
diff --git a/content/browser/indexed_db/indexed_db_transaction.h b/content/browser/indexed_db/indexed_db_transaction.h
index f5e3596f..af81390 100644
--- a/content/browser/indexed_db/indexed_db_transaction.h
+++ b/content/browser/indexed_db/indexed_db_transaction.h
@@ -60,7 +60,16 @@
     FINISHED,    // Either aborted or committed.
   };
 
-  virtual ~IndexedDBTransaction();
+  static void DisableInactivityTimeoutForTesting();
+
+  IndexedDBTransaction(
+      int64_t id,
+      IndexedDBConnection* connection,
+      const std::set<int64_t>& object_store_ids,
+      blink::mojom::IDBTransactionMode mode,
+      IndexedDBBucketContextHandle bucket_context,
+      IndexedDBBackingStore::Transaction* backing_store_transaction);
+  ~IndexedDBTransaction();
 
   // Signals the transaction for commit.
   void SetCommitFlag();
@@ -145,20 +154,6 @@
   // written using ScheduleTask. This is reported to memory dumps.
   base::CheckedNumeric<size_t>& in_flight_memory() { return in_flight_memory_; }
 
- protected:
-  // Test classes may derive, but most creation should be done via
-  // IndexedDBClassFactory.
-  IndexedDBTransaction(
-      int64_t id,
-      IndexedDBConnection* connection,
-      const std::set<int64_t>& object_store_ids,
-      blink::mojom::IDBTransactionMode mode,
-      IndexedDBBucketContextHandle bucket_context,
-      IndexedDBBackingStore::Transaction* backing_store_transaction);
-
-  // May be overridden in tests.
-  virtual base::TimeDelta GetInactivityTimeout() const;
-
  private:
   friend class IndexedDBClassFactory;
   friend class IndexedDBConnection;
@@ -279,6 +274,8 @@
   // This timer is started after requests have been processed. If no subsequent
   // requests are processed before the timer fires, assume the script is
   // unresponsive and abort to unblock the transaction queue.
+  // TODO(crbug.com/1474996): this will not be necessary when each backing store
+  // has its own task runner.
   base::OneShotTimer timeout_timer_;
 
   Diagnostics diagnostics_;
diff --git a/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/content/browser/indexed_db/indexed_db_transaction_unittest.cc
index 93fb2f3d..9b214e0d 100644
--- a/content/browser/indexed_db/indexed_db_transaction_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -85,16 +85,17 @@
 
     bucket_context_ = std::make_unique<IndexedDBBucketContext>(
         storage::BucketInfo(), false, base::DefaultClock::GetInstance(),
-        &IndexedDBClassFactory::Get()->transactional_leveldb_factory(),
         std::make_unique<PartitionedLockManager>(), std::move(delegate),
         std::make_unique<IndexedDBFakeBackingStore>(), quota_manager_->proxy(),
-        base::DoNothing());
+        /*io_task_runner=*/base::SequencedTaskRunner::GetCurrentDefault(),
+        /*blob_storage_context=*/mojo::NullRemote(),
+        /*file_system_access_context=*/mojo::NullRemote(), base::DoNothing());
 
     // DB is created here instead of the constructor to workaround a
     // "peculiarity of C++". More info at
     // https://github.com/google/googletest/blob/main/docs/faq.md#my-compiler-complains-that-a-constructor-or-destructor-cannot-return-a-value-whats-going-on
-    db_ = IndexedDBClassFactory::Get()->CreateIndexedDBDatabase(
-        u"db", *bucket_context_, IndexedDBDatabase::Identifier());
+    db_ = std::make_unique<IndexedDBDatabase>(u"db", *bucket_context_,
+                                              IndexedDBDatabase::Identifier());
   }
 
   TasksAvailableCallback CreateRunTasksCallback() {
@@ -142,8 +143,8 @@
     mojo::PendingAssociatedRemote<storage::mojom::IndexedDBClientStateChecker>
         remote;
     auto connection = std::make_unique<IndexedDBConnection>(
-        *bucket_context_, IndexedDBClassFactory::Get(), db_->AsWeakPtr(),
-        base::DoNothing(), base::DoNothing(),
+        *bucket_context_, db_->AsWeakPtr(), base::DoNothing(),
+        base::DoNothing(),
         base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(),
         base::MakeRefCounted<IndexedDBClientStateCheckerWrapper>(
             std::move(remote)));
diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc
index d2a5acf..798809c 100644
--- a/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -24,12 +24,12 @@
 #include "components/services/storage/privileged/mojom/indexed_db_control.mojom-test-utils.h"
 #include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "content/browser/indexed_db/indexed_db_bucket_context.h"
+#include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_client_state_checker_wrapper.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_factory.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
-#include "content/browser/indexed_db/indexed_db_leveldb_env.h"
 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
 #include "content/browser/indexed_db/mock_indexed_db_factory_client.h"
 #include "content/browser/indexed_db/mock_mojo_indexed_db_factory_client.h"
@@ -43,6 +43,7 @@
 #include "storage/browser/test/mock_special_storage_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
+#include "third_party/leveldatabase/src/include/leveldb/env.h"
 
 using blink::IndexedDBDatabaseMetadata;
 
@@ -74,7 +75,7 @@
 };
 
 std::unique_ptr<LevelDBLock> LockForTesting(const base::FilePath& file_name) {
-  leveldb::Env* env = IndexedDBLevelDBEnv::Get();
+  leveldb::Env* env = IndexedDBClassFactory::GetLevelDBOptions().env;
   base::FilePath lock_path = file_name.AppendASCII("LOCK");
   leveldb::FileLock* lock = nullptr;
   leveldb::Status status = env->LockFile(lock_path.AsUTF8Unsafe(), &lock);
@@ -425,8 +426,7 @@
  public:
   ForceCloseFactoryClient(scoped_refptr<IndexedDBContextImpl> idb_context,
                           const storage::BucketInfo& bucket_info)
-      : IndexedDBFactoryClient(nullptr,
-                               mojo::NullAssociatedRemote(),
+      : IndexedDBFactoryClient(mojo::NullAssociatedRemote(),
                                idb_context->IDBTaskRunner()),
         idb_context_(idb_context),
         bucket_locator_(bucket_info.ToBucketLocator()) {}
diff --git a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
index 734f3ef1..76ec1d4 100644
--- a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
+++ b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
@@ -52,49 +52,6 @@
 
 namespace content {
 
-class IndexedDBTestDatabase : public IndexedDBDatabase {
- public:
-  IndexedDBTestDatabase(const std::u16string& name,
-                        IndexedDBBucketContext& bucket_context,
-                        IndexedDBClassFactory* class_factory,
-                        const Identifier& unique_identifier)
-      : IndexedDBDatabase(name,
-                          bucket_context,
-                          class_factory,
-                          unique_identifier) {}
-  ~IndexedDBTestDatabase() override = default;
-
- protected:
-  size_t GetUsableMessageSizeInBytes() const override {
-    return 10 * 1024 * 1024;  // 10MB
-  }
-};
-
-class IndexedDBTestTransaction : public IndexedDBTransaction {
- public:
-  IndexedDBTestTransaction(
-      int64_t id,
-      IndexedDBConnection* connection,
-      const std::set<int64_t>& scope,
-      blink::mojom::IDBTransactionMode mode,
-      IndexedDBBucketContextHandle bucket_context,
-      IndexedDBBackingStore::Transaction* backing_store_transaction)
-      : IndexedDBTransaction(id,
-                             connection,
-                             scope,
-                             mode,
-                             std::move(bucket_context),
-                             backing_store_transaction) {}
-  ~IndexedDBTestTransaction() override = default;
-
- protected:
-  // Browser tests run under memory/address sanitizers (etc) may trip the
-  // default 60s timeout, so relax it during tests.
-  base::TimeDelta GetInactivityTimeout() const override {
-    return base::Seconds(60 * 60);
-  }
-};
-
 class LevelDBTestDatabase : public TransactionalLevelDBDatabase {
  public:
   LevelDBTestDatabase(scoped_refptr<LevelDBState> level_db_state,
@@ -357,33 +314,6 @@
 MockBrowserTestIndexedDBClassFactory::~MockBrowserTestIndexedDBClassFactory() =
     default;
 
-TransactionalLevelDBFactory&
-MockBrowserTestIndexedDBClassFactory::transactional_leveldb_factory() {
-  return *this;
-}
-
-std::unique_ptr<IndexedDBDatabase>
-MockBrowserTestIndexedDBClassFactory::CreateIndexedDBDatabase(
-    const std::u16string& name,
-    IndexedDBBucketContext& bucket_context,
-    const IndexedDBDatabase::Identifier& unique_identifier) {
-  return std::make_unique<IndexedDBTestDatabase>(name, bucket_context, this,
-                                                 unique_identifier);
-}
-
-std::unique_ptr<IndexedDBTransaction>
-MockBrowserTestIndexedDBClassFactory::CreateIndexedDBTransaction(
-    int64_t id,
-    IndexedDBConnection* connection,
-    const std::set<int64_t>& scope,
-    blink::mojom::IDBTransactionMode mode,
-    IndexedDBBucketContextHandle bucket_context,
-    IndexedDBBackingStore::Transaction* backing_store_transaction) {
-  return std::make_unique<IndexedDBTestTransaction>(id, connection, scope, mode,
-                                                    std::move(bucket_context),
-                                                    backing_store_transaction);
-}
-
 std::unique_ptr<TransactionalLevelDBDatabase>
 MockBrowserTestIndexedDBClassFactory::CreateLevelDBDatabase(
     scoped_refptr<LevelDBState> state,
@@ -399,11 +329,10 @@
         std::move(state), std::move(scopes), this, std::move(task_runner),
         max_open_iterators, failure_method_,
         fail_on_call_num_[FailClass::LEVELDB_DATABASE]);
-  } else {
-    return DefaultTransactionalLevelDBFactory::CreateLevelDBDatabase(
-        std::move(state), std::move(scopes), std::move(task_runner),
-        max_open_iterators);
   }
+  return DefaultTransactionalLevelDBFactory::CreateLevelDBDatabase(
+      std::move(state), std::move(scopes), std::move(task_runner),
+      max_open_iterators);
 }
 
 std::unique_ptr<LevelDBDirectTransaction>
@@ -417,10 +346,8 @@
     return std::make_unique<LevelDBTestDirectTransaction>(
         db, failure_method_,
         fail_on_call_num_[FailClass::LEVELDB_DIRECT_TRANSACTION]);
-  } else {
-    return DefaultTransactionalLevelDBFactory::CreateLevelDBDirectTransaction(
-        db);
   }
+  return DefaultTransactionalLevelDBFactory::CreateLevelDBDirectTransaction(db);
 }
 
 scoped_refptr<TransactionalLevelDBTransaction>
@@ -432,18 +359,16 @@
   if (only_trace_calls_) {
     return base::MakeRefCounted<LevelDBTraceTransaction>(
         db, std::move(scope), instance_count_[FailClass::LEVELDB_TRANSACTION]);
-  } else {
-    if (failure_class_ == FailClass::LEVELDB_TRANSACTION &&
-        instance_count_[FailClass::LEVELDB_TRANSACTION] ==
-            fail_on_instance_num_[FailClass::LEVELDB_TRANSACTION]) {
-      return base::MakeRefCounted<LevelDBTestTransaction>(
-          db, std::move(scope), failure_method_,
-          fail_on_call_num_[FailClass::LEVELDB_TRANSACTION]);
-    } else {
-      return DefaultTransactionalLevelDBFactory::CreateLevelDBTransaction(
-          db, std::move(scope));
-    }
   }
+  if (failure_class_ == FailClass::LEVELDB_TRANSACTION &&
+      instance_count_[FailClass::LEVELDB_TRANSACTION] ==
+          fail_on_instance_num_[FailClass::LEVELDB_TRANSACTION]) {
+    return base::MakeRefCounted<LevelDBTestTransaction>(
+        db, std::move(scope), failure_method_,
+        fail_on_call_num_[FailClass::LEVELDB_TRANSACTION]);
+  }
+  return DefaultTransactionalLevelDBFactory::CreateLevelDBTransaction(
+      db, std::move(scope));
 }
 
 std::unique_ptr<TransactionalLevelDBIterator>
@@ -458,18 +383,16 @@
     return std::make_unique<LevelDBTraceIterator>(
         std::move(iterator), db, std::move(txn), std::move(snapshot),
         instance_count_[FailClass::LEVELDB_ITERATOR]);
-  } else {
-    if (failure_class_ == FailClass::LEVELDB_ITERATOR &&
-        instance_count_[FailClass::LEVELDB_ITERATOR] ==
-            fail_on_instance_num_[FailClass::LEVELDB_ITERATOR]) {
-      return std::make_unique<LevelDBTestIterator>(
-          std::move(iterator), db, std::move(txn), std::move(snapshot),
-          failure_method_, fail_on_call_num_[FailClass::LEVELDB_ITERATOR]);
-    } else {
-      return DefaultTransactionalLevelDBFactory::CreateIterator(
-          std::move(iterator), db, std::move(txn), std::move(snapshot));
-    }
   }
+  if (failure_class_ == FailClass::LEVELDB_ITERATOR &&
+      instance_count_[FailClass::LEVELDB_ITERATOR] ==
+          fail_on_instance_num_[FailClass::LEVELDB_ITERATOR]) {
+    return std::make_unique<LevelDBTestIterator>(
+        std::move(iterator), db, std::move(txn), std::move(snapshot),
+        failure_method_, fail_on_call_num_[FailClass::LEVELDB_ITERATOR]);
+  }
+  return DefaultTransactionalLevelDBFactory::CreateIterator(
+      std::move(iterator), db, std::move(txn), std::move(snapshot));
 }
 
 void MockBrowserTestIndexedDBClassFactory::FailOperation(
diff --git a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
index 4d568eb..7e596cd 100644
--- a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
+++ b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
@@ -5,24 +5,16 @@
 #ifndef CONTENT_BROWSER_INDEXED_DB_MOCK_BROWSERTEST_INDEXED_DB_CLASS_FACTORY_H_
 #define CONTENT_BROWSER_INDEXED_DB_MOCK_BROWSERTEST_INDEXED_DB_CLASS_FACTORY_H_
 
-#include <stdint.h>
-
 #include <map>
 #include <memory>
 #include <set>
 
 #include "base/task/sequenced_task_runner.h"
-#include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h"
 #include "components/services/storage/privileged/mojom/indexed_db_control_test.mojom.h"
-#include "content/browser/indexed_db/indexed_db_backing_store.h"
-#include "content/browser/indexed_db/indexed_db_class_factory.h"
-#include "content/browser/indexed_db/indexed_db_database.h"
-#include "content/browser/indexed_db/indexed_db_task_helper.h"
 
 namespace content {
 
-class IndexedDBConnection;
 class LevelDBDirectTransaction;
 class LevelDBScope;
 class LevelDBScopes;
@@ -31,27 +23,15 @@
 class TransactionalLevelDBDatabase;
 
 class MockBrowserTestIndexedDBClassFactory
-    : public IndexedDBClassFactory,
-      public DefaultTransactionalLevelDBFactory,
+    : public DefaultTransactionalLevelDBFactory,
       public storage::mojom::MockFailureInjector {
  public:
   MockBrowserTestIndexedDBClassFactory();
   ~MockBrowserTestIndexedDBClassFactory() override;
 
-  TransactionalLevelDBFactory& transactional_leveldb_factory() override;
+  void Reset();
 
-  std::unique_ptr<IndexedDBDatabase> CreateIndexedDBDatabase(
-      const std::u16string& name,
-      IndexedDBBucketContext& bucket_context,
-      const IndexedDBDatabase::Identifier& unique_identifier) override;
-  std::unique_ptr<IndexedDBTransaction> CreateIndexedDBTransaction(
-      int64_t id,
-      IndexedDBConnection* connection,
-      const std::set<int64_t>& scope,
-      blink::mojom::IDBTransactionMode mode,
-      IndexedDBBucketContextHandle bucket_context,
-      IndexedDBBackingStore::Transaction* backing_store_transaction) override;
-
+  // DefaultTransactionalLevelDBFactory:
   std::unique_ptr<TransactionalLevelDBDatabase> CreateLevelDBDatabase(
       scoped_refptr<LevelDBState> state,
       std::unique_ptr<LevelDBScopes> scopes,
@@ -68,12 +48,12 @@
       base::WeakPtr<TransactionalLevelDBTransaction> txn,
       std::unique_ptr<LevelDBSnapshot> snapshot) override;
 
+  // storage::mojom::MockFailureInjector:
   void FailOperation(storage::mojom::FailClass failure_class,
                      storage::mojom::FailMethod failure_method,
                      int fail_on_instance_num,
                      int fail_on_call_num,
                      base::OnceClosure callback) override;
-  void Reset();
 
  private:
   storage::mojom::FailClass failure_class_;
diff --git a/content/browser/indexed_db/mock_indexed_db_factory_client.cc b/content/browser/indexed_db/mock_indexed_db_factory_client.cc
index 5538a6c..83991c9 100644
--- a/content/browser/indexed_db/mock_indexed_db_factory_client.cc
+++ b/content/browser/indexed_db/mock_indexed_db_factory_client.cc
@@ -17,12 +17,10 @@
 namespace content {
 
 MockIndexedDBFactoryClient::MockIndexedDBFactoryClient()
-    : IndexedDBFactoryClient(nullptr,
-                             mojo::NullAssociatedRemote(),
+    : IndexedDBFactoryClient(mojo::NullAssociatedRemote(),
                              base::SequencedTaskRunner::GetCurrentDefault()) {}
 MockIndexedDBFactoryClient::MockIndexedDBFactoryClient(bool expect_connection)
-    : IndexedDBFactoryClient(nullptr,
-                             mojo::NullAssociatedRemote(),
+    : IndexedDBFactoryClient(mojo::NullAssociatedRemote(),
                              base::SequencedTaskRunner::GetCurrentDefault()),
       expect_connection_(expect_connection) {}
 
diff --git a/content/browser/interest_group/header_direct_from_seller_signals.cc b/content/browser/interest_group/header_direct_from_seller_signals.cc
index 157a66d..1106bfd 100644
--- a/content/browser/interest_group/header_direct_from_seller_signals.cc
+++ b/content/browser/interest_group/header_direct_from_seller_signals.cc
@@ -13,7 +13,9 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/json/json_string_value_serializer.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/strings/stringprintf.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "services/data_decoder/public/cpp/data_decoder.h"
 #include "url/gurl.h"
@@ -163,11 +165,16 @@
     std::string ad_slot,
     std::vector<std::string> errors,
     HeaderDirectFromSellerSignals::CompletionCallback callback,
+    base::TimeTicks start_time,
     data_decoder::DataDecoder::ValueOrError result) {
   std::unique_ptr<HeaderDirectFromSellerSignals> maybe_parsed =
       MaybeFindAdSlotSignalsInResponse(result, ad_slot, *it, errors);
   if (maybe_parsed) {
     // Found a match.
+    base::UmaHistogramTimes(
+        "Ads.InterestGroup.NetHeaderResponse.HeaderDirectFromSellerSignals."
+        "ParseAndFindMatchTime",
+        base::TimeTicks::Now() - start_time);
     std::move(callback).Run(std::move(maybe_parsed), std::move(errors));
     return;
   }
@@ -175,6 +182,10 @@
   ++it;
   if (it == responses->end()) {
     // No responses matched so add an error and return.
+    base::UmaHistogramTimes(
+        "Ads.InterestGroup.NetHeaderResponse.HeaderDirectFromSellerSignals."
+        "ParseAndFindMatchTime",
+        base::TimeTicks::Now() - start_time);
     errors.push_back(NoMatchError(ad_slot));
     std::move(callback).Run(std::make_unique<HeaderDirectFromSellerSignals>(),
                             std::move(errors));
@@ -190,7 +201,7 @@
   maybe_decoder->ParseJson(
       *it, base::BindOnce(&OnJsonDecoded, std::move(get_decoder),
                           std::move(responses), it, std::move(ad_slot),
-                          std::move(errors), std::move(callback)));
+                          std::move(errors), std::move(callback), start_time));
 }
 
 }  // namespace
@@ -199,7 +210,7 @@
 
 HeaderDirectFromSellerSignals::~HeaderDirectFromSellerSignals() = default;
 
-// TODO(crbug.com/1462720): Add UMA for response size and parsing time.
+// TODO(crbug.com/1462720): Add UMA for response size.
 /* static */
 void HeaderDirectFromSellerSignals::ParseAndFind(
     GetDecoderCallback get_decoder,
@@ -208,6 +219,10 @@
     CompletionCallback callback) {
   std::vector<std::string> errors;
   if (responses.empty()) {
+    base::UmaHistogramTimes(
+        "Ads.InterestGroup.NetHeaderResponse.HeaderDirectFromSellerSignals."
+        "ParseAndFindMatchTime",
+        base::Seconds(0));
     errors.push_back(NoMatchError(ad_slot));
     std::move(callback).Run(std::make_unique<HeaderDirectFromSellerSignals>(),
                             std::move(errors));
@@ -226,7 +241,7 @@
   maybe_decoder->ParseJson(
       *it, base::BindOnce(&OnJsonDecoded, get_decoder, std::move(my_responses),
                           it, std::move(ad_slot), std::move(errors),
-                          std::move(callback)));
+                          std::move(callback), base::TimeTicks::Now()));
 }
 
 HeaderDirectFromSellerSignals::HeaderDirectFromSellerSignals(
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc
index 85b8d8a..e17f83f 100644
--- a/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -7,7 +7,6 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/functional/callback_helpers.h"
-#include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
 #include "content/browser/notifications/devtools_event_logging.h"
@@ -383,10 +382,6 @@
     PersistentNotificationDispatchCompleteCallback dispatch_complete_callback,
     PersistentNotificationStatus status,
     blink::ServiceWorkerStatusCode service_worker_status) {
-  base::UmaHistogramEnumeration(
-      "Notifications.PersistentWebNotificationClickEventResult",
-      service_worker_status);
-
   std::move(dispatch_complete_callback).Run(status);
 }
 
@@ -394,10 +389,6 @@
     PersistentNotificationDispatchCompleteCallback dispatch_complete_callback,
     PersistentNotificationStatus status,
     blink::ServiceWorkerStatusCode service_worker_status) {
-  base::UmaHistogramEnumeration(
-      "Notifications.PersistentWebNotificationCloseEventResult",
-      service_worker_status);
-
   std::move(dispatch_complete_callback).Run(status);
 }
 
diff --git a/content/browser/preloading/prefetch/prefetch_response_reader.cc b/content/browser/preloading/prefetch/prefetch_response_reader.cc
index 23e52a9c..fb5c9e7 100644
--- a/content/browser/preloading/prefetch/prefetch_response_reader.cc
+++ b/content/browser/preloading/prefetch/prefetch_response_reader.cc
@@ -97,6 +97,12 @@
     streaming_url_loader_->OnStartServing();
   }
 
+  // Currently only one client is allowed.
+  // This CHECK is also for investigation of crbug.com/1483599.
+  // TODO(crbug.com/1449360): Actually support multiple clients.
+  CHECK(!create_request_handler_called_);
+  create_request_handler_called_ = true;
+
   return base::BindOnce(&PrefetchResponseReader::BindAndStart,
                         base::WrapRefCounted(this), std::move(body_));
 }
@@ -125,14 +131,8 @@
 
   forward_body_ = std::move(body);
 
-  // TODO(crbug.com/1483599): Remove this alias.
-  auto load_state = load_state_;
-  base::debug::Alias(&load_state);
-
   switch (load_state_) {
     case LoadState::kResponseReceived:
-    case LoadState::kCompleted:
-    case LoadState::kFailed:
       // In these cases, `ForwardResponse()` is expected to be called always
       // inside `RunEventQueue()` below, because `CreateRequestHandler()` was
       // called after response headers are received. Both the head and body
@@ -146,9 +146,19 @@
       // reach here.
       //
       // TODO(crbug.com/1449360): we might want to revisit this behavior.
+
+      // TODO(crbug.com/1483599): The code below is duplicated to investigate
+      // the `load_state_` value on CHECK failure. Remove the duplicated code.
       CHECK(GetHead());
-      CHECK(forward_body_) << "Body is null for load state: "
-                           << static_cast<int>(load_state_);
+      CHECK(forward_body_);
+      break;
+    case LoadState::kCompleted:
+      CHECK(GetHead());
+      CHECK(forward_body_);
+      break;
+    case LoadState::kFailed:
+      CHECK(GetHead());
+      CHECK(forward_body_);
       break;
 
     case LoadState::kRedirectHandled:
diff --git a/content/browser/preloading/prefetch/prefetch_response_reader.h b/content/browser/preloading/prefetch/prefetch_response_reader.h
index 4874cc3..336a5f2 100644
--- a/content/browser/preloading/prefetch/prefetch_response_reader.h
+++ b/content/browser/preloading/prefetch/prefetch_response_reader.h
@@ -197,6 +197,8 @@
   // `ForwardResponse()`.
   mojo::ScopedDataPipeConsumerHandle forward_body_;
 
+  bool create_request_handler_called_{false};
+
   // The URL loader clients that will serve the prefetched data.
   mojo::ReceiverSet<network::mojom::URLLoader> serving_url_loader_receivers_;
   mojo::RemoteSet<network::mojom::URLLoaderClient> serving_url_loader_clients_;
diff --git a/content/browser/preloading/preloading_decider_unittest.cc b/content/browser/preloading/preloading_decider_unittest.cc
index 437e7db..e235f1c 100644
--- a/content/browser/preloading/preloading_decider_unittest.cc
+++ b/content/browser/preloading/preloading_decider_unittest.cc
@@ -108,6 +108,7 @@
   }
 
   ~ScopedMockPrerenderer() {
+    prerenderer_ = nullptr;
     preloading_decider_->SetPrerendererForTesting(std::move(old_prerenderer_));
   }
 
@@ -115,7 +116,7 @@
 
  private:
   raw_ptr<PreloadingDecider> preloading_decider_;
-  raw_ptr<MockPrerenderer, DanglingUntriaged> prerenderer_;
+  raw_ptr<MockPrerenderer> prerenderer_;
   std::unique_ptr<Prerenderer> old_prerenderer_;
 };
 
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index ecbd03a..5d00859c 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -1600,4 +1600,12 @@
   return true;
 }
 
+#if !BUILDFLAG(IS_ANDROID)
+void ContentBrowserClient::BindVideoEffectsManager(
+    const std::string& device_id,
+    content::BrowserContext* browser_context,
+    mojo::PendingReceiver<video_capture::mojom::VideoEffectsManager>
+        video_effects_manager) {}
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 }  // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index fb6b64a..401eef3 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -82,6 +82,10 @@
 #include "content/public/browser/posix_file_descriptor_info.h"
 #endif
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "services/video_capture/public/mojom/video_effects_manager.mojom.h"
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 namespace net {
 class SiteForCookies;
 class IsolationInfo;
@@ -2630,6 +2634,16 @@
   // Set whether the browser is running in minimal mode (where most subsystems
   // are left uninitialized).
   virtual void SetIsMinimalMode(bool minimal) {}
+
+#if !BUILDFLAG(IS_ANDROID)
+  // Allows the embedder to correlate backend media services with profile-keyed
+  // effect settings.
+  virtual void BindVideoEffectsManager(
+      const std::string& device_id,
+      content::BrowserContext* browser_context,
+      mojo::PendingReceiver<video_capture::mojom::VideoEffectsManager>
+          video_effects_manager);
+#endif  // !BUILDFLAG(IS_ANDROID)
 };
 
 }  // namespace content
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 1fcb363..7317c01 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -388,7 +388,7 @@
 // Controls how many sites are allowed to be in the Associated subset (ignoring
 // ccTLD aliases).
 const base::FeatureParam<int> kFirstPartySetsMaxAssociatedSites{
-    &kFirstPartySets, "FirstPartySetsMaxAssociatedSites", 3};
+    &kFirstPartySets, "FirstPartySetsMaxAssociatedSites", 5};
 
 // Controls the maximum time duration an outermost frame navigation should be
 // deferred by FPS initialization.
diff --git a/content/renderer/PRESUBMIT_test.py b/content/renderer/PRESUBMIT_test.py
index 39bc98b..2c62b611 100755
--- a/content/renderer/PRESUBMIT_test.py
+++ b/content/renderer/PRESUBMIT_test.py
@@ -24,7 +24,7 @@
     self.assertEqual(1, len(errors))
 
   def testNewUsageSequencedTaskRunnerHandleGet(self):
-    diff = ['scoped_refptr<SequencedThreadTaskRunner> task_runner =',
+    diff = ['scoped_refptr<SequencedTaskRunner> task_runner =',
              '    base::SequencedTaskRunner::GetCurrentDefault()']
     input_api = MockInputApi()
     input_api.files = [MockAffectedFile('content/renderer/foo.cc', diff)]
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 599d79b..665674d 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -2402,7 +2402,6 @@
     "../browser/indexed_db/indexed_db_fake_backing_store.cc",
     "../browser/indexed_db/indexed_db_fake_backing_store.h",
     "../browser/indexed_db/indexed_db_leveldb_coding_unittest.cc",
-    "../browser/indexed_db/indexed_db_leveldb_env_unittest.cc",
     "../browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc",
     "../browser/indexed_db/indexed_db_quota_client_unittest.cc",
     "../browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc",
diff --git a/device/vr/public/cpp/features.cc b/device/vr/public/cpp/features.cc
index 5afb02b7..7a14070 100644
--- a/device/vr/public/cpp/features.cc
+++ b/device/vr/public/cpp/features.cc
@@ -50,7 +50,7 @@
 #if BUILDFLAG(ENABLE_CARDBOARD)
 // Controls WebXR support for the Cardboard SDK Runtime. Note that enabling
 // this will also disable the GVR runtime.
-BASE_FEATURE(kEnableCardboard, "Cardboard", base::FEATURE_DISABLED_BY_DEFAULT);
+BASE_FEATURE(kEnableCardboard, "Cardboard", base::FEATURE_ENABLED_BY_DEFAULT);
 #endif  // ENABLE_CARDBOARD
 
 #if BUILDFLAG(ENABLE_OPENXR)
diff --git a/docs/enterprise/policies.md b/docs/enterprise/policies.md
index 2a54e9eb..b162b10 100644
--- a/docs/enterprise/policies.md
+++ b/docs/enterprise/policies.md
@@ -31,7 +31,7 @@
 
 On these systems it is also possible to set machine-wide cloud-based policies.
 
-** ChromeOS **
+**ChromeOS**
 
 ChromeOS devices can be either cloud-managed or Active Directory managed
 ([AdManagement](https://support.google.com/chrome/a?p=ad)).
@@ -111,14 +111,18 @@
 
 ## Policy Ownership
 
+Policy owners can be individuals, references to OWNERS files, or Google Group
+aliases.
+
 Each policy has two or more owners to minimize the risk of becoming orphaned
 when the author moves away from it.
-
-Policy owners can either be individuals or references to OWNERS files. At least
-one of the owners listed for a policy needs to be an individual, preferably one
-with a chromium.org or google.com account. This is to ensure that some external
-organizations like the translators team can more easily reach out in case of
-questions.
+At least one of the owners listed for a policy needs to be an individual,
+preferably one with a chromium.org or google.com account. This is to ensure
+that some external organizations like the translators team can more easily
+reach out in case of questions.
+At least one of the owners should be a reference to an OWNERS file or a Google
+Group. OWNERS files are preferred to groups since groups can have restricted
+access rights.
 
 ### Responsibilities of the Policy Ownership
 
diff --git a/docs/git_submodules.md b/docs/git_submodules.md
index aeda207..46b0bcc 100644
--- a/docs/git_submodules.md
+++ b/docs/git_submodules.md
@@ -149,6 +149,60 @@
 NOTE: setdep for chromium/src is always prefixed with src/. For example, if you
 are updating v8, the command would be `gclient setdep -r src/v8@<hash>.
 
+## Workflows with submodules
+
+### Submodules during 'git status' and 'git commit'
+Submodules that show up under `Changes not staged for commit` when you run
+`git status` can be hidden with `git -c diff.ignoreSubmodules=all status`
+
+You can also `git commit -a` your changes while excluding all submodules with
+`git -c diff.ignoreSubmodules=all commit -a`.
+
+To make these commands shorter, you can create git aliases for them by adding
+the following to your src/.git/commit file:
+```
+[alias]
+        # 's', 'c', or whatever alias you want for each command
+        s = -c diff.ignoreSubmodules=all status
+        c = -c diff.ignoreSubmodules=all commit -a
+        d = -c diff.ignoreSubmodules=all difftool --dir-diff
+```
+With the above, you can execute these commands by running `git s` and `git c`
+
+NOTE: `diff.ignoreSubmodules` is not supported with `git add`. If you are hiding
+subodules from your view with something like `git s`, running
+`git add .|--all|-A` will still stage any submodules you do not see for commit.
+Then running `git c` will still include these submodules in your commit.
+
+We recommend you use the pre-commit git hook detailed below.
+
+### Submodules during a 'git rebase-update'
+While resolving merge conflicts during a `git rebase-update` you may see
+submodules show up in unexpected places.
+
+#### Submodules under "Changes not staged for commit"
+Submodules under this section can be safely ignored. This simply shows that the
+local commits of these submodules do not match the latest pinned commits fetched
+from remote. In other words, these submodules have been rolled since your last
+`git rebase-update`.
+
+If you use a diff tool like meld you can run:
+`git -c diff.ignoreSubmodules=all difftool --dir-diff`
+to prevent these submodules from showing up in your diff tool.
+
+#### Submodules under "Unmerged paths"
+If Submodules show up under this section it means that new revisions were
+committed for those submodules (either intentional or unintentionally) and these
+submodules were also rolled at remote. So now there is a conflict.
+
+If you DID NOT intentionally make any submdoules changes, you should run:
+`gclient gitmodules`. This will update the submdoules for you, to match whatever
+commits are listed in DEPS (which you have just pulled from remote).
+
+If you DID intentionally roll submodules, you can resolve this conflict just by
+resetting it:
+`gclient setdep -r {path}@{hash}`
+
 ## BETA: Install a hook to help detect unintentional submodule commits
 
 depot_tools provides an opt-in pre-commit hook to detect unintentional submodule
diff --git a/extensions/browser/api/feedback_private/feedback_service.cc b/extensions/browser/api/feedback_private/feedback_service.cc
index 6b0e525..c03a1d88 100644
--- a/extensions/browser/api/feedback_private/feedback_service.cc
+++ b/extensions/browser/api/feedback_private/feedback_service.cc
@@ -147,8 +147,9 @@
         },
         feedback_data);
 
-    BlobReader::Read(browser_context_, feedback_data->attached_file_uuid(),
-                     std::move(populate_attached_file).Then(barrier_closure));
+    BlobReader::Read(
+        browser_context_->GetBlobRemote(feedback_data->attached_file_uuid()),
+        std::move(populate_attached_file).Then(barrier_closure));
   }
 
   if (must_attach_screenshot) {
@@ -160,8 +161,9 @@
             feedback_data->set_image(std::move(*data));
         },
         feedback_data);
-    BlobReader::Read(browser_context_, feedback_data->screenshot_uuid(),
-                     std::move(populate_screenshot).Then(barrier_closure));
+    BlobReader::Read(
+        browser_context_->GetBlobRemote(feedback_data->screenshot_uuid()),
+        std::move(populate_screenshot).Then(barrier_closure));
   }
 }
 
diff --git a/extensions/browser/blob_reader.cc b/extensions/browser/blob_reader.cc
index ce57d92..927fa4a 100644
--- a/extensions/browser/blob_reader.cc
+++ b/extensions/browser/blob_reader.cc
@@ -8,42 +8,37 @@
 #include <utility>
 
 #include "base/functional/bind.h"
-#include "content/public/browser/browser_context.h"
+#include "base/memory/ptr_util.h"
 #include "content/public/browser/browser_thread.h"
 
 // static
-void BlobReader::Read(content::BrowserContext* browser_context,
-                      const std::string& blob_uuid,
-                      BlobReader::BlobReadCallback callback,
-                      int64_t offset,
-                      int64_t length) {
+void BlobReader::Read(mojo::PendingRemote<blink::mojom::Blob> blob,
+                      BlobReadCallback callback,
+                      uint64_t offset,
+                      uint64_t length) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  CHECK_GE(offset, 0);
-  CHECK_GT(length, 0);
-  CHECK_LE(offset, std::numeric_limits<int64_t>::max() - length);
+  CHECK_GE(offset, 0U);
+  CHECK_GT(length, 0U);
+  CHECK_LE(offset, std::numeric_limits<uint64_t>::max() - length);
 
-  absl::optional<Range> range =
-      Range{static_cast<uint64_t>(offset), static_cast<uint64_t>(length)};
-  Read(browser_context, blob_uuid, std::move(callback), std::move(range));
+  Read(std::move(blob), std::move(callback), Range{offset, length});
 }
 
 // static
-void BlobReader::Read(content::BrowserContext* browser_context,
-                      const std::string& blob_uuid,
-                      BlobReader::BlobReadCallback callback) {
+void BlobReader::Read(mojo::PendingRemote<blink::mojom::Blob> blob,
+                      BlobReadCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  Read(browser_context, blob_uuid, std::move(callback), absl::nullopt);
+  Read(std::move(blob), std::move(callback), /*range=*/absl::nullopt);
 }
 
 BlobReader::~BlobReader() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); }
 
 // static
-void BlobReader::Read(content::BrowserContext* browser_context,
-                      const std::string& blob_uuid,
-                      BlobReader::BlobReadCallback callback,
+void BlobReader::Read(mojo::PendingRemote<blink::mojom::Blob> blob,
+                      BlobReadCallback callback,
                       absl::optional<BlobReader::Range> range) {
-  std::unique_ptr<BlobReader> reader(new BlobReader(
-      browser_context->GetBlobRemote(blob_uuid), std::move(range)));
+  auto reader =
+      base::WrapUnique(new BlobReader(std::move(blob), std::move(range)));
 
   // Move the reader to be owned by the callback, so hold onto a temporary
   // pointer to it so we can still call Start on it.
diff --git a/extensions/browser/blob_reader.h b/extensions/browser/blob_reader.h
index dcba896..b63562f 100644
--- a/extensions/browser/blob_reader.h
+++ b/extensions/browser/blob_reader.h
@@ -16,11 +16,6 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/system/data_pipe_drainer.h"
 #include "third_party/blink/public/mojom/blob/blob.mojom.h"
-#include "url/gurl.h"
-
-namespace content {
-class BrowserContext;
-}
 
 // This class may only be used from the UI thread.
 class BlobReader : public blink::mojom::BlobReaderClient,
@@ -33,13 +28,12 @@
                                   int64_t blob_total_size)>
       BlobReadCallback;
 
-  static void Read(content::BrowserContext* browser_context,
-                   const std::string& blob_uuid,
+  static void Read(mojo::PendingRemote<blink::mojom::Blob> blob,
                    BlobReadCallback callback,
-                   int64_t offset,
-                   int64_t length);
-  static void Read(content::BrowserContext* browser_context,
-                   const std::string& blob_uuid,
+                   uint64_t offset,
+                   uint64_t length);
+
+  static void Read(mojo::PendingRemote<blink::mojom::Blob> blob,
                    BlobReadCallback callback);
 
   BlobReader(const BlobReader&) = delete;
@@ -53,10 +47,9 @@
     uint64_t length;
   };
 
-  static void Read(content::BrowserContext* browser_context,
-                   const std::string& blob_uuid,
+  static void Read(mojo::PendingRemote<blink::mojom::Blob> blob,
                    BlobReadCallback callback,
-                   absl::optional<BlobReader::Range> range);
+                   absl::optional<Range> range);
 
   BlobReader(mojo::PendingRemote<blink::mojom::Blob> blob,
              absl::optional<Range> range);
diff --git a/fuchsia_web/runners/cast/cast_runner.cml b/fuchsia_web/runners/cast/cast_runner.cml
index 3bfa4a5..7995464 100644
--- a/fuchsia_web/runners/cast/cast_runner.cml
+++ b/fuchsia_web/runners/cast/cast_runner.cml
@@ -80,24 +80,4 @@
       path: "/cache",
     },
   ],
-  environments: [
-    {
-      name: "cast-capable-env",
-      extends: "none",
-      __stop_timeout_ms: 1000,
-      resolvers: [
-        {
-          resolver: "cast-resolver",
-          from: "self",
-          scheme: "cast",
-        },
-      ],
-      runners: [
-        {
-          runner: "cast-runner",
-          from: "self",
-        },
-      ],
-    },
-  ],
 }
diff --git a/infra/config/.lucicfgfmtrc b/infra/config/.lucicfgfmtrc
index a9fc06d..c9faa8a 100644
--- a/infra/config/.lucicfgfmtrc
+++ b/infra/config/.lucicfgfmtrc
@@ -87,19 +87,51 @@
         arg: "executable_suffix"
         arg: "skip_usage_check"
 
-        # mixin/variant
+        # variant
         arg: "enabled"
         arg: "identifier"
         arg: "description"
+
+        # tests
+        arg: "test"
+        arg: "override_compile_targets"
+        arg: "results_handler"
+        arg: "telemetry_test_name"
+        arg: "tast_expr"
+        arg: "test_level_retries"
+        arg: "mixins"
+        arg: "remove_mixins"
+
+        # mixin/variant/test common fields
         arg: "args"
         arg: "precommit_args"
+        arg: "android_args"
+        arg: "chromeos_args"
+        arg: "desktop_args"
+        arg: "lacros_args"
         arg: "linux_args"
         arg: "mac_args"
         arg: "win64_args"
+        arg: "ci_only"
+        arg: "swarming"
+        arg: "android_swarming"
+        arg: "chromeos_swarming"
+        arg: "merge"
+        arg: "resultdb"
+        arg: "timeout_sec"
+        arg: "experiment_percentage"
 
         # swarming
+        arg: "shards"
         arg: "dimensions"
         arg: "optional_dimensions"
+        arg: "expiration_sec"
+        arg: "hard_timeout_sec"
+        arg: "io_timeout_sec"
+
+        # resultdb
+        arg: "enable"
+        arg: "result_format"
 
         # cipd_package
         arg: "package"
diff --git a/infra/config/console-header.star b/infra/config/console-header.star
index fa1452c..3e2b169 100644
--- a/infra/config/console-header.star
+++ b/infra/config/console-header.star
@@ -154,6 +154,11 @@
                     alt = "Chromium Android console",
                 ),
                 headers.link(
+                    text = "checks",
+                    url = "/p/{}/checks/builders".format(settings.project),
+                    alt = "Checks console",
+                ),
+                headers.link(
                     text = "clang",
                     url = "/p/{}/g/chromium.clang".format(settings.project),
                     alt = "Chromium Clang console",
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index c6677df8..76a6398 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -203,6 +203,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -1145,6 +1150,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -1885,6 +1895,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -2370,6 +2385,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -2734,6 +2754,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -3436,6 +3461,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -3785,6 +3815,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -4214,6 +4249,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -4564,6 +4604,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -5167,6 +5212,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -5570,6 +5620,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -5984,6 +6039,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -6339,6 +6399,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -6792,6 +6857,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -7366,6 +7436,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -7895,6 +7970,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -8276,6 +8356,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -8650,6 +8735,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -9143,6 +9233,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -9977,6 +10072,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -10349,6 +10449,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -10754,6 +10859,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -11154,6 +11264,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -11794,6 +11909,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -12172,6 +12292,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -12595,6 +12720,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -13029,6 +13159,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -13473,6 +13608,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -13837,6 +13977,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -14336,6 +14481,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -14716,6 +14866,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -15100,6 +15255,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -15619,6 +15779,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -15998,6 +16163,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -16418,6 +16588,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -16802,6 +16977,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
@@ -17180,6 +17360,11 @@
         alt: "Chromium Android console"
       }
       links {
+        text: "checks"
+        url: "/p/chromium/checks/builders"
+        alt: "Checks console"
+      }
+      links {
         text: "clang"
         url: "/p/chromium/g/chromium.clang"
         alt: "Chromium Clang console"
diff --git a/infra/config/generated/luci/luci-notify.cfg b/infra/config/generated/luci/luci-notify.cfg
index f7dbaccc..84cd937c 100644
--- a/infra/config/generated/luci/luci-notify.cfg
+++ b/infra/config/generated/luci/luci-notify.cfg
@@ -117,25 +117,6 @@
     }
     template: "tree_closure_email_template"
   }
-  builders {
-    bucket: "ci"
-    name: "Android ASAN (dbg)"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-    template: "tree_closure_email_template"
-  }
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "\\b(bot_update|compile|gclient runhooks|runhooks|update|\\w*nocompile_test)\\b"
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl
new file mode 100644
index 0000000..8d4d250a
--- /dev/null
+++ b/infra/config/generated/testing/test_suites.pyl
@@ -0,0 +1,7988 @@
+# THIS IS A GENERATED FILE DO NOT EDIT!!!
+# Instead:
+# 1. Modify //infra/config/targets/basic_suites.star, //infra/config/targets/compound_suites.star and/or //infra/config/targets/matrix_compound_suites.star
+# 2. Run //infra/config/main.star
+# 3. Run //infra/config/scripts/sync-pyl-files.py
+
+{
+  'basic_suites': {
+
+    'android_12_fieldtrial_webview_tests': {
+      'webview_trichrome_64_cts_tests_no_field_trial': {
+        'test': 'webview_trichrome_64_cts_tests',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 2,
+          'cipd_packages': [
+            {
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
+              'location': 'android_webview/tools/cts_archive',
+              'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
+            },
+          ],
+        },
+      },
+      'webview_ui_test_app_test_apk_no_field_trial': {
+        'test': 'webview_ui_test_app_test_apk',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'ci_only': True,
+      },
+    },
+
+    'android_ar_gtests': {
+      'monochrome_public_test_ar_apk': {},
+      'vr_android_unittests': {},
+    },
+
+    'android_ddready_vr_gtests': {
+      'chrome_public_test_vr_apk-ddready-cardboard': {
+        'test': 'chrome_public_test_vr_apk',
+        'mixins': [
+          'vr_instrumentation_test',
+        ],
+        'args': [
+          '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'chrome_public_test_vr_apk-ddready-ddview': {
+        'test': 'chrome_public_test_vr_apk',
+        'mixins': [
+          'skia_gold_test',
+          'vr_instrumentation_test',
+        ],
+        'args': [
+          '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json',
+          '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk',
+        ],
+        'swarming': {
+          'shards': 4,
+        },
+      },
+      'chrome_public_test_vr_apk-ddready-don-enabled': {
+        'test': 'chrome_public_test_vr_apk',
+        'mixins': [
+          'vr_instrumentation_test',
+        ],
+        'args': [
+          '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_don_setupcomplete.json',
+          '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk',
+          '--annotation=Restriction=VR_DON_Enabled',
+          '--vr-don-enabled',
+        ],
+      },
+    },
+
+    'android_emulator_specific_chrome_public_tests': {
+      'chrome_public_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+          'emulator-8-cores',
+        ],
+        'args': [
+          '--gtest_filter=-org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+      },
+      'chrome_public_test_apk_with_playstore': {
+        'test': 'chrome_public_test_apk',
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'args': [
+          '--gtest_filter=org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*',
+        ],
+      },
+      'chrome_public_unit_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'swarming': {
+          'shards': 4,
+        },
+      },
+    },
+
+    'android_finch_smoke_tests': {
+      'chrome_finch_smoke_tests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'args': [
+          '--finch-seed-path',
+          '../../variations_seed',
+        ],
+      },
+      'monochrome_finch_smoke_tests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'args': [
+          '--finch-seed-path',
+          '../../variations_seed',
+        ],
+      },
+      'variations_smoke_tests': {
+        'test': 'variations_desktop_smoke_tests',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--target-platform=android',
+        ],
+      },
+    },
+
+    'android_isolated_scripts': {
+      'content_shell_crash_test': {
+        'args': [
+          '--platform=android',
+        ],
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+        },
+      },
+    },
+
+    'android_monochrome_smoke_tests': {
+      'monochrome_public_bundle_smoke_test': {},
+      'monochrome_public_smoke_test': {},
+    },
+
+    'android_oreo_standard_gtests': {
+      'chrome_public_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'swarming': {
+          'shards': 5,
+        },
+      },
+      'chrome_public_unit_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+      },
+      'webview_instrumentation_test_apk': {
+        'swarming': {
+          'shards': 5,
+          'expiration': 10800,
+        },
+      },
+    },
+
+    'android_pie_rel_reduced_capacity_gtests': {
+      'android_browsertests': {},
+      'blink_platform_unittests': {},
+      'cc_unittests': {},
+      'content_browsertests': {
+        'swarming': {
+          'shards': 20,
+        },
+      },
+      'viz_unittests': {},
+      'webview_instrumentation_test_apk': {
+        'swarming': {
+          'shards': 7,
+        },
+      },
+    },
+
+    'android_smoke_tests': {
+      'chrome_public_smoke_test': {},
+    },
+
+    'android_specific_chromium_gtests': {
+      'android_browsertests': {
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'android_sync_integration_tests': {
+        'args': [
+          '--test-launcher-batch-limit=1',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+      },
+      'android_webview_unittests': {},
+      'content_shell_test_apk': {
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'gl_tests_validating': {
+        'test': 'gl_tests',
+        'args': [
+          '--use-cmd-decoder=validating',
+        ],
+      },
+      'gl_unittests': {},
+      'mojo_test_apk': {},
+      'ui_android_unittests': {},
+      'webview_instrumentation_test_apk': {
+        'swarming': {
+          'shards': 7,
+        },
+      },
+    },
+
+    'android_specific_coverage_java_tests': {
+      'content_shell_test_apk': {
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'mojo_test_apk': {},
+      'webview_instrumentation_test_apk': {
+        'swarming': {
+          'shards': 7,
+        },
+      },
+    },
+
+    'android_trichrome_smoke_tests': {
+      'trichrome_chrome_bundle_smoke_test': {},
+    },
+
+    'android_webview_gpu_telemetry_tests': {
+      'android_webview_pixel_skia_gold_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+      },
+    },
+
+    'android_wpr_record_replay_tests': {
+      'chrome_java_test_wpr_tests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+      },
+    },
+
+    'ash_pixel_gtests': {
+      'ash_pixeltests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'args': [
+          '--enable-pixel-output-in-tests',
+        ],
+      },
+    },
+
+    'aura_gtests': {
+      'aura_unittests': {},
+      'compositor_unittests': {},
+      'wm_unittests': {},
+    },
+
+    'bfcache_android_specific_gtests': {
+      'bf_cache_android_browsertests': {
+        'test': 'android_browsertests',
+        'args': [
+          '--disable-features=BackForwardCache',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'bfcache_generic_gtests': {
+      'bf_cache_content_browsertests': {
+        'test': 'content_browsertests',
+        'args': [
+          '--disable-features=BackForwardCache',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+      },
+    },
+
+    'bfcache_linux_specific_gtests': {
+      'bf_cache_browser_tests': {
+        'test': 'browser_tests',
+        'args': [
+          '--disable-features=BackForwardCache',
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+      },
+    },
+
+    'blink_unittests': {
+      'blink_unit_tests': {
+        'test': 'blink_unittests',
+      },
+    },
+
+    'cast_audio_specific_chromium_gtests': {
+      'cast_audio_backend_unittests': {},
+      'cast_base_unittests': {},
+      'cast_cast_core_unittests': {},
+      'cast_crash_unittests': {},
+      'cast_media_unittests': {},
+      'cast_shell_browsertests': {
+        'args': [
+          '--enable-local-file-accesses',
+          '--ozone-platform=headless',
+          '--no-sandbox',
+          '--test-launcher-jobs=1',
+        ],
+        'swarming': {
+          'can_use_on_swarming_builders': False,
+        },
+      },
+      'cast_shell_unittests': {},
+    },
+
+    'cast_junit_tests': {
+      'cast_base_junit_tests': {},
+      'cast_shell_junit_tests': {},
+    },
+
+    'cast_video_specific_chromium_gtests': {
+      'cast_display_settings_unittests': {
+        'experiment_percentage': 100,
+      },
+      'cast_graphics_unittests': {},
+      'views_unittests': {
+        'experiment_percentage': 100,
+      },
+    },
+
+    'chrome_android_finch_smoke_tests': {
+      'variations_android_smoke_tests': {
+        'test': 'variations_desktop_smoke_tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--target-platform=android',
+        ],
+      },
+      'variations_webview_smoke_tests': {
+        'test': 'variations_desktop_smoke_tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--target-platform=webview',
+        ],
+      },
+    },
+
+    'chrome_finch_smoke_tests': {
+      'variations_desktop_smoke_tests': {
+        'test': 'variations_desktop_smoke_tests',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'chromeos_args': [
+          '--target-platform=cros',
+        ],
+        'lacros_args': [
+          '--target-platform=lacros',
+        ],
+      },
+    },
+
+    'chrome_isolated_script_tests': {
+      'chrome_sizes': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+      },
+      'variations_smoke_tests': {
+        'test': 'variations_smoke_tests',
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+        },
+      },
+    },
+
+    'chrome_private_code_test_isolated_scripts': {
+      'chrome_private_code_test': {},
+    },
+
+    'chrome_profile_generator_tests': {
+      'chrome_public_apk_profile_tests': {
+        'test': 'chrome_public_apk_baseline_profile_generator',
+        'ci_only': True,
+        'experiment_percentage': 100,
+      },
+    },
+
+    'chrome_public_tests': {
+      'chrome_public_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'swarming': {
+          'shards': 19,
+        },
+      },
+      'chrome_public_unit_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'chrome_public_wpt': {
+      'chrome_public_wpt': {
+        'results_handler': 'layout tests',
+        'args': [
+          '--no-wpt-internal',
+        ],
+        'swarming': {
+          'shards': 36,
+          'expiration': 18000,
+          'hard_timeout': 14400,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'chrome_sizes': {
+      'chrome_sizes': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+      },
+    },
+
+    'chrome_sizes_android': {
+      'chrome_sizes': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'remove_mixins': [
+          'android_r',
+          'bullhead',
+          'flame',
+          'marshmallow',
+          'mdarcy',
+          'oreo_fleet',
+          'oreo_mr1_fleet',
+          'pie_fleet',
+          'walleye',
+        ],
+        'args': [
+          '--platform=android',
+        ],
+        'swarming': {
+          'dimensions': {
+            'cpu': 'x86-64',
+            'os': 'Ubuntu-22.04',
+          },
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+      },
+    },
+
+    'chromedriver_py_tests_isolated_scripts': {
+      'chromedriver_py_tests': {
+        'args': [
+          '--test-type=integration',
+        ],
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'chromedriver_replay_unittests': {},
+    },
+
+    'chromeos_annotation_scripts': {
+      'check_network_annotations': {
+        'script': 'check_network_annotations.py',
+      },
+    },
+
+    'chromeos_browser_all_tast_tests': {
+      'chrome_all_tast_tests': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--tast-retries=1',
+        ],
+        'swarming': {
+          'shards': 10,
+          'io_timeout': 3600,
+          'idempotent': False,
+        },
+      },
+    },
+
+    'chromeos_browser_integration_tests': {
+      'disk_usage_tast_test': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--strip-chrome',
+        ],
+        'swarming': {
+          'idempotent': False,
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+      },
+    },
+
+    'chromeos_chrome_all_tast_tests': {
+      'chrome_all_tast_tests': {
+        'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS',
+        'test_level_retries': 2,
+        'timeout_sec': 21600,
+        'shards': 10,
+      },
+    },
+
+    'chromeos_chrome_criticalstaging_tast_tests': {
+      'chrome_criticalstaging_tast_tests': {
+        'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS',
+        'test_level_retries': 2,
+        'timeout_sec': 7200,
+        'shards': 3,
+        'experiment_percentage': 100,
+      },
+    },
+
+    'chromeos_chrome_disabled_tast_tests': {
+      'chrome_disabled_tast_tests': {
+        'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS',
+        'test_level_retries': 1,
+        'timeout_sec': 7200,
+        'shards': 2,
+        'experiment_percentage': 100,
+      },
+    },
+
+    'chromeos_device_only_gtests': {
+      'base_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.base_unittests.filter',
+        ],
+      },
+    },
+
+    'chromeos_integration_tests': {
+      'chromeos_integration_tests': {
+        'ci_only': True,
+      },
+    },
+
+    'chromeos_isolated_scripts': {
+      'telemetry_perf_unittests': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--browser=cros-chrome',
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+          '--xvfb',
+          '--typ-max-failures=3',
+        ],
+        'swarming': {
+          'shards': 12,
+          'idempotent': False,
+        },
+      },
+      'telemetry_unittests': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--jobs=1',
+          '--browser=cros-chrome',
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+          '--typ-max-failures=3',
+        ],
+        'swarming': {
+          'shards': 24,
+          'idempotent': False,
+        },
+      },
+    },
+
+    'chromeos_js_code_coverage_browser_tests': {
+      'chromeos_js_code_coverage_browser_tests': {
+        'test': 'browser_tests',
+        'swarming': {
+          'shards': 16,
+        },
+      },
+    },
+
+    'chromeos_system_friendly_gtests': {
+      'aura_unittests': {
+        'args': [
+          '--ozone-platform=headless',
+        ],
+      },
+      'base_unittests': {},
+      'capture_unittests': {
+        'args': [
+          '--test-launcher-jobs=1',
+          '--gtest_filter=-*UsingRealWebcam_CaptureMjpeg*',
+        ],
+      },
+      'cc_unittests': {},
+      'crypto_unittests': {},
+      'display_unittests': {},
+      'fake_libva_driver_unittest': {
+        'args': [
+          '--env-var',
+          'LIBVA_DRIVERS_PATH',
+          './',
+          '--env-var',
+          'LIBVA_DRIVER_NAME',
+          'libfake',
+        ],
+        'experiment_percentage': 100,
+      },
+      'google_apis_unittests': {},
+      'ipc_tests': {},
+      'latency_unittests': {},
+      'libcups_unittests': {},
+      'media_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.media_unittests.filter',
+        ],
+      },
+      'midi_unittests': {},
+      'mojo_unittests': {},
+      'net_unittests': {
+        'args': [
+          '--vpython-dir=../../vpython_dir_linux_amd64',
+          '--gtest_filter=-PythonUtils.PythonRunTime',
+        ],
+        'swarming': {
+          'shards': 3,
+          'cipd_packages': [
+            {
+              'cipd_package': 'infra/3pp/tools/cpython3/linux-amd64',
+              'location': 'vpython_dir_linux_amd64',
+              'revision': 'version:2@3.8.10.chromium.21',
+            },
+            {
+              'cipd_package': 'infra/tools/luci/vpython/linux-amd64',
+              'location': 'vpython_dir_linux_amd64',
+              'revision': 'git_revision:0f694cdc06ba054b9960aa1ae9766e45b53d02c1',
+            },
+          ],
+        },
+      },
+      'ozone_gl_unittests': {
+        'args': [
+          '--stop-ui',
+        ],
+      },
+      'ozone_unittests': {},
+      'pdf_unittests': {},
+      'printing_unittests': {},
+      'profile_provider_unittest': {
+        'args': [
+          '--stop-ui',
+          '--test-launcher-jobs=1',
+        ],
+      },
+      'rust_gtest_interop_unittests': {},
+      'sql_unittests': {},
+      'url_unittests': {},
+      'vaapi_unittest': {
+        'args': [
+          '--stop-ui',
+          '--env-var',
+          'LIBVA_DRIVERS_PATH',
+          './',
+          '--env-var',
+          'LIBVA_DRIVER_NAME',
+          'libfake',
+          '--gtest_filter="VaapiTest.*"',
+        ],
+      },
+    },
+
+    'chromium_android_scripts': {
+      'check_network_annotations': {
+        'script': 'check_network_annotations.py',
+      },
+    },
+
+    'chromium_android_webkit_gtests': {
+      'blink_heap_unittests': {},
+      'webkit_unit_tests': {
+        'test': 'blink_unittests',
+      },
+    },
+
+    'chromium_dev_android_gtests': {
+      'chrome_public_smoke_test': {},
+    },
+
+    'chromium_dev_desktop_gtests': {
+      'base_unittests': {},
+      'content_browsertests': {
+        'swarming': {
+          'shards': 4,
+        },
+      },
+      'content_unittests': {},
+      'interactive_ui_tests': {},
+      'net_unittests': {},
+      'rust_gtest_interop_unittests': {},
+      'unit_tests': {},
+    },
+
+    'chromium_dev_linux_gtests': {
+      'base_unittests': {
+        'swarming': {
+          'dimensions': {
+            'cores': '8',
+          },
+        },
+      },
+      'browser_tests': {
+        'swarming': {
+          'shards': 8,
+          'dimensions': {
+            'cores': '8',
+          },
+        },
+      },
+      'content_browsertests': {
+        'swarming': {
+          'shards': 5,
+          'dimensions': {
+            'cores': '8',
+          },
+        },
+      },
+      'content_unittests': {
+        'swarming': {
+          'dimensions': {
+            'cores': '2',
+          },
+        },
+      },
+      'interactive_ui_tests': {
+        'swarming': {
+          'shards': 3,
+          'dimensions': {
+            'cores': '8',
+          },
+        },
+      },
+      'net_unittests': {
+        'swarming': {
+          'dimensions': {
+            'cores': '8',
+          },
+        },
+      },
+      'rust_gtest_interop_unittests': {},
+      'unit_tests': {
+        'swarming': {
+          'dimensions': {
+            'cores': '2',
+          },
+        },
+      },
+    },
+
+    'chromium_gtests': {
+      'absl_hardening_tests': {},
+      'angle_unittests': {
+        'android_args': [
+          '-v',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'base_unittests': {},
+      'blink_common_unittests': {},
+      'blink_heap_unittests': {},
+      'blink_platform_unittests': {},
+      'boringssl_crypto_tests': {},
+      'boringssl_ssl_tests': {},
+      'capture_unittests': {
+        'args': [
+          '--gtest_filter=-*UsingRealWebcam*',
+        ],
+      },
+      'cast_unittests': {},
+      'components_browsertests': {},
+      'components_unittests': {
+        'android_swarming': {
+          'shards': 6,
+        },
+      },
+      'content_browsertests': {
+        'swarming': {
+          'shards': 8,
+        },
+        'android_swarming': {
+          'shards': 15,
+        },
+      },
+      'content_unittests': {
+        'android_swarming': {
+          'shards': 3,
+        },
+      },
+      'crashpad_tests': {},
+      'crypto_unittests': {},
+      'env_chromium_unittests': {
+        'ci_only': True,
+      },
+      'events_unittests': {},
+      'gcm_unit_tests': {},
+      'gin_unittests': {},
+      'google_apis_unittests': {},
+      'gpu_unittests': {},
+      'gwp_asan_unittests': {},
+      'ipc_tests': {},
+      'latency_unittests': {},
+      'leveldb_unittests': {
+        'ci_only': True,
+      },
+      'libjingle_xmpp_unittests': {},
+      'liburlpattern_unittests': {},
+      'media_unittests': {},
+      'midi_unittests': {},
+      'mojo_unittests': {},
+      'net_unittests': {
+        'android_swarming': {
+          'shards': 3,
+        },
+      },
+      'perfetto_unittests': {},
+      'services_unittests': {},
+      'shell_dialogs_unittests': {},
+      'skia_unittests': {},
+      'sql_unittests': {},
+      'storage_unittests': {},
+      'ui_base_unittests': {},
+      'ui_touch_selection_unittests': {},
+      'url_unittests': {},
+      'webkit_unit_tests': {
+        'test': 'blink_unittests',
+        'android_swarming': {
+          'shards': 6,
+        },
+      },
+      'wtf_unittests': {},
+      'zlib_unittests': {},
+    },
+
+    'chromium_gtests_for_devices_with_graphical_output': {
+      'cc_unittests': {},
+      'device_unittests': {},
+      'display_unittests': {},
+      'gfx_unittests': {},
+      'unit_tests': {
+        'android_swarming': {
+          'shards': 2,
+        },
+      },
+      'viz_unittests': {},
+    },
+
+    'chromium_gtests_for_linux_and_chromeos_only': {
+      'dbus_unittests': {},
+    },
+
+    'chromium_gtests_for_linux_and_mac_only': {
+      'openscreen_unittests': {},
+    },
+
+    'chromium_gtests_for_linux_only': {
+      'ozone_unittests': {},
+      'ozone_x11_unittests': {},
+    },
+
+    'chromium_gtests_for_win_and_linux_only': {
+      'pthreadpool_unittests': {
+        'ci_only': True,
+      },
+    },
+
+    'chromium_ios_scripts': {
+      'check_static_initializers': {
+        'script': 'check_static_initializers.py',
+      },
+    },
+
+    'chromium_junit_tests_no_swarming': {
+      'android_webview_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'base_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'build_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'chrome_java_test_pagecontroller_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'chrome_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'components_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'content_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'device_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'junit_unit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'keyboard_accessory_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'media_base_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'module_installer_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'net_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'paint_preview_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'password_check_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'password_manager_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'services_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'touch_to_fill_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'ui_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'webapk_client_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'webapk_shell_apk_h2o_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+      'webapk_shell_apk_junit_tests': {
+        'remove_mixins': [
+          'nougat-x86-emulator',
+        ],
+      },
+    },
+
+    'chromium_junit_tests_scripts': {
+      'android_webview_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'base_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'build_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'chrome_java_test_pagecontroller_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'chrome_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'components_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'content_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'device_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'junit_unit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'keyboard_accessory_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'media_base_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'module_installer_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'net_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'paint_preview_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'password_check_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'password_manager_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'services_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'touch_to_fill_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'ui_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'webapk_client_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'webapk_shell_apk_h2o_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'webapk_shell_apk_junit_tests': {
+        'mixins': [
+          'x86-64',
+          'linux-jammy',
+          'junit-swarming',
+        ],
+        'remove_mixins': [
+          'emulator-4-cores',
+          'nougat-x86-emulator',
+          'oreo-x86-emulator',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+    },
+
+    'chromium_linux_scripts': {
+      'check_network_annotations': {
+        'script': 'check_network_annotations.py',
+      },
+      'check_static_initializers': {
+        'script': 'check_static_initializers.py',
+      },
+      'checkdeps': {
+        'script': 'checkdeps.py',
+      },
+      'checkperms': {
+        'script': 'checkperms.py',
+      },
+      'headless_python_unittests': {
+        'script': 'headless_python_unittests.py',
+      },
+      'metrics_python_tests': {
+        'script': 'metrics_python_tests.py',
+      },
+      'webkit_lint': {
+        'script': 'blink_lint_expectations.py',
+      },
+    },
+
+    'chromium_mac_scripts': {
+      'check_static_initializers': {
+        'script': 'check_static_initializers.py',
+      },
+      'metrics_python_tests': {
+        'script': 'metrics_python_tests.py',
+      },
+      'webkit_lint': {
+        'script': 'blink_lint_expectations.py',
+      },
+    },
+
+    'chromium_tracing_gtests': {
+      'services_unittests': {},
+    },
+
+    'chromium_web_tests_high_dpi_isolated_scripts': {
+      'high_dpi_blink_web_tests': {
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--flag-specific=highdpi',
+          '--skipped=always',
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'high_dpi_blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--flag-specific=highdpi',
+          '--skipped=always',
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'chromium_webkit_isolated_scripts': {
+      'blink_web_tests': {
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 5,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 7,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'chromium_win_scripts': {
+      'check_network_annotations': {
+        'script': 'check_network_annotations.py',
+      },
+      'metrics_python_tests': {
+        'script': 'metrics_python_tests.py',
+      },
+      'webkit_lint': {
+        'script': 'blink_lint_expectations.py',
+      },
+    },
+
+    'clang_tot_gtests': {
+      'base_unittests': {},
+    },
+
+    'client_v8_chromium_gtests': {
+      'app_shell_unittests': {},
+      'browser_tests': {
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'chrome_app_unittests': {},
+      'chromedriver_unittests': {},
+      'components_browsertests': {},
+      'components_unittests': {},
+      'compositor_unittests': {},
+      'content_browsertests': {},
+      'content_unittests': {},
+      'device_unittests': {},
+      'extensions_browsertests': {},
+      'extensions_unittests': {},
+      'gcm_unit_tests': {},
+      'gin_unittests': {},
+      'google_apis_unittests': {},
+      'gpu_unittests': {},
+      'headless_browsertests': {},
+      'headless_unittests': {},
+      'interactive_ui_tests': {},
+      'nacl_loader_unittests': {},
+      'net_unittests': {},
+      'pdf_unittests': {},
+      'ppapi_unittests': {},
+      'remoting_unittests': {},
+      'services_unittests': {},
+      'sync_integration_tests': {
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'unit_tests': {},
+    },
+
+    'client_v8_chromium_isolated_scripts': {
+      'content_shell_crash_test': {
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+        },
+      },
+      'telemetry_gpu_unittests': {
+        'swarming': {
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'telemetry_perf_unittests': {
+        'args': [
+          '--xvfb',
+          '--extra-browser-args=--enable-crashpad',
+        ],
+        'swarming': {
+          'shards': 12,
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'telemetry_unittests': {
+        'args': [
+          '--jobs=1',
+          '--extra-browser-args=--disable-gpu',
+        ],
+        'swarming': {
+          'shards': 4,
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'components_perftests_isolated_scripts': {
+      'components_perftests': {
+        'args': [
+          '--gtest-benchmark-name=components_perftests',
+        ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+          'args': [
+            '--smoke-test-mode',
+          ],
+        },
+      },
+    },
+
+    'cr23_linux_gtests': {
+      'cr23_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 20,
+        },
+      },
+      'cr23_interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'cr23_views_unittests': {
+        'test': 'views_unittests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'ci_only': True,
+      },
+    },
+
+    'cr23_mac_gtests': {
+      'cr23_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 20,
+        },
+      },
+      'cr23_interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'cr23_views_unittests': {
+        'test': 'views_unittests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'ci_only': True,
+      },
+    },
+
+    'cr23_pixel_browser_tests_gtests': {
+      'cr23_pixel_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'skia_gold_test',
+          'chrome-refresh-2023',
+        ],
+        'args': [
+          '--browser-ui-tests-verify-pixels',
+          '--enable-pixel-output-in-tests',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter',
+          '--test-launcher-jobs=1',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'cr23_pixel_interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'mixins': [
+          'skia_gold_test',
+          'chrome-refresh-2023',
+        ],
+        'args': [
+          '--browser-ui-tests-verify-pixels',
+          '--enable-pixel-output-in-tests',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter',
+        ],
+      },
+    },
+
+    'cr23_win_gtests': {
+      'cr23_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 20,
+        },
+      },
+      'cr23_interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'cr23_views_unittests': {
+        'test': 'views_unittests',
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'ci_only': True,
+      },
+    },
+
+    'cronet_gtests': {
+      'cronet_sample_test_apk': {},
+      'cronet_smoketests_missing_native_library_instrumentation_apk': {},
+      'cronet_smoketests_platform_only_instrumentation_apk': {},
+      'cronet_test_instrumentation_apk': {},
+      'cronet_tests_android': {},
+      'cronet_unittests_android': {},
+      'net_unittests': {
+        'swarming': {
+          'shards': 4,
+        },
+      },
+    },
+
+    'cronet_resource_sizes': {
+      'resource_sizes_cronet_sample_apk': {
+        'swarming': {
+          'dimensions': {
+            'os': 'Ubuntu-22.04',
+            'cpu': 'x86-64',
+          },
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+        },
+      },
+    },
+
+    'cronet_sizes': {
+      'cronet_sizes': {
+        'remove_mixins': [
+          'android_r',
+          'bullhead',
+          'flame',
+          'marshmallow',
+          'mdarcy',
+          'oreo_fleet',
+          'oreo_mr1_fleet',
+          'pie_fleet',
+          'walleye',
+        ],
+        'swarming': {
+          'dimensions': {
+            'os': 'Ubuntu-22.04',
+            'cpu': 'x86-64',
+          },
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+          'result_file': '${ISOLATED_OUTDIR}/sizes/test_results.json',
+        },
+      },
+    },
+
+    'desktop_chromium_isolated_scripts': {
+      'blink_python_tests': {
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'blink_web_tests': {
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 5,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 7,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'content_shell_crash_test': {
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+        },
+      },
+      'flatbuffers_unittests': {
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+        },
+      },
+      'grit_python_unittests': {
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'telemetry_gpu_unittests': {
+        'swarming': {
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'telemetry_unittests': {
+        'args': [
+          '--jobs=1',
+          '--extra-browser-args=--disable-gpu',
+        ],
+        'swarming': {
+          'shards': 8,
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'views_perftests': {
+        'args': [
+          '--gtest-benchmark-name=views_perftests',
+        ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+          'args': [
+            '--smoke-test-mode',
+          ],
+        },
+      },
+    },
+
+    'desktop_once_isolated_scripts': {
+      'test_env_py_unittests': {
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'xvfb_py_unittests': {
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'devtools_browser_tests': {
+      'devtools_browser_tests': {
+        'test': 'browser_tests',
+        'args': [
+          '--gtest_filter=*DevTools*',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+      },
+    },
+
+    'devtools_webkit_and_tab_target_isolated_scripts': {
+      'blink_web_tests': {
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 5,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'blink_web_tests_dt_tab_target': {
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--flag-specific=devtools-tab-target',
+          '--num-retries=3',
+          'http/tests/devtools',
+        ],
+        'swarming': {
+          'shards': 5,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 7,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'devtools_webkit_isolated_scripts': {
+      'blink_web_tests': {
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 5,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 7,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'fieldtrial_android_tests': {
+      'android_browsertests_no_fieldtrial': {
+        'test': 'android_browsertests',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 3,
+        },
+      },
+    },
+
+    'fieldtrial_browser_tests': {
+      'browser_tests_no_field_trial': {
+        'test': 'browser_tests',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'components_browsertests_no_field_trial': {
+        'test': 'components_browsertests',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'ci_only': True,
+      },
+      'interactive_ui_tests_no_field_trial': {
+        'test': 'interactive_ui_tests',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'ci_only': True,
+      },
+      'sync_integration_tests_no_field_trial': {
+        'test': 'sync_integration_tests',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'ci_only': True,
+      },
+    },
+
+    'finch_smoke_tests': {
+      'base_unittests': {},
+    },
+
+    'fuchsia_accessibility_content_browsertests': {
+      'accessibility_content_browsertests': {
+        'test': 'content_browsertests',
+        'args': [
+          '--gtest_filter=*All/DumpAccessibility*/fuchsia*',
+          '--test-arg=--disable-gpu',
+          '--test-arg=--headless',
+          '--test-arg=--ozone-platform=headless',
+        ],
+        'swarming': {
+          'shards': 8,
+        },
+      },
+    },
+
+    'fuchsia_chrome_small_gtests': {
+      'courgette_unittests': {},
+      'extensions_unittests': {},
+      'headless_unittests': {},
+      'message_center_unittests': {},
+      'views_examples_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_examples_unittests.filter',
+        ],
+      },
+      'views_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_unittests.filter',
+        ],
+      },
+    },
+
+    'fuchsia_common_gtests': {
+      'absl_hardening_tests': {},
+      'accessibility_unittests': {},
+      'aura_unittests': {},
+      'base_unittests': {},
+      'blink_common_unittests': {},
+      'blink_fuzzer_unittests': {},
+      'blink_heap_unittests': {},
+      'blink_platform_unittests': {},
+      'blink_unittests': {},
+      'boringssl_crypto_tests': {},
+      'boringssl_ssl_tests': {},
+      'capture_unittests': {},
+      'components_browsertests': {
+        'args': [
+          '--test-arg=--disable-gpu',
+          '--test-arg=--headless',
+          '--test-arg=--ozone-platform=headless',
+        ],
+      },
+      'components_unittests': {
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'compositor_unittests': {},
+      'content_browsertests': {
+        'args': [
+          '--gtest_filter=-All/DumpAccessibility*/fuchsia',
+          '--test-arg=--disable-gpu',
+          '--test-arg=--headless',
+          '--test-arg=--ozone-platform=headless',
+        ],
+        'swarming': {
+          'shards': 14,
+        },
+      },
+      'content_unittests': {},
+      'crypto_unittests': {},
+      'events_unittests': {},
+      'filesystem_service_unittests': {},
+      'gcm_unit_tests': {},
+      'gin_unittests': {},
+      'google_apis_unittests': {},
+      'gpu_unittests': {},
+      'gwp_asan_unittests': {},
+      'headless_browsertests': {},
+      'ipc_tests': {},
+      'latency_unittests': {},
+      'media_unittests': {},
+      'midi_unittests': {},
+      'mojo_unittests': {},
+      'native_theme_unittests': {},
+      'net_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter',
+        ],
+        'swarming': {
+          'shards': 4,
+        },
+      },
+      'ozone_gl_unittests': {
+        'args': [
+          '--test-arg=--ozone-platform=headless',
+        ],
+      },
+      'ozone_unittests': {},
+      'perfetto_unittests': {},
+      'service_manager_unittests': {},
+      'services_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.services_unittests.filter',
+        ],
+      },
+      'shell_dialogs_unittests': {},
+      'skia_unittests': {},
+      'snapshot_unittests': {},
+      'sql_unittests': {},
+      'storage_unittests': {},
+      'ui_base_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter',
+        ],
+      },
+      'ui_touch_selection_unittests': {},
+      'ui_unittests': {},
+      'url_unittests': {},
+      'wm_unittests': {},
+      'wtf_unittests': {},
+      'zlib_unittests': {},
+    },
+
+    'fuchsia_common_gtests_with_graphical_output': {
+      'cc_unittests': {
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'display_unittests': {},
+      'gfx_unittests': {},
+      'viz_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.viz_unittests.filter',
+        ],
+      },
+    },
+
+    'fuchsia_facility_gtests': {
+      'aura_unittests': {},
+      'blink_common_unittests': {},
+      'courgette_unittests': {},
+      'crypto_unittests': {},
+      'filesystem_service_unittests': {},
+      'web_engine_integration_tests': {
+        'args': [
+          '--test-arg=--vmodule=test_navigation_listener=1',
+        ],
+      },
+      'web_engine_unittests': {},
+    },
+
+    'fuchsia_sizes_tests': {
+      'fuchsia_sizes': {
+        'args': [
+          '--sizes-path',
+          'tools/fuchsia/size_tests/fyi_sizes_smoketest.json',
+        ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+      },
+    },
+
+    'gl_gtests_passthrough': {
+      'gl_tests_passthrough': {
+        'test': 'gl_tests',
+        'args': [
+          '--use-cmd-decoder=passthrough',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'gl_unittests': {},
+    },
+
+    'goma_gtests': {
+      'base_unittests': {},
+      'content_unittests': {},
+    },
+
+    'goma_mac_gtests': {
+      'base_unittests': {
+        'swarming': {
+          'dimensions': {
+            'cpu': 'x86-64',
+            'os': 'Mac-13',
+          },
+        },
+      },
+      'content_unittests': {
+        'swarming': {
+          'dimensions': {
+            'cpu': 'x86-64',
+            'os': 'Mac-13',
+          },
+        },
+      },
+    },
+
+    'gpu_angle_fuchsia_unittests_isolated_scripts': {
+      'angle_unittests': {
+        'mixins': [
+          'fuchsia_logs',
+        ],
+        'args': [
+          'bin/run_angle_unittests',
+        ],
+      },
+    },
+
+    'gpu_angle_ios_end2end_gtests': {
+      'angle_end2end_tests': {
+        'args': [
+          '--release',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+    },
+
+    'gpu_angle_ios_white_box_gtests': {
+      'angle_white_box_tests': {
+        'args': [
+          '--release',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+    },
+
+    'gpu_angle_unit_gtests': {
+      'angle_unittests': {
+        'android_args': [
+          '-v',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+    },
+
+    'gpu_command_buffer_perf_passthrough_isolated_scripts': {
+      'passthrough_command_buffer_perftests': {
+        'test': 'command_buffer_perftests',
+        'args': [
+          '--gtest-benchmark-name=passthrough_command_buffer_perftests',
+          '-v',
+          '--use-cmd-decoder=passthrough',
+          '--use-angle=gl-null',
+          '--fast-run',
+        ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+          'args': [
+            '--smoke-test-mode',
+          ],
+        },
+      },
+    },
+
+    'gpu_common_and_optional_telemetry_tests': {
+      'info_collection_tests': {
+        'telemetry_test_name': 'info_collection',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--expected-vendor-id',
+          '${gpu_vendor_id}',
+          '$$MAGIC_SUBSTITUTION_GPUExpectedDeviceId',
+          '--extra-browser-args=--force_high_performance_gpu',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'trace_test': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+    },
+
+    'gpu_common_gtests_passthrough': {
+      'gl_tests_passthrough': {
+        'test': 'gl_tests',
+        'args': [
+          '--use-cmd-decoder=passthrough',
+          '--use-gl=angle',
+        ],
+        'chromeos_args': [
+          '--stop-ui',
+        ],
+        'desktop_args': [
+          '--use-gpu-in-tests',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'gl_unittests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'chromeos_args': [
+          '--stop-ui',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.gl_unittests.filter',
+        ],
+        'desktop_args': [
+          '--use-gpu-in-tests',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+    },
+
+    'gpu_common_gtests_validating': {
+      'gl_tests_validating': {
+        'test': 'gl_tests',
+        'args': [
+          '--use-cmd-decoder=validating',
+        ],
+        'chromeos_args': [
+          '--stop-ui',
+          '$$MAGIC_SUBSTITUTION_ChromeOSGtestFilterFile',
+        ],
+        'desktop_args': [
+          '--use-gpu-in-tests',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+      'gl_unittests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'chromeos_args': [
+          '--stop-ui',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.gl_unittests.filter',
+        ],
+        'desktop_args': [
+          '--use-gpu-in-tests',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+    },
+
+    'gpu_dawn_common_isolated_scripts': {
+      'telemetry_gpu_unittests': {
+        'swarming': {
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'gpu_dawn_gtests': {
+      'dawn_end2end_implicit_device_sync_tests': {
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
+        'args': [
+          '--enable-implicit-device-sync',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+        'ci_only': True,
+      },
+      'dawn_end2end_skip_validation_tests': {
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
+        'args': [
+          '--enable-toggles=skip_validation',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+      'dawn_end2end_tests': {
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+      'dawn_end2end_wire_tests': {
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
+        'args': [
+          '--use-wire',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+    },
+
+    'gpu_dawn_gtests_no_dxc': {
+      'dawn_end2end_no_dxc_tests': {
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
+        'args': [
+          '--disable-toggles=use_dxc',
+        ],
+      },
+    },
+
+    'gpu_dawn_gtests_no_dxc_with_validation': {
+      'dawn_end2end_no_dxc_validation_layers_tests': {
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
+        'args': [
+          '--disable-toggles=use_dxc',
+          '--enable-backend-validation',
+        ],
+      },
+    },
+
+    'gpu_dawn_gtests_with_validation': {
+      'dawn_end2end_validation_layers_tests': {
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
+        'args': [
+          '--enable-backend-validation',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+    },
+
+    'gpu_dawn_perf_smoke_isolated_scripts': {
+      'dawn_perf_tests': {
+        'args': [
+          '--override-steps=1',
+          '--gtest-benchmark-name=dawn_perf_tests',
+          '-v',
+        ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+          'args': [
+            '--smoke-test-mode',
+          ],
+        },
+      },
+    },
+
+    'gpu_dawn_web_platform_webgpu_cts_force_swiftshader': {
+      'webgpu_swiftshader_web_platform_cts_tests': {
+        'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
+        'args': [
+          '--use-webgpu-adapter=swiftshader',
+          '--test-filter=*web_platform*',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'webgpu_swiftshader_web_platform_cts_with_validation_tests': {
+        'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
+        'args': [
+          '--use-webgpu-adapter=swiftshader',
+          '--test-filter=*web_platform*',
+          '--enable-dawn-backend-validation',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'gpu_dawn_webgpu_blink_web_tests': {
+      'webgpu_blink_web_tests': {
+        'test': 'webgpu_blink_web_tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_cts',
+        ],
+        'args': [
+          '--flag-specific=webgpu',
+        ],
+      },
+      'webgpu_blink_web_tests_with_backend_validation': {
+        'test': 'webgpu_blink_web_tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_cts',
+        ],
+        'args': [
+          '--flag-specific=webgpu-with-backend-validation',
+          '--timeout-ms=30000',
+        ],
+      },
+    },
+
+    'gpu_dawn_webgpu_blink_web_tests_force_swiftshader': {
+      'webgpu_swiftshader_blink_web_tests': {
+        'test': 'webgpu_blink_web_tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_cts',
+        ],
+        'args': [
+          '--flag-specific=webgpu-swiftshader',
+        ],
+      },
+      'webgpu_swiftshader_blink_web_tests_with_backend_validation': {
+        'test': 'webgpu_blink_web_tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_cts',
+        ],
+        'args': [
+          '--flag-specific=webgpu-swiftshader-with-backend-validation',
+          '--timeout-ms=30000',
+        ],
+      },
+    },
+
+    'gpu_dawn_webgpu_cts': {
+      'webgpu_cts_tests': {
+        'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
+        'swarming': {
+          'shards': 14,
+        },
+        'android_swarming': {
+          'shards': 36,
+        },
+      },
+      'webgpu_cts_with_validation_tests': {
+        'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
+        'args': [
+          '--enable-dawn-backend-validation',
+        ],
+        'swarming': {
+          'shards': 14,
+        },
+        'android_swarming': {
+          'shards': 36,
+        },
+      },
+    },
+
+    'gpu_dawn_webgpu_cts_asan': {
+      'webgpu_cts_tests': {
+        'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
+        'swarming': {
+          'shards': 8,
+        },
+      },
+    },
+
+    'gpu_dawn_webgpu_cts_dxc': {
+      'webgpu_cts_dxc_tests': {
+        'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
+        'args': [
+          '--use-dxc',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 14,
+        },
+      },
+      'webgpu_cts_dxc_with_validation_tests': {
+        'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
+        'args': [
+          '--enable-dawn-backend-validation',
+          '--use-dxc',
+        ],
+        'ci_only': True,
+        'swarming': {
+          'shards': 14,
+        },
+      },
+    },
+
+    'gpu_default_and_optional_win_media_foundation_specific_gtests': {
+      'media_foundation_browser_tests': {
+        'test': 'browser_tests',
+        'args': [
+          '--gtest_filter=MediaFoundationEncryptedMediaTest*',
+          '--use-gpu-in-tests',
+        ],
+      },
+    },
+
+    'gpu_default_and_optional_win_specific_gtests': {
+      'xr_browser_tests': {
+        'test': 'xr_browser_tests',
+        'args': [
+          '--ignore-runtime-requirements=*',
+        ],
+      },
+    },
+
+    'gpu_desktop_specific_gtests': {
+      'tab_capture_end2end_tests': {
+        'test': 'browser_tests',
+        'args': [
+          '--enable-gpu',
+          '--test-launcher-bot-mode',
+          '--test-launcher-jobs=1',
+          '--gtest_filter=TabCaptureApiPixelTest.EndToEnd*',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+    },
+
+    'gpu_fyi_and_optional_non_linux_gtests': {
+      'gpu_unittests': {},
+    },
+
+    'gpu_fyi_and_optional_win_specific_gtests': {
+      'gles2_conform_d3d9_test': {
+        'test': 'gles2_conform_test',
+        'args': [
+          '--use-gpu-in-tests',
+          '--use-angle=d3d9',
+        ],
+      },
+      'gles2_conform_gl_test': {
+        'test': 'gles2_conform_test',
+        'args': [
+          '--use-gpu-in-tests',
+          '--use-angle=gl',
+          '--disable-gpu-sandbox',
+        ],
+      },
+      'services_webnn_unittests': {
+        'test': 'services_unittests',
+        'args': [
+          '--gtest_filter=WebNN*',
+          '--use-gpu-in-tests',
+        ],
+      },
+    },
+
+    'gpu_fyi_mac_specific_gtests': {
+      'services_unittests': {
+        'args': [
+          '--gtest_filter=*Detection*',
+          '--use-gpu-in-tests',
+        ],
+      },
+    },
+
+    'gpu_fyi_vulkan_swiftshader_gtests': {
+      'vulkan_swiftshader_content_browsertests': {
+        'test': 'content_browsertests',
+        'args': [
+          '--enable-gpu',
+          '--test-launcher-bot-mode',
+          '--test-launcher-jobs=1',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter',
+          '--enable-features=UiGpuRasterization,Vulkan',
+          '--use-vulkan=swiftshader',
+          '--enable-gpu-rasterization',
+          '--disable-software-compositing-fallback',
+          '--disable-vulkan-fallback-to-gl-for-testing',
+          '--disable-headless-mode',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+    },
+
+    'gpu_gl_passthrough_ganesh_telemetry_tests': {
+      'context_lost_gl_passthrough_ganesh_tests': {
+        'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+      },
+      'expected_color_pixel_gl_passthrough_ganesh_test': {
+        'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite',
+        ],
+      },
+      'gpu_process_launch_tests': {
+        'telemetry_test_name': 'gpu_process',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'hardware_accelerated_feature_tests': {
+        'telemetry_test_name': 'hardware_accelerated_feature',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'pixel_skia_gold_gl_passthrough_ganesh_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+      },
+      'screenshot_sync_gl_passthrough_ganesh_tests': {
+        'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite',
+        ],
+      },
+    },
+
+    'gpu_gles2_conform_gtests': {
+      'gles2_conform_test': {
+        'args': [
+          '--use-gpu-in-tests',
+        ],
+      },
+    },
+
+    'gpu_info_collection_telemetry_tests': {
+      'info_collection_tests': {
+        'telemetry_test_name': 'info_collection',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--expected-vendor-id',
+          '${gpu_vendor_id}',
+          '$$MAGIC_SUBSTITUTION_GPUExpectedDeviceId',
+          '--extra-browser-args=--force_high_performance_gpu',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+      },
+    },
+
+    'gpu_mediapipe_passthrough_telemetry_tests': {
+      'mediapipe_passthrough_tests': {
+        'telemetry_test_name': 'mediapipe',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--force_higher_performance_gpu --use-cmd-decoder=passthrough --use-gl=angle',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+    },
+
+    'gpu_mediapipe_validating_telemetry_tests': {
+      'mediapipe_validating_tests': {
+        'telemetry_test_name': 'mediapipe',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--force_higher_performance_gpu --use-cmd-decoder=validating',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+    },
+
+    'gpu_metal_passthrough_ganesh_telemetry_tests': {
+      'context_lost_metal_passthrough_ganesh_tests': {
+        'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+      },
+      'expected_color_pixel_metal_passthrough_ganesh_test': {
+        'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite',
+        ],
+      },
+      'gpu_process_launch_tests': {
+        'telemetry_test_name': 'gpu_process',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'hardware_accelerated_feature_tests': {
+        'telemetry_test_name': 'hardware_accelerated_feature',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'pixel_skia_gold_metal_passthrough_ganesh_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+      },
+      'screenshot_sync_metal_passthrough_ganesh_tests': {
+        'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite',
+        ],
+      },
+    },
+
+    'gpu_metal_passthrough_graphite_telemetry_tests': {
+      'context_lost_metal_passthrough_graphite_tests': {
+        'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+      },
+      'expected_color_pixel_metal_passthrough_graphite_test': {
+        'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite',
+        ],
+      },
+      'gpu_process_launch_tests': {
+        'telemetry_test_name': 'gpu_process',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'hardware_accelerated_feature_tests': {
+        'telemetry_test_name': 'hardware_accelerated_feature',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'pixel_skia_gold_metal_passthrough_graphite_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+      },
+      'screenshot_sync_metal_passthrough_graphite_tests': {
+        'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite',
+        ],
+      },
+    },
+
+    'gpu_noop_sleep_telemetry_test': {
+      'noop_sleep_tests': {
+        'telemetry_test_name': 'noop_sleep',
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+      },
+    },
+
+    'gpu_passthrough_telemetry_tests': {
+      'context_lost_passthrough_tests': {
+        'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'expected_color_pixel_passthrough_test': {
+        'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+        ],
+        'android_args': [
+          '--extra-browser-args=--force-online-connection-state-for-indicator',
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'gpu_process_launch_tests': {
+        'telemetry_test_name': 'gpu_process',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'hardware_accelerated_feature_tests': {
+        'telemetry_test_name': 'hardware_accelerated_feature',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'pixel_skia_gold_passthrough_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '--extra-browser-args=--force-online-connection-state-for-indicator',
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'screenshot_sync_passthrough_tests': {
+        'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+        ],
+        'android_args': [
+          '--extra-browser-args=--force-online-connection-state-for-indicator',
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+    },
+
+    'gpu_pixel_passthrough_telemetry_tests': {
+      'expected_color_pixel_passthrough_test': {
+        'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+      },
+      'pixel_skia_gold_passthrough_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+      },
+    },
+
+    'gpu_skia_renderer_vulkan_passthrough_telemetry_tests': {
+      'vulkan_pixel_skia_gold_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-vulkan=native --disable-vulkan-fallback-to-gl-for-testing --enable-features=Vulkan --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '--extra-browser-args=--force-online-connection-state-for-indicator',
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+      },
+    },
+
+    'gpu_validating_telemetry_tests': {
+      'context_lost_validating_tests': {
+        'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=validating',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'expected_color_pixel_validating_test': {
+        'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=validating',
+        ],
+        'android_args': [
+          '--extra-browser-args=--force-online-connection-state-for-indicator',
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'gpu_process_launch_tests': {
+        'telemetry_test_name': 'gpu_process',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'hardware_accelerated_feature_tests': {
+        'telemetry_test_name': 'hardware_accelerated_feature',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'pixel_skia_gold_validating_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=validating',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '--extra-browser-args=--force-online-connection-state-for-indicator',
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+      'screenshot_sync_validating_tests': {
+        'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--extra-browser-args=--use-cmd-decoder=validating',
+        ],
+        'android_args': [
+          '--extra-browser-args=--force-online-connection-state-for-indicator',
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+    },
+
+    'gpu_vulkan_gtests': {
+      'vulkan_tests': {
+        'desktop_args': [
+          '--use-gpu-in-tests',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
+      },
+    },
+
+    'gpu_webcodecs_telemetry_test': {
+      'webcodecs_tests': {
+        'telemetry_test_name': 'webcodecs',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+    },
+
+    'gpu_webcodecs_validating_telemetry_test': {
+      'webcodecs_tests': {
+        'telemetry_test_name': 'webcodecs',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=validating',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+      },
+    },
+
+    'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests': {
+      'webgl2_conformance_d3d11_passthrough_tests': {
+        'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--webgl-conformance-version=2.0.1',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+      },
+    },
+
+    'gpu_webgl2_conformance_gl_passthrough_telemetry_tests': {
+      'webgl2_conformance_gl_passthrough_tests': {
+        'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--webgl-conformance-version=2.0.1',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+      },
+    },
+
+    'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': {
+      'webgl2_conformance_gles_passthrough_tests': {
+        'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--webgl-conformance-version=2.0.1',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+      },
+    },
+
+    'gpu_webgl2_conformance_metal_passthrough_telemetry_tests': {
+      'webgl2_conformance_metal_passthrough_tests': {
+        'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--webgl-conformance-version=2.0.1',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+          '--enable-metal-debug-layers',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+      },
+    },
+
+    'gpu_webgl2_conformance_validating_telemetry_tests': {
+      'webgl2_conformance_validating_tests': {
+        'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--webgl-conformance-version=2.0.1',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests': {
+      'webgl_conformance_d3d11_passthrough_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests': {
+      'webgl_conformance_d3d9_passthrough_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-gl=angle --use-angle=d3d9 --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_gl_passthrough_telemetry_tests': {
+      'webgl_conformance_gl_passthrough_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_gles_passthrough_telemetry_tests': {
+      'webgl_conformance_gles_passthrough_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+        'swarming': {
+          'shards': 6,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_metal_passthrough_telemetry_tests': {
+      'webgl_conformance_metal_passthrough_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+          '--enable-metal-debug-layers',
+        ],
+      },
+    },
+
+    'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests': {
+      'webgl_conformance_swangle_passthrough_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '--test-filter=conformance/rendering/gl-drawelements.html',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_swangle_passthrough_telemetry_tests': {
+      'webgl_conformance_swangle_passthrough_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough',
+          '--xvfb',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_telemetry_tests': {
+      'webgl_conformance_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+        'android_swarming': {
+          'shards': 12,
+        },
+        'chromeos_swarming': {
+          'shards': 20,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_validating_telemetry_tests': {
+      'webgl_conformance_validating_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'android_args': [
+          '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'lacros_args': [
+          '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
+          '--xvfb',
+          '--no-xvfb',
+          '--use-weston',
+          '--weston-use-gl',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+        'android_swarming': {
+          'shards': 6,
+        },
+      },
+    },
+
+    'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests': {
+      'webgl_conformance_vulkan_passthrough_tests': {
+        'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'headless_browser_gtests': {
+      'headless_browsertests': {},
+      'headless_unittests': {},
+    },
+
+    'ios_blink_tests': {
+      'absl_hardening_tests': {},
+      'angle_unittests': {
+        'use_isolated_scripts_api': True,
+      },
+      'base_unittests': {},
+      'blink_common_unittests': {},
+      'blink_fuzzer_unittests': {},
+      'blink_heap_unittests': {},
+      'blink_platform_unittests': {},
+      'blink_unittests': {},
+      'boringssl_crypto_tests': {},
+      'boringssl_ssl_tests': {},
+      'capture_unittests': {},
+      'cast_unittests': {},
+      'cc_unittests': {},
+      'components_browsertests': {},
+      'components_unittests': {},
+      'content_browsertests': {
+        'args': [
+          '--test-launcher-bot-mode',
+          '--test-launcher-filter-file=testing/buildbot/filters/ios.content_browsertests.filter',
+        ],
+        'timeout_sec': 14400,
+        'swarming': {
+          'shards': 8,
+          'expiration': 10800,
+          'hard_timeout': 14400,
+        },
+      },
+      'content_unittests': {},
+      'crashpad_tests': {},
+      'crypto_unittests': {},
+      'device_unittests': {},
+      'display_unittests': {},
+      'env_chromium_unittests': {},
+      'events_unittests': {},
+      'gcm_unit_tests': {},
+      'gfx_unittests': {},
+      'gin_unittests': {},
+      'gl_unittests': {},
+      'google_apis_unittests': {},
+      'gpu_unittests': {},
+      'gwp_asan_unittests': {},
+      'ipc_tests': {},
+      'latency_unittests': {},
+      'leveldb_unittests': {},
+      'libjingle_xmpp_unittests': {},
+      'liburlpattern_unittests': {},
+      'media_unittests': {},
+      'midi_unittests': {},
+      'mojo_unittests': {},
+      'net_unittests': {},
+      'perfetto_unittests': {},
+      'printing_unittests': {},
+      'services_unittests': {},
+      'shell_dialogs_unittests': {},
+      'skia_unittests': {},
+      'sql_unittests': {},
+      'storage_unittests': {},
+      'ui_base_unittests': {
+        'args': [
+          '--test-launcher-filter-file=testing/buildbot/filters/ios.ui_base_unittests.filter',
+        ],
+      },
+      'ui_touch_selection_unittests': {},
+      'ui_unittests': {},
+      'url_unittests': {},
+      'viz_unittests': {},
+      'wtf_unittests': {},
+      'zlib_unittests': {},
+    },
+
+    'ios_common_tests': {
+      'absl_hardening_tests': {},
+      'boringssl_crypto_tests': {},
+      'boringssl_ssl_tests': {},
+      'crashpad_tests': {},
+      'crypto_unittests': {},
+      'google_apis_unittests': {},
+      'ios_components_unittests': {},
+      'ios_net_unittests': {
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'ios_remoting_unittests': {},
+      'ios_testing_unittests': {},
+      'net_unittests': {},
+      'services_unittests': {},
+      'sql_unittests': {},
+      'url_unittests': {},
+    },
+
+    'ios_crash_xcuitests': {
+      'ios_crash_xcuitests_module': {},
+    },
+
+    'ios_cronet_tests': {
+      'cronet_test': {},
+    },
+
+    'ios_eg2_cq_tests': {
+      'ios_chrome_integration_eg2tests_module': {
+        'swarming': {
+          'shards': 8,
+        },
+      },
+      'ios_web_shell_eg2tests_module': {},
+    },
+
+    'ios_eg2_cq_tests_parallel': {
+      'ios_chrome_integration_eg2tests_module': {
+        'mixins': [
+          'ios_parallel_simulators',
+        ],
+        'swarming': {
+          'shards': 8,
+        },
+      },
+      'ios_web_shell_eg2tests_module': {},
+    },
+
+    'ios_eg2_tests': {
+      'ios_chrome_bookmarks_eg2tests_module': {},
+      'ios_chrome_settings_eg2tests_module': {
+        'swarming': {
+          'shards': 6,
+        },
+      },
+      'ios_chrome_signin_eg2tests_module': {
+        'swarming': {
+          'shards': 6,
+        },
+      },
+      'ios_chrome_smoke_eg2tests_module': {},
+      'ios_chrome_ui_eg2tests_module': {
+        'swarming': {
+          'shards': 12,
+        },
+      },
+      'ios_chrome_web_eg2tests_module': {
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'ios_showcase_eg2tests_module': {},
+    },
+
+    'ios_eg2_tests_parallel': {
+      'ios_chrome_bookmarks_eg2tests_module': {},
+      'ios_chrome_settings_eg2tests_module': {
+        'mixins': [
+          'ios_parallel_simulators',
+        ],
+        'swarming': {
+          'shards': 4,
+        },
+      },
+      'ios_chrome_signin_eg2tests_module': {
+        'swarming': {
+          'shards': 6,
+        },
+      },
+      'ios_chrome_smoke_eg2tests_module': {},
+      'ios_chrome_ui_eg2tests_module': {
+        'mixins': [
+          'ios_parallel_simulators',
+        ],
+        'swarming': {
+          'shards': 12,
+        },
+      },
+      'ios_chrome_web_eg2tests_module': {
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'ios_showcase_eg2tests_module': {},
+    },
+
+    'ios_remoting_fyi_unittests': {
+      'ios_remoting_unittests': {},
+    },
+
+    'ios_screen_size_dependent_tests': {
+      'base_unittests': {},
+      'components_unittests': {},
+      'gfx_unittests': {},
+      'ios_chrome_unittests': {},
+      'ios_web_inttests': {},
+      'ios_web_unittests': {},
+      'ios_web_view_inttests': {},
+      'ios_web_view_unittests': {},
+      'skia_unittests': {},
+      'ui_base_unittests': {},
+    },
+
+    'js_code_coverage_browser_tests': {
+      'js_code_coverage_browser_tests': {
+        'test': 'browser_tests',
+        'swarming': {
+          'shards': 16,
+        },
+      },
+    },
+
+    'lacros_all_tast_tests': {
+      'lacros_all_tast_tests': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'swarming': {
+          'idempotent': False,
+        },
+      },
+    },
+
+    'lacros_all_tast_tests_informational': {
+      'lacros_all_tast_tests_informational': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'swarming': {
+          'idempotent': False,
+        },
+      },
+    },
+
+    'lacros_cq_tast_tests_eve': {
+      'lacros_cq_tast_tests_eve': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'swarming': {
+          'idempotent': False,
+        },
+        'experiment_percentage': 5,
+      },
+    },
+
+    'lacros_device_or_vm_gtests': {
+      'aura_unittests': {},
+      'cc_unittests': {},
+      'interactive_ui_tests': {},
+      'ozone_unittests': {},
+      'vaapi_unittest': {
+        'args': [
+          '--stop-ui',
+          '--env-var',
+          'LIBVA_DRIVERS_PATH',
+          './',
+          '--env-var',
+          'LIBVA_DRIVER_NAME',
+          'libfake',
+          '--gtest_filter="VaapiTest.*"',
+        ],
+      },
+    },
+
+    'lacros_fyi_tast_tests': {
+      'lacros_fyi_tast_tests': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'swarming': {
+          'idempotent': False,
+        },
+      },
+    },
+
+    'lacros_skylab_amd64_fyi': {
+      'lacros_fyi_tast_tests': {
+        'tast_expr': '("group:mainline" && "dep:lacros" && !informational)',
+        'timeout_sec': 10800,
+      },
+      'ozone_unittests': {
+        'timeout_sec': 3600,
+      },
+    },
+
+    'lacros_skylab_arm_tests_fyi': {
+      'lacros_all_tast_tests': {
+        'tast_expr': '("group:mainline" && "dep:lacros" && !informational)',
+        'timeout_sec': 10800,
+      },
+      'ozone_unittests': {
+        'timeout_sec': 3600,
+      },
+      'viz_unittests': {
+        'timeout_sec': 3600,
+      },
+    },
+
+    'lacros_skylab_tests': {
+      'lacros_all_tast_tests': {
+        'tast_expr': '("group:mainline" && ("dep:lacros_stable" || "dep:lacros") && !informational)',
+        'test_level_retries': 2,
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'timeout_sec': 10800,
+        'shards': 2,
+      },
+    },
+
+    'lacros_skylab_tests_with_gtests': {
+      'chromeos_integration_tests': {},
+    },
+
+    'lacros_vm_gtests': {
+      'base_unittests': {},
+    },
+
+    'leak_detection_isolated_scripts': {
+      'memory.leak_detection': {
+        'test': 'performance_test_suite',
+        'override_compile_targets': [
+          'performance_test_suite',
+        ],
+        'args': [
+          '--pageset-repeat=1',
+          '--test-shard-map-filename=linux_leak_detection_shard_map.json',
+          '--upload-results',
+          '--output-format=histograms',
+          '--browser=release',
+          '--xvfb',
+        ],
+        'swarming': {
+          'shards': 10,
+          'expiration': 36000,
+          'hard_timeout': 10800,
+          'io_timeout': 3600,
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+          'args': [
+            '--smoke-test-mode',
+          ],
+        },
+      },
+    },
+
+    'linux_cfm_gtests': {
+      'chromeos_unittests': {},
+      'unit_tests': {},
+    },
+
+    'linux_chromeos_browser_tests_require_lacros': {
+      'browser_tests_require_lacros': {
+        'test': 'browser_tests',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter',
+          '--lacros-chrome-path=lacros_clang_x64',
+        ],
+        'swarming': {
+          'shards': 8,
+        },
+      },
+    },
+
+    'linux_chromeos_lacros_gtests': {
+      'chromeos_unittests': {},
+    },
+
+    'linux_chromeos_oobe_specific_tests': {
+      'oobe_only_browser_tests': {
+        'test': 'browser_tests',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+        'experiment_percentage': 100,
+      },
+    },
+
+    'linux_chromeos_specific_gtests': {
+      'ash_components_unittests': {},
+      'ash_crosapi_tests': {
+        'ci_only': True,
+      },
+      'ash_unittests': {
+        'swarming': {
+          'shards': 5,
+        },
+      },
+      'ash_webui_unittests': {},
+      'aura_unittests': {},
+      'chromeos_components_unittests': {},
+      'exo_unittests': {},
+      'gl_unittests_ozone': {},
+      'keyboard_unittests': {},
+      'ozone_gl_unittests': {
+        'args': [
+          '--ozone-platform=headless',
+        ],
+      },
+      'ozone_unittests': {},
+      'ozone_x11_unittests': {},
+      'shell_encryption_unittests': {},
+      'ui_chromeos_unittests': {},
+      'usage_time_limit_unittests': {
+        'experiment_percentage': 100,
+      },
+      'wayland_client_perftests': {},
+      'wayland_client_tests': {},
+    },
+
+    'linux_flavor_specific_chromium_gtests': {
+      'sandbox_linux_unittests': {},
+    },
+
+    'linux_lacros_chrome_browsertests_non_version_skew': {
+      'lacros_chrome_browsertests': {
+        'test': 'lacros_chrome_browsertests',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter',
+        ],
+      },
+      'lacros_chrome_browsertests_run_in_series': {
+        'test': 'lacros_chrome_browsertests_run_in_series',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'linux_lacros_chrome_browsertests_version_skew': {
+      'lacros_chrome_browsertests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter',
+        ],
+      },
+      'lacros_chrome_browsertests_run_in_series': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+    },
+
+    'linux_lacros_chrome_interactive_ui_tests_version_skew': {
+      'interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+      },
+    },
+
+    'linux_lacros_chrome_interactive_ui_tests_version_skew_beta': {
+      'interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+      },
+    },
+
+    'linux_lacros_chrome_interactive_ui_tests_version_skew_dev': {
+      'interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+      },
+    },
+
+    'linux_lacros_chrome_interactive_ui_tests_version_skew_stable': {
+      'interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+      },
+    },
+
+    'linux_lacros_specific_gtests': {
+      'lacros_chrome_unittests': {},
+      'ozone_unittests': {},
+    },
+
+    'linux_specific_chromium_isolated_scripts': {
+      'not_site_per_process_blink_web_tests': {
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--flag-specific=disable-site-isolation-trials',
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 8,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'not_site_per_process_blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--flag-specific=disable-site-isolation-trials',
+          '--num-retries=3',
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'webdriver_tests_suite': {
+        'test': 'chrome_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--test-type=wdspec',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'linux_specific_xr_gtests': {
+      'xr_browser_tests': {
+        'test': 'xr_browser_tests',
+      },
+    },
+
+    'live_companion_tests': {
+      'live_companion_tests': {
+        'test': 'browser_tests',
+        'override_compile_targets': [
+          'browser_tests',
+        ],
+        'args': [
+          '--gtest_filter=CompanionLiveTest.*',
+          '--run-live-tests',
+          '--run-manual',
+          '--sync-status-change-checker-timeout=600',
+          '--test-tiny-timeout=85000',
+          '--ui-test-action-timeout=90000',
+          '--ui-test-action-max-timeout=95000',
+          '--test-launcher-timeout=100000',
+          '--isolated-script-test-launcher-retry-limit=5',
+        ],
+        'swarming': {
+          'expiration': 3600,
+          'hard_timeout': 3600,
+        },
+      },
+    },
+
+    'mac_lsan_fyi_gtests': {
+      'absl_hardening_tests': {},
+      'accessibility_unittests': {},
+      'app_shell_unittests': {},
+      'base_unittests': {},
+      'blink_heap_unittests': {},
+      'blink_platform_unittests': {},
+      'blink_unittests': {},
+      'cc_unittests': {},
+      'components_unittests': {},
+      'content_unittests': {},
+      'crashpad_tests': {},
+      'cronet_unittests': {},
+      'device_unittests': {},
+      'net_unittests': {},
+    },
+
+    'mac_specific_chromium_gtests': {
+      'power_sampler_unittests': {},
+      'sandbox_unittests': {},
+      'updater_tests': {},
+      'xr_browser_tests': {
+        'test': 'xr_browser_tests',
+      },
+    },
+
+    'mac_specific_isolated_scripts': {
+      'mac_signing_tests': {},
+    },
+
+    'minidump_uploader_tests': {
+      'minidump_uploader_test': {
+        'experiment_percentage': 100,
+      },
+    },
+
+    'model_validation_tests': {
+      'model_validation_tests': {
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+        },
+      },
+    },
+
+    'mojo_python_unittests_isolated_scripts': {
+      'mojo_python_unittests': {
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'monochrome_public_apk_checker_isolated_script': {
+      'monochrome_public_apk_checker': {
+        'remove_mixins': [
+          'android_r',
+          'bullhead',
+          'flame',
+          'marshmallow',
+          'mdarcy',
+          'oreo_fleet',
+          'oreo_mr1_fleet',
+          'pie_fleet',
+          'walleye',
+        ],
+        'swarming': {
+          'dimensions': {
+            'os': 'Ubuntu-18.04',
+            'cpu': 'x86-64',
+            'device_os': None,
+            'device_os_flavor': None,
+            'device_playstore_version': None,
+            'device_type': None,
+          },
+        },
+      },
+    },
+
+    'network_sandbox_browser_tests': {
+      'browser_tests_network_sandbox': {
+        'test': 'browser_tests',
+        'args': [
+          '--enable-features=NetworkServiceSandbox',
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'components_browsertests_network_sandbox': {
+        'test': 'components_browsertests',
+        'args': [
+          '--enable-features=NetworkServiceSandbox',
+        ],
+      },
+      'content_browsertests_network_sandbox': {
+        'test': 'content_browsertests',
+        'args': [
+          '--enable-features=NetworkServiceSandbox',
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'interactive_ui_tests_network_sandbox': {
+        'test': 'interactive_ui_tests',
+        'args': [
+          '--enable-features=NetworkServiceSandbox',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'sync_integration_tests_network_sandbox': {
+        'test': 'sync_integration_tests',
+        'args': [
+          '--enable-features=NetworkServiceSandbox',
+        ],
+      },
+    },
+
+    'network_service_fyi_gtests': {
+      'network_service_web_request_proxy_browser_tests': {
+        'test': 'browser_tests',
+        'args': [
+          '--enable-features=ForceWebRequestProxyForTest',
+        ],
+        'swarming': {
+          'shards': 15,
+        },
+      },
+    },
+
+    'non_android_and_cast_and_chromeos_chromium_gtests': {
+      'cronet_tests': {},
+      'cronet_unittests': {},
+      'headless_browsertests': {},
+      'headless_unittests': {},
+    },
+
+    'non_android_chromium_gtests': {
+      'accessibility_unittests': {},
+      'app_shell_unittests': {},
+      'blink_fuzzer_unittests': {},
+      'browser_tests': {
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'chrome_app_unittests': {},
+      'chromedriver_unittests': {},
+      'extensions_browsertests': {},
+      'extensions_unittests': {},
+      'filesystem_service_unittests': {},
+      'interactive_ui_tests': {
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'message_center_unittests': {},
+      'nacl_loader_unittests': {},
+      'native_theme_unittests': {},
+      'pdf_unittests': {},
+      'ppapi_unittests': {},
+      'printing_unittests': {},
+      'remoting_unittests': {},
+      'service_manager_unittests': {},
+      'snapshot_unittests': {},
+      'sync_integration_tests': {
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'ui_unittests': {},
+      'views_unittests': {},
+    },
+
+    'non_android_chromium_gtests_no_nacl': {
+      'accessibility_unittests': {},
+      'app_shell_unittests': {},
+      'blink_fuzzer_unittests': {},
+      'browser_tests': {
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'chrome_app_unittests': {},
+      'chromedriver_unittests': {},
+      'extensions_browsertests': {},
+      'extensions_unittests': {},
+      'filesystem_service_unittests': {},
+      'interactive_ui_tests': {
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'message_center_unittests': {},
+      'native_theme_unittests': {},
+      'pdf_unittests': {},
+      'printing_unittests': {},
+      'remoting_unittests': {},
+      'service_manager_unittests': {},
+      'snapshot_unittests': {},
+      'sync_integration_tests': {
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'ui_unittests': {},
+      'views_unittests': {},
+    },
+
+    'non_android_chromium_gtests_skia_gold': {
+      'views_examples_unittests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
+      },
+    },
+
+    'oop_network_service_tests': {
+      'oop_network_service_content_browsertests': {
+        'test': 'content_browsertests',
+        'args': [
+          '--enable-features=NetworkServiceOutOfProcessMemoryThreshold:network_service_oop_threshold_mb/1077',
+          '--disable-features=NetworkServiceInProcess2',
+        ],
+        'swarming': {
+          'shards': 25,
+        },
+      },
+    },
+
+    'optimization_guide_android_gtests': {
+      'optimization_guide_components_unittests': {
+        'test': 'components_unittests',
+        'args': [
+          '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*',
+        ],
+      },
+    },
+
+    'optimization_guide_gtests': {
+      'optimization_guide_browser_tests': {
+        'test': 'browser_tests',
+        'args': [
+          '--gtest_filter=*OptimizationGuide*:*PageContentAnnotations*',
+        ],
+      },
+      'optimization_guide_components_unittests': {
+        'test': 'components_unittests',
+        'args': [
+          '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*',
+        ],
+      },
+      'optimization_guide_unittests': {},
+    },
+
+    'perfetto_gtests': {
+      'base_unittests': {},
+      'browser_tests': {
+        'args': [
+          '--gtest_filter=ChromeTracingDelegateBrowserTest.*',
+        ],
+      },
+      'content_browsertests': {
+        'swarming': {
+          'shards': 8,
+        },
+        'android_swarming': {
+          'shards': 15,
+        },
+      },
+      'perfetto_unittests': {},
+      'services_unittests': {},
+    },
+
+    'perfetto_gtests_android': {
+      'android_browsertests': {
+        'args': [
+          '--gtest_filter=StartupMetricsTest.*',
+        ],
+      },
+      'base_unittests': {},
+      'content_browsertests': {
+        'swarming': {
+          'shards': 8,
+        },
+        'android_swarming': {
+          'shards': 15,
+        },
+      },
+      'perfetto_unittests': {},
+      'services_unittests': {},
+    },
+
+    'performance_smoke_test_isolated_scripts': {
+      'performance_test_suite': {
+        'args': [
+          '--pageset-repeat=1',
+          '--test-shard-map-filename=smoke_test_benchmark_shard_map.json',
+        ],
+        'swarming': {
+          'shards': 2,
+          'hard_timeout': 960,
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+          'args': [
+            '--smoke-test-mode',
+          ],
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'pixel_browser_tests_gtests': {
+      'pixel_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'args': [
+          '--browser-ui-tests-verify-pixels',
+          '--enable-pixel-output-in-tests',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter',
+          '--test-launcher-jobs=1',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'pixel_interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'args': [
+          '--browser-ui-tests-verify-pixels',
+          '--enable-pixel-output-in-tests',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter',
+        ],
+      },
+    },
+
+    'pixel_experimental_browser_tests_gtests': {
+      'pixel_experimental_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'args': [
+          '--browser-ui-tests-verify-pixels',
+          '--enable-pixel-output-in-tests',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.pixel_tests.filter',
+        ],
+        'experiment_percentage': 100,
+      },
+    },
+
+    'private_code_failure_test_isolated_scripts': {
+      'private_code_failure_test': {},
+    },
+
+    'public_build_scripts': {
+      'checkbins': {
+        'script': 'checkbins.py',
+      },
+    },
+
+    'pytype_tests': {
+      'blink_pytype': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'fuchsia_pytype': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'gold_common_pytype': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'gpu_pytype': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+      'testing_pytype': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+      },
+    },
+
+    'rust_common_gtests': {
+      'base_unittests': {},
+      'components_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/rust.components_unittests.filter',
+        ],
+      },
+      'mojo_rust_integration_unittests': {},
+      'mojo_rust_unittests': {},
+      'rust_gtest_interop_unittests': {},
+      'test_cpp_including_rust_unittests': {
+        'test': 'test_cpp_including_rust_unittests',
+      },
+      'test_serde_json_lenient': {
+        'test': 'test_serde_json_lenient',
+      },
+    },
+
+    'rust_native_tests': {
+      'build_rust_tests': {
+        'test': 'build_rust_tests',
+      },
+    },
+
+    'site_isolation_android_fyi_gtests': {
+      'site_per_process_android_browsertests': {
+        'test': 'android_browsertests',
+        'args': [
+          '--site-per-process',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+      },
+      'site_per_process_chrome_public_test_apk': {
+        'test': 'chrome_public_test_apk',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--site-per-process',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+      },
+      'site_per_process_chrome_public_unit_test_apk': {
+        'test': 'chrome_public_unit_test_apk',
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'args': [
+          '--site-per-process',
+        ],
+      },
+      'site_per_process_components_browsertests': {
+        'test': 'components_browsertests',
+        'args': [
+          '--site-per-process',
+        ],
+      },
+      'site_per_process_components_unittests': {
+        'test': 'components_unittests',
+        'args': [
+          '--site-per-process',
+        ],
+        'swarming': {
+          'shards': 5,
+        },
+      },
+      'site_per_process_content_browsertests': {
+        'test': 'content_browsertests',
+        'args': [
+          '--site-per-process',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/site_isolation_android.content_browsertests.filter',
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+      },
+      'site_per_process_content_shell_test_apk': {
+        'test': 'content_shell_test_apk',
+        'args': [
+          '--site-per-process',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+      },
+      'site_per_process_content_unittests': {
+        'test': 'content_unittests',
+        'args': [
+          '--site-per-process',
+        ],
+      },
+      'site_per_process_unit_tests': {
+        'test': 'unit_tests',
+        'args': [
+          '--site-per-process',
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+      },
+    },
+
+    'swangle_gtests': {
+      'angle_deqp_egl_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles2_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles31_rotate180_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles31_rotate270_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles31_rotate90_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles31_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles3_rotate180_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles3_rotate270_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles3_rotate90_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_gles3_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'swarming': {
+          'shards': 4,
+        },
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_khr_gles2_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_khr_gles31_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_deqp_khr_gles3_tests': {
+        'args': [
+          '--use-angle=swiftshader',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+      'angle_end2end_tests': {
+        'args': [
+          '--gtest_filter=*Vulkan_SwiftShader*',
+        ],
+        'use_isolated_scripts_api': True,
+      },
+    },
+
+    'system_webview_shell_instrumentation_tests': {
+      'system_webview_shell_layout_test_apk': {},
+    },
+
+    'system_webview_wpt': {
+      'system_webview_wpt': {
+        'results_handler': 'layout tests',
+        'args': [
+          '--no-wpt-internal',
+        ],
+        'swarming': {
+          'shards': 25,
+          'expiration': 18000,
+          'hard_timeout': 14400,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'telemetry_android_minidump_unittests_isolated_scripts': {
+      'telemetry_chromium_minidump_unittests': {
+        'test': 'telemetry_perf_unittests_android_chrome',
+        'args': [
+          'BrowserMinidumpTest',
+          '--browser=android-chromium',
+          '-v',
+          '--passthrough',
+          '--retry-limit=2',
+        ],
+        'resultdb': {
+          'enable': True,
+        },
+      },
+      'telemetry_monochrome_minidump_unittests': {
+        'test': 'telemetry_perf_unittests_android_monochrome',
+        'args': [
+          'BrowserMinidumpTest',
+          '--browser=android-chromium-monochrome',
+          '-v',
+          '--passthrough',
+          '--retry-limit=2',
+        ],
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'telemetry_desktop_minidump_unittests_isolated_scripts': {
+      'telemetry_desktop_minidump_unittests': {
+        'test': 'telemetry_perf_unittests',
+        'args': [
+          'BrowserMinidumpTest',
+          '-v',
+          '--passthrough',
+          '--retry-limit=2',
+        ],
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'telemetry_perf_unittests_isolated_scripts': {
+      'telemetry_perf_unittests': {
+        'args': [
+          '--extra-browser-args=--enable-crashpad',
+        ],
+        'swarming': {
+          'shards': 12,
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'telemetry_perf_unittests_isolated_scripts_android': {
+      'telemetry_perf_unittests': {
+        'test': 'telemetry_perf_unittests_android_chrome',
+        'args': [
+          '--extra-browser-args=--enable-crashpad',
+        ],
+        'swarming': {
+          'shards': 12,
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'telemetry_perf_unittests_isolated_scripts_xvfb': {
+      'telemetry_perf_unittests': {
+        'args': [
+          '--extra-browser-args=--enable-crashpad',
+          '--xvfb',
+        ],
+        'swarming': {
+          'shards': 12,
+          'idempotent': False,
+        },
+        'resultdb': {
+          'enable': True,
+        },
+      },
+    },
+
+    'test_traffic_annotation_auditor_script': {
+      'test_traffic_annotation_auditor': {
+        'script': 'test_traffic_annotation_auditor.py',
+      },
+    },
+
+    'updater_gtests_linux': {
+      'updater_tests': {
+        'mixins': [
+          'updater-default-pool',
+        ],
+      },
+    },
+
+    'updater_gtests_mac': {
+      'updater_tests': {
+        'mixins': [
+          'updater-default-pool',
+        ],
+      },
+      'updater_tests_system': {
+        'mixins': [
+          'updater-mac-pool',
+        ],
+      },
+    },
+
+    'updater_gtests_win': {
+      'updater_tests': {
+        'mixins': [
+          'integrity_high',
+          'updater-default-pool',
+        ],
+      },
+      'updater_tests_system': {
+        'mixins': [
+          'integrity_high',
+          'updater-default-pool',
+        ],
+      },
+    },
+
+    'updater_gtests_win_uac': {
+      'updater_tests_system': {
+        'mixins': [
+          'integrity_high',
+          'updater-win-uac-pool',
+        ],
+      },
+      'updater_tests_win_uac': {
+        'mixins': [
+          'updater-win-uac-pool',
+        ],
+      },
+    },
+
+    'upload_perfetto': {
+      'upload_trace_processor': {},
+    },
+
+    'variations_smoke_tests': {
+      'variations_smoke_tests': {
+        'test': 'variations_smoke_tests',
+        'mixins': [
+          'skia_gold_test',
+        ],
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+        },
+      },
+    },
+
+    'vr_android_specific_chromium_tests': {
+      'chrome_public_test_vr_apk': {
+        'args': [
+          '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json',
+          '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk',
+        ],
+        'swarming': {
+          'shards': 2,
+        },
+      },
+      'vr_android_unittests': {},
+    },
+
+    'vr_platform_specific_chromium_gtests': {
+      'vr_common_unittests': {},
+    },
+
+    'vulkan_swiftshader_isolated_scripts': {
+      'vulkan_swiftshader_blink_web_tests': {
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+          '--skipped=always',
+          '--flag-specific=skia-vulkan-swiftshader',
+        ],
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'web_engine_gtests': {
+      'cast_runner_browsertests': {},
+      'cast_runner_integration_tests': {},
+      'cast_runner_unittests': {},
+      'web_engine_browsertests': {},
+      'web_engine_integration_tests': {
+        'args': [
+          '--test-arg=--vmodule=test_navigation_listener=1',
+        ],
+      },
+      'web_engine_unittests': {},
+    },
+
+    'webrtc_chromium_baremetal_gtests': {
+      'capture_unittests': {
+        'args': [
+          '--enable-logging',
+          '--v=1',
+          '--test-launcher-jobs=1',
+          '--test-launcher-print-test-stdio=always',
+        ],
+        'swarming': {
+          'dimensions': {
+            'pool': 'WebRTC-chromium',
+          },
+        },
+      },
+    },
+
+    'webrtc_chromium_gtests': {
+      'browser_tests': {
+        'args': [
+          '--gtest_filter=WebRtcStatsPerfBrowserTest.*:WebRtcVideoDisplayPerfBrowserTests*:WebRtcVideoQualityBrowserTests*:WebRtcVideoHighBitrateBrowserTest*:WebRtcWebcamBrowserTests*',
+          '--run-manual',
+          '--ui-test-action-max-timeout=300000',
+          '--test-launcher-timeout=350000',
+          '--test-launcher-jobs=1',
+          '--test-launcher-bot-mode',
+          '--test-launcher-print-test-stdio=always',
+        ],
+      },
+      'browser_tests_functional': {
+        'test': 'browser_tests',
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/webrtc_functional.browser_tests.filter',
+          '--run-manual',
+          '--test-launcher-jobs=1',
+        ],
+      },
+      'content_browsertests': {
+        'args': [
+          '--gtest_filter=WebRtc*',
+        ],
+      },
+      'content_browsertests_sequential': {
+        'test': 'content_browsertests',
+        'args': [
+          '--gtest_filter=UsingRealWebcam*',
+          '--run-manual',
+          '--test-launcher-jobs=1',
+        ],
+      },
+      'content_browsertests_stress': {
+        'test': 'content_browsertests',
+        'args': [
+          '--gtest_filter=WebRtc*MANUAL*:-UsingRealWebcam*',
+          '--run-manual',
+          '--ui-test-action-max-timeout=110000',
+          '--test-launcher-timeout=120000',
+        ],
+      },
+      'content_unittests': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/webrtc.content_unittests.filter',
+        ],
+      },
+      'remoting_unittests': {
+        'args': [
+          '--gtest_filter=Webrtc*',
+        ],
+      },
+    },
+
+    'webrtc_chromium_simple_gtests': {
+      'content_browsertests': {
+        'args': [
+          '--gtest_filter=WebRtc*',
+        ],
+      },
+      'content_browsertests_sequential': {
+        'test': 'content_browsertests',
+        'args': [
+          '--gtest_filter=UsingRealWebcam*',
+          '--run-manual',
+          '--test-launcher-jobs=1',
+        ],
+      },
+    },
+
+    'webrtc_chromium_wpt_tests': {
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
+        'args': [
+          '--num-retries=3',
+          '-t',
+          'Release',
+          'external/wpt/webrtc',
+          'external/wpt/webrtc-encoded-transform',
+          'external/wpt/webrtc-extensions',
+          'external/wpt/webrtc-priority',
+          'external/wpt/webrtc-stats',
+          'external/wpt/webrtc-svc',
+        ],
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'webview_64_cts_tests_gtest': {
+      'webview_64_cts_tests': {
+        'swarming': {
+          'shards': 2,
+          'cipd_packages': [
+            {
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
+              'location': 'android_webview/tools/cts_archive',
+              'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
+            },
+          ],
+        },
+      },
+    },
+
+    'webview_bot_instrumentation_test_apk_gtest': {
+      'webview_instrumentation_test_apk': {
+        'args': [
+          '--use-apk-under-test-flags-file',
+        ],
+        'swarming': {
+          'shards': 12,
+        },
+      },
+    },
+
+    'webview_bot_instrumentation_test_apk_no_field_trial_gtest': {
+      'webview_instrumentation_test_apk_no_field_trial': {
+        'test': 'webview_instrumentation_test_apk',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'swarming': {
+          'shards': 12,
+        },
+      },
+    },
+
+    'webview_bot_unittests_gtest': {
+      'android_webview_unittests': {},
+    },
+
+    'webview_cts_tests_gtest': {
+      'webview_cts_tests': {
+        'swarming': {
+          'shards': 2,
+          'cipd_packages': [
+            {
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
+              'location': 'android_webview/tools/cts_archive',
+              'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
+            },
+          ],
+        },
+      },
+    },
+
+    'webview_cts_tests_gtest_no_field_trial': {
+      'webview_cts_tests_no_field_trial': {
+        'test': 'webview_cts_tests',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'swarming': {
+          'shards': 2,
+          'cipd_packages': [
+            {
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
+              'location': 'android_webview/tools/cts_archive',
+              'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
+            },
+          ],
+        },
+      },
+    },
+
+    'webview_trichrome_64_cts_field_trial_tests': {
+      'webview_trichrome_64_cts_tests': {
+        'args': [
+          '--store-data-dependencies-in-temp',
+        ],
+        'swarming': {
+          'shards': 2,
+          'cipd_packages': [
+            {
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
+              'location': 'android_webview/tools/cts_archive',
+              'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
+            },
+          ],
+        },
+      },
+    },
+
+    'webview_trichrome_64_cts_tests': {
+      'webview_trichrome_64_cts_tests': {
+        'swarming': {
+          'shards': 2,
+          'cipd_packages': [
+            {
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
+              'location': 'android_webview/tools/cts_archive',
+              'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
+            },
+          ],
+        },
+      },
+    },
+
+    'webview_trichrome_64_cts_tests_no_field_trial': {
+      'webview_trichrome_64_cts_tests_no_field_trial': {
+        'test': 'webview_trichrome_64_cts_tests',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+        'swarming': {
+          'shards': 2,
+          'cipd_packages': [
+            {
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
+              'location': 'android_webview/tools/cts_archive',
+              'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
+            },
+          ],
+        },
+      },
+    },
+
+    'webview_trichrome_cts_tests': {
+      'webview_trichrome_cts_tests': {
+        'swarming': {
+          'cipd_packages': [
+            {
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
+              'location': 'android_webview/tools/cts_archive',
+              'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
+            },
+          ],
+        },
+      },
+    },
+
+    'webview_ui_instrumentation_tests': {
+      'webview_ui_test_app_test_apk': {},
+    },
+
+    'webview_ui_instrumentation_tests_no_field_trial': {
+      'webview_ui_test_app_test_apk_no_field_trial': {
+        'test': 'webview_ui_test_app_test_apk',
+        'args': [
+          '--disable-field-trial-config',
+        ],
+      },
+    },
+
+    'win_specific_chromium_gtests': {
+      'chrome_elf_unittests': {},
+      'courgette_unittests': {},
+      'delayloads_unittests': {},
+      'elevation_service_unittests': {},
+      'gcp_unittests': {},
+      'install_static_unittests': {},
+      'installer_util_unittests': {
+        'swarming': {
+          'dimensions': {
+            'integrity': 'high',
+          },
+        },
+      },
+      'notification_helper_unittests': {},
+      'sbox_integration_tests': {
+        'swarming': {
+          'dimensions': {
+            'integrity': 'high',
+          },
+        },
+      },
+      'sbox_unittests': {},
+      'sbox_validation_tests': {},
+      'setup_unittests': {
+        'swarming': {
+          'dimensions': {
+            'integrity': 'high',
+          },
+        },
+      },
+      'updater_tests': {},
+      'updater_tests_system': {},
+      'zucchini_unittests': {},
+    },
+
+    'win_specific_isolated_scripts': {
+      'mini_installer_tests': {
+        'swarming': {
+          'dimensions': {
+            'integrity': 'high',
+          },
+        },
+      },
+      'polymer_tools_python_unittests': {
+        'experiment_percentage': 0,
+      },
+    },
+
+    'win_specific_xr_perf_tests': {
+      'xr.webxr.static': {
+        'test': 'vr_perf_tests',
+        'args': [
+          '--benchmarks=xr.webxr.static',
+          '-v',
+          '--upload-results',
+          '--output-format=histograms',
+          '--browser=release_x64',
+        ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+        'experiment_percentage': 100,
+      },
+    },
+
+    'wpt_tests_ios': {
+      'wpt_tests_ios': {
+        'test': 'chrome_ios_wpt',
+        'results_handler': 'layout tests',
+        'args': [
+          '--no-wpt-internal',
+        ],
+        'swarming': {
+          'shards': 15,
+          'expiration': 18000,
+          'hard_timeout': 14400,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+        'experiment_percentage': 100,
+      },
+    },
+
+    'wpt_web_tests': {
+      'wpt_tests_suite': {
+        'test': 'chrome_wpt_tests',
+        'results_handler': 'layout tests',
+        'swarming': {
+          'shards': 15,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'wpt_web_tests_android': {
+      'chrome_public_wpt': {
+        'results_handler': 'layout tests',
+        'swarming': {
+          'shards': 15,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+      'system_webview_wpt': {
+        'results_handler': 'layout tests',
+        'swarming': {
+          'shards': 15,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'wpt_web_tests_content_shell': {
+      'wpt_tests_suite': {
+        'test': 'content_shell_wpt',
+        'results_handler': 'layout tests',
+        'swarming': {
+          'shards': 15,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'wpt_web_tests_enable_leak_detection': {
+      'wpt_tests_suite': {
+        'test': 'content_shell_wpt',
+        'results_handler': 'layout tests',
+        'args': [
+          '--enable-leak-detection',
+        ],
+        'swarming': {
+          'shards': 15,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+        'experiment_percentage': 100,
+      },
+    },
+
+    'wpt_web_tests_highdpi': {
+      'wpt_tests_suite_highdpi': {
+        'test': 'content_shell_wpt',
+        'results_handler': 'layout tests',
+        'args': [
+          '--flag-specific',
+          'highdpi',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'wpt_web_tests_identity': {
+      'wpt_tests_suite': {
+        'test': 'chrome_wpt_tests',
+        'results_handler': 'layout tests',
+        'args': [
+          '--no-wpt-internal',
+          'webauthn/',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+
+    'wpt_web_tests_input': {
+      'wpt_tests_suite': {
+        'test': 'chrome_wpt_tests',
+        'results_handler': 'layout tests',
+        'args': [
+          '--no-wpt-internal',
+          'infrastructure/testdriver/actions/',
+          'input-events/',
+          'pointerevents/',
+          'touch-events/',
+          'uievents/',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+        'experiment_percentage': 100,
+      },
+    },
+
+    'wpt_web_tests_not_site_per_process': {
+      'wpt_tests_suite_not_site_per_process': {
+        'test': 'content_shell_wpt',
+        'results_handler': 'layout tests',
+        'args': [
+          '--child-processes=8',
+          '--flag-specific',
+          'disable-site-isolation-trials',
+        ],
+        'swarming': {
+          'shards': 10,
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
+      },
+    },
+  },
+
+  'compound_suites': {
+
+    'android_10_rel_gtests': [
+      'android_trichrome_smoke_tests',
+      'android_ar_gtests',
+      'android_ddready_vr_gtests',
+    ],
+
+    'android_12_dbg_emulator_gtests': [
+      'android_trichrome_smoke_tests',
+    ],
+
+    'android_marshmallow_gtests': [
+      'android_smoke_tests',
+      'android_specific_chromium_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chrome_public_tests',
+      'linux_flavor_specific_chromium_gtests',
+      'vr_android_specific_chromium_tests',
+      'vr_platform_specific_chromium_gtests',
+    ],
+
+    'android_nougat_emulator_gtests': [
+      'android_emulator_specific_chrome_public_tests',
+      'android_monochrome_smoke_tests',
+      'android_smoke_tests',
+      'android_specific_chromium_gtests',
+      'android_wpr_record_replay_tests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'linux_flavor_specific_chromium_gtests',
+      'system_webview_shell_instrumentation_tests',
+      'webview_cts_tests_gtest',
+      'webview_ui_instrumentation_tests',
+    ],
+
+    'android_nougat_gtests': [
+      'android_ar_gtests',
+      'android_ddready_vr_gtests',
+      'android_monochrome_smoke_tests',
+      'android_smoke_tests',
+    ],
+
+    'android_oreo_gtests': [
+      'android_ar_gtests',
+      'android_ddready_vr_gtests',
+      'android_monochrome_smoke_tests',
+      'android_oreo_standard_gtests',
+      'android_smoke_tests',
+    ],
+
+    'android_pie_coverage_instrumentation_tests': [
+      'android_smoke_tests',
+      'android_specific_coverage_java_tests',
+      'chrome_public_tests',
+      'vr_android_specific_chromium_tests',
+      'webview_ui_instrumentation_tests',
+    ],
+
+    'android_pie_gtests': [
+      'android_ar_gtests',
+      'android_ddready_vr_gtests',
+      'android_monochrome_smoke_tests',
+      'android_smoke_tests',
+      'chromium_tracing_gtests',
+    ],
+
+    'android_pie_rel_emulator_gtests': [
+      'android_emulator_specific_chrome_public_tests',
+      'android_monochrome_smoke_tests',
+      'android_smoke_tests',
+      'android_specific_chromium_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'linux_flavor_specific_chromium_gtests',
+      'system_webview_shell_instrumentation_tests',
+      'webview_cts_tests_gtest',
+      'webview_ui_instrumentation_tests',
+    ],
+
+    'android_pie_rel_gtests': [
+      'android_pie_rel_reduced_capacity_gtests',
+      'android_monochrome_smoke_tests',
+      'android_smoke_tests',
+      'chrome_public_tests',
+      'system_webview_shell_instrumentation_tests',
+      'webview_64_cts_tests_gtest',
+      'webview_ui_instrumentation_tests',
+    ],
+
+    'bfcache_android_gtests': [
+      'bfcache_android_specific_gtests',
+      'bfcache_generic_gtests',
+    ],
+
+    'bfcache_linux_gtests': [
+      'bfcache_generic_gtests',
+      'bfcache_linux_specific_gtests',
+    ],
+
+    'chrome_linux_isolated_script_tests': [
+      'chrome_isolated_script_tests',
+      'chrome_private_code_test_isolated_scripts',
+    ],
+
+    'chromeos_device_gtests': [
+      'chromeos_browser_all_tast_tests',
+      'chromeos_browser_integration_tests',
+      'chromeos_device_only_gtests',
+    ],
+
+    'chromeos_device_no_gtests': [
+      'chromeos_browser_all_tast_tests',
+      'chromeos_browser_integration_tests',
+    ],
+
+    'chromeos_vm_gtests': [
+      'chromeos_browser_all_tast_tests',
+      'chromeos_browser_integration_tests',
+      'chromeos_system_friendly_gtests',
+      'chromeos_integration_tests',
+    ],
+
+    'chromium_android_gtests': [
+      'android_smoke_tests',
+      'android_specific_chromium_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chrome_public_tests',
+      'linux_flavor_specific_chromium_gtests',
+      'vr_android_specific_chromium_tests',
+      'vr_platform_specific_chromium_gtests',
+    ],
+
+    'chromium_dbg_isolated_scripts': [
+      'desktop_chromium_isolated_scripts',
+      'performance_smoke_test_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts',
+    ],
+
+    'chromium_linux_and_gl_and_vulkan_gtests': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_chromeos_only',
+      'chromium_gtests_for_linux_and_mac_only',
+      'chromium_gtests_for_linux_only',
+      'chromium_gtests_for_win_and_linux_only',
+      'linux_flavor_specific_chromium_gtests',
+      'linux_specific_xr_gtests',
+      'gl_gtests_passthrough',
+      'gpu_fyi_vulkan_swiftshader_gtests',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests',
+      'vr_platform_specific_chromium_gtests',
+    ],
+
+    'chromium_linux_and_gl_gtests': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_chromeos_only',
+      'chromium_gtests_for_linux_and_mac_only',
+      'chromium_gtests_for_linux_only',
+      'chromium_gtests_for_win_and_linux_only',
+      'linux_flavor_specific_chromium_gtests',
+      'linux_specific_xr_gtests',
+      'gl_gtests_passthrough',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests',
+      'vr_platform_specific_chromium_gtests',
+    ],
+
+    'chromium_linux_blink_rel_isolated_scripts': [
+      'chromium_webkit_isolated_scripts',
+      'linux_specific_chromium_isolated_scripts',
+      'vulkan_swiftshader_isolated_scripts',
+      'chromium_web_tests_high_dpi_isolated_scripts',
+    ],
+
+    'chromium_linux_cast_audio_gtests': [
+      'cast_audio_specific_chromium_gtests',
+      'chromium_gtests',
+      'linux_flavor_specific_chromium_gtests',
+    ],
+
+    'chromium_linux_cast_video_gtests': [
+      'cast_audio_specific_chromium_gtests',
+      'cast_video_specific_chromium_gtests',
+      'chromium_gtests',
+      'linux_flavor_specific_chromium_gtests',
+    ],
+
+    'chromium_linux_dbg_isolated_scripts': [
+      'desktop_chromium_isolated_scripts',
+      'linux_specific_chromium_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts',
+    ],
+
+    'chromium_linux_gtests': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_chromeos_only',
+      'chromium_gtests_for_linux_and_mac_only',
+      'chromium_gtests_for_linux_only',
+      'chromium_gtests_for_win_and_linux_only',
+      'linux_flavor_specific_chromium_gtests',
+      'linux_specific_xr_gtests',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests',
+      'vr_platform_specific_chromium_gtests',
+    ],
+
+    'chromium_linux_gtests_once': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_chromeos_only',
+      'chromium_gtests_for_linux_and_mac_only',
+      'chromium_gtests_for_linux_only',
+      'chromium_gtests_for_win_and_linux_only',
+      'cr23_linux_gtests',
+      'linux_flavor_specific_chromium_gtests',
+      'linux_specific_xr_gtests',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests',
+      'vr_platform_specific_chromium_gtests',
+    ],
+
+    'chromium_linux_rel_isolated_scripts': [
+      'chromedriver_py_tests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'linux_specific_chromium_isolated_scripts',
+      'mojo_python_unittests_isolated_scripts',
+      'pytype_tests',
+      'telemetry_perf_unittests_isolated_scripts',
+      'vulkan_swiftshader_isolated_scripts',
+      'chromium_web_tests_high_dpi_isolated_scripts',
+    ],
+
+    'chromium_linux_rel_isolated_scripts_code_coverage': [
+      'chromedriver_py_tests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'linux_specific_chromium_isolated_scripts',
+      'mojo_python_unittests_isolated_scripts',
+      'pytype_tests',
+      'telemetry_perf_unittests_isolated_scripts_xvfb',
+      'vulkan_swiftshader_isolated_scripts',
+      'chromium_web_tests_high_dpi_isolated_scripts',
+      'gpu_dawn_webgpu_blink_web_tests',
+    ],
+
+    'chromium_linux_rel_isolated_scripts_once': [
+      'chromedriver_py_tests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'desktop_once_isolated_scripts',
+      'linux_specific_chromium_isolated_scripts',
+      'mojo_python_unittests_isolated_scripts',
+      'pytype_tests',
+      'telemetry_perf_unittests_isolated_scripts',
+      'vulkan_swiftshader_isolated_scripts',
+      'chromium_web_tests_high_dpi_isolated_scripts',
+      'wpt_web_tests_content_shell',
+      'wpt_web_tests_highdpi',
+    ],
+
+    'chromium_mac_gtests': [
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_mac_only',
+      'mac_specific_chromium_gtests',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests',
+    ],
+
+    'chromium_mac_gtests_no_nacl': [
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_mac_only',
+      'mac_specific_chromium_gtests',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests_no_nacl',
+    ],
+
+    'chromium_mac_gtests_no_nacl_once': [
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'cr23_mac_gtests',
+      'mac_specific_chromium_gtests',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests_no_nacl',
+    ],
+
+    'chromium_mac_rel_isolated_scripts': [
+      'chromedriver_py_tests_isolated_scripts',
+      'components_perftests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'mac_specific_isolated_scripts',
+      'mojo_python_unittests_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts',
+    ],
+
+    'chromium_mac_rel_isolated_scripts_and_sizes': [
+      'chrome_sizes',
+      'chromedriver_py_tests_isolated_scripts',
+      'components_perftests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'mac_specific_isolated_scripts',
+      'mojo_python_unittests_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts',
+    ],
+
+    'chromium_mac_rel_isolated_scripts_code_coverage': [
+    ],
+
+    'chromium_mac_rel_isolated_scripts_once': [
+      'chromedriver_py_tests_isolated_scripts',
+      'components_perftests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'desktop_once_isolated_scripts',
+      'mac_specific_isolated_scripts',
+      'mojo_python_unittests_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts',
+      'wpt_web_tests_content_shell',
+    ],
+
+    'chromium_win10_gtests': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_win_and_linux_only',
+      'cr23_pixel_browser_tests_gtests',
+      'fieldtrial_browser_tests',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests',
+      'non_android_chromium_gtests_skia_gold',
+      'pixel_browser_tests_gtests',
+      'vr_platform_specific_chromium_gtests',
+      'win_specific_chromium_gtests',
+    ],
+
+    'chromium_win10_gtests_once': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_win_and_linux_only',
+      'cr23_pixel_browser_tests_gtests',
+      'cr23_win_gtests',
+      'fieldtrial_browser_tests',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests',
+      'non_android_chromium_gtests_skia_gold',
+      'pixel_browser_tests_gtests',
+      'vr_platform_specific_chromium_gtests',
+      'win_specific_chromium_gtests',
+    ],
+
+    'chromium_win_dbg_isolated_scripts': [
+      'chromedriver_py_tests_isolated_scripts',
+      'components_perftests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'performance_smoke_test_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts',
+    ],
+
+    'chromium_win_gtests': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_win_and_linux_only',
+      'non_android_and_cast_and_chromeos_chromium_gtests',
+      'non_android_chromium_gtests',
+      'vr_platform_specific_chromium_gtests',
+      'win_specific_chromium_gtests',
+    ],
+
+    'chromium_win_rel_isolated_scripts': [
+      'chromedriver_py_tests_isolated_scripts',
+      'components_perftests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'mojo_python_unittests_isolated_scripts',
+      'telemetry_desktop_minidump_unittests_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts',
+      'win_specific_isolated_scripts',
+    ],
+
+    'chromium_win_rel_isolated_scripts_code_coverage': [
+      'gpu_dawn_webgpu_blink_web_tests',
+    ],
+
+    'chromium_win_rel_isolated_scripts_once': [
+      'chromedriver_py_tests_isolated_scripts',
+      'components_perftests_isolated_scripts',
+      'desktop_chromium_isolated_scripts',
+      'desktop_once_isolated_scripts',
+      'mojo_python_unittests_isolated_scripts',
+      'telemetry_desktop_minidump_unittests_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts',
+      'win_specific_isolated_scripts',
+      'wpt_web_tests_content_shell',
+    ],
+
+    'cronet_dbg_isolated_scripts': [
+      'cronet_sizes',
+    ],
+
+    'cronet_rel_isolated_scripts': [
+      'cronet_resource_sizes',
+      'cronet_sizes',
+    ],
+
+    'devtools_gtests': [
+      'devtools_browser_tests',
+      'blink_unittests',
+    ],
+
+    'fuchsia_accessibility_browsertests': [
+      'fuchsia_accessibility_content_browsertests',
+    ],
+
+    'fuchsia_arm64_isolated_scripts': [
+      'fuchsia_sizes_tests',
+      'gpu_angle_fuchsia_unittests_isolated_scripts',
+    ],
+
+    'fuchsia_gtests': [
+      'fuchsia_chrome_small_gtests',
+      'fuchsia_common_gtests',
+      'fuchsia_common_gtests_with_graphical_output',
+      'web_engine_gtests',
+    ],
+
+    'fuchsia_isolated_scripts': [
+      'chromium_webkit_isolated_scripts',
+      'gpu_angle_fuchsia_unittests_isolated_scripts',
+    ],
+
+    'fuchsia_web_engine_non_graphical_gtests': [
+      'fuchsia_common_gtests',
+      'web_engine_gtests',
+    ],
+
+    'gpu_angle_linux_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+    ],
+
+    'gpu_angle_mac_telemetry_tests': [
+      'gpu_info_collection_telemetry_tests',
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_metal_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_metal_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests',
+    ],
+
+    'gpu_angle_win_intel_nvidia_telemetry_tests': [
+      'gpu_info_collection_telemetry_tests',
+      'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests',
+    ],
+
+    'gpu_chromeos_telemetry_tests': [
+      'gpu_webgl_conformance_telemetry_tests',
+    ],
+
+    'gpu_common_android_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_validating_telemetry_tests',
+      'gpu_webgl_conformance_validating_telemetry_tests',
+    ],
+
+    'gpu_common_gl_passthrough_ganesh_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_gl_passthrough_ganesh_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+    ],
+
+    'gpu_common_linux_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_telemetry_tests',
+    ],
+
+    'gpu_common_metal_passthrough_ganesh_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_metal_passthrough_ganesh_telemetry_tests',
+      'gpu_webgl_conformance_metal_passthrough_telemetry_tests',
+    ],
+
+    'gpu_common_win_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests',
+    ],
+
+    'gpu_dawn_android_isolated_scripts': [
+      'gpu_dawn_perf_smoke_isolated_scripts',
+      'gpu_dawn_webgpu_blink_web_tests',
+    ],
+
+    'gpu_dawn_android_telemetry_tests': [
+      'gpu_dawn_webgpu_cts',
+    ],
+
+    'gpu_dawn_asan_isolated_scripts': [
+      'gpu_dawn_common_isolated_scripts',
+      'gpu_dawn_perf_smoke_isolated_scripts',
+      'gpu_dawn_webgpu_blink_web_tests',
+      'gpu_dawn_webgpu_blink_web_tests_force_swiftshader',
+    ],
+
+    'gpu_dawn_integration_asan_gtests_passthrough': [
+      'gpu_dawn_gtests',
+      'gpu_dawn_gtests_no_dxc',
+      'gpu_common_gtests_passthrough',
+    ],
+
+    'gpu_dawn_integration_gtests_passthrough': [
+      'gpu_dawn_gtests',
+      'gpu_dawn_gtests_with_validation',
+      'gpu_common_gtests_passthrough',
+    ],
+
+    'gpu_dawn_integration_gtests_passthrough_win_x64': [
+      'gpu_dawn_gtests',
+      'gpu_dawn_gtests_with_validation',
+      'gpu_dawn_gtests_no_dxc',
+      'gpu_dawn_gtests_no_dxc_with_validation',
+      'gpu_common_gtests_passthrough',
+    ],
+
+    'gpu_dawn_isolated_scripts': [
+      'gpu_dawn_common_isolated_scripts',
+      'gpu_dawn_perf_smoke_isolated_scripts',
+      'gpu_dawn_webgpu_blink_web_tests',
+      'gpu_dawn_webgpu_blink_web_tests_force_swiftshader',
+    ],
+
+    'gpu_dawn_telemetry_tests': [
+      'gpu_dawn_webgpu_cts',
+      'gpu_dawn_web_platform_webgpu_cts_force_swiftshader',
+    ],
+
+    'gpu_dawn_telemetry_win_x64_tests': [
+      'gpu_dawn_webgpu_cts',
+      'gpu_dawn_webgpu_cts_dxc',
+      'gpu_dawn_web_platform_webgpu_cts_force_swiftshader',
+    ],
+
+    'gpu_dawn_tsan_gtests': [
+      'gpu_dawn_gtests',
+    ],
+
+    'gpu_desktop_mac_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_desktop_specific_gtests',
+    ],
+
+    'gpu_desktop_passthrough_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_desktop_specific_gtests',
+    ],
+
+    'gpu_fuchsia_telemetry_tests': [
+      'gpu_validating_telemetry_tests',
+    ],
+
+    'gpu_fyi_android_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_common_gtests_validating',
+      'gpu_fyi_and_optional_non_linux_gtests',
+    ],
+
+    'gpu_fyi_android_shieldtv_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_common_gtests_validating',
+      'gpu_fyi_and_optional_non_linux_gtests',
+    ],
+
+    'gpu_fyi_android_webgl2_and_gold_telemetry_tests': [
+      'gpu_validating_telemetry_tests',
+      'gpu_webgl2_conformance_gles_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_validating_telemetry_tests',
+    ],
+
+    'gpu_fyi_chromeos_release_gtests': [
+      'gpu_common_gtests_validating',
+    ],
+
+    'gpu_fyi_chromeos_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_mediapipe_validating_telemetry_tests',
+      'gpu_validating_telemetry_tests',
+      'gpu_webcodecs_validating_telemetry_test',
+      'gpu_webgl_conformance_validating_telemetry_tests',
+      'gpu_webgl2_conformance_gles_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_validating_telemetry_tests',
+    ],
+
+    'gpu_fyi_lacros_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webcodecs_telemetry_test',
+      'gpu_webgl2_conformance_gles_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gles_passthrough_telemetry_tests',
+    ],
+
+    'gpu_fyi_linux_debug_gtests': [
+      'gpu_common_gtests_passthrough',
+      'gpu_gles2_conform_gtests',
+    ],
+
+    'gpu_fyi_linux_debug_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+    ],
+
+    'gpu_fyi_linux_release_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_desktop_specific_gtests',
+      'gpu_gles2_conform_gtests',
+      'gpu_vulkan_gtests',
+    ],
+
+    'gpu_fyi_linux_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+    ],
+
+    'gpu_fyi_linux_release_vulkan_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+      'gpu_skia_renderer_vulkan_passthrough_telemetry_tests',
+    ],
+
+    'gpu_fyi_mac_debug_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_fyi_and_optional_non_linux_gtests',
+      'gpu_fyi_mac_specific_gtests',
+      'gpu_gles2_conform_gtests',
+    ],
+
+    'gpu_fyi_mac_nvidia_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_gl_passthrough_ganesh_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_webcodecs_telemetry_test',
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests',
+    ],
+
+    'gpu_fyi_mac_pro_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_metal_passthrough_graphite_telemetry_tests',
+      'gpu_webgl2_conformance_metal_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_metal_passthrough_telemetry_tests',
+    ],
+
+    'gpu_fyi_mac_release_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_desktop_specific_gtests',
+      'gpu_fyi_and_optional_non_linux_gtests',
+      'gpu_fyi_mac_specific_gtests',
+      'gpu_gles2_conform_gtests',
+    ],
+
+    'gpu_fyi_mac_release_telemetry_tests': [
+      'gpu_gl_passthrough_ganesh_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_metal_passthrough_graphite_telemetry_tests',
+      'gpu_webcodecs_telemetry_test',
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_metal_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests',
+    ],
+
+    'gpu_fyi_only_mac_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_gl_passthrough_ganesh_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_metal_passthrough_ganesh_telemetry_tests',
+      'gpu_metal_passthrough_graphite_telemetry_tests',
+      'gpu_webcodecs_telemetry_test',
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_metal_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_metal_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests',
+    ],
+
+    'gpu_fyi_win_amd_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webcodecs_telemetry_test',
+      'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
+    ],
+
+    'gpu_fyi_win_debug_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests',
+    ],
+
+    'gpu_fyi_win_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_default_and_optional_win_media_foundation_specific_gtests',
+      'gpu_default_and_optional_win_specific_gtests',
+      'gpu_desktop_specific_gtests',
+      'gpu_fyi_and_optional_non_linux_gtests',
+      'gpu_fyi_and_optional_win_specific_gtests',
+      'gpu_gles2_conform_gtests',
+    ],
+
+    'gpu_fyi_win_intel_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webcodecs_telemetry_test',
+      'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests',
+    ],
+
+    'gpu_fyi_win_optional_isolated_scripts': [
+      'gpu_command_buffer_perf_passthrough_isolated_scripts',
+    ],
+
+    'gpu_fyi_win_release_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webcodecs_telemetry_test',
+      'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests',
+    ],
+
+    'gpu_nexus5x_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_mediapipe_validating_telemetry_tests',
+      'gpu_validating_telemetry_tests',
+      'gpu_webcodecs_validating_telemetry_test',
+      'gpu_webgl_conformance_gles_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_validating_telemetry_tests',
+    ],
+
+    'gpu_nexus5x_telemetry_tests_v8': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_validating_telemetry_tests',
+      'gpu_webgl_conformance_gles_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_validating_telemetry_tests',
+    ],
+
+    'gpu_pixel_4_and_6_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_mediapipe_passthrough_telemetry_tests',
+      'gpu_mediapipe_validating_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_validating_telemetry_tests',
+      'gpu_webcodecs_validating_telemetry_test',
+      'gpu_webgl_conformance_gles_passthrough_telemetry_tests',
+      'gpu_webgl_conformance_validating_telemetry_tests',
+      'gpu_webgl2_conformance_gles_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_validating_telemetry_tests',
+    ],
+
+    'gpu_swangle_telemetry_tests': [
+      'gpu_webgl_conformance_swangle_passthrough_telemetry_tests',
+    ],
+
+    'gpu_win_gtests': [
+      'gpu_angle_unit_gtests',
+      'gpu_common_gtests_passthrough',
+      'gpu_default_and_optional_win_specific_gtests',
+      'gpu_desktop_specific_gtests',
+    ],
+
+    'linux_chromeos_gtests': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_chromeos_only',
+      'chromium_gtests_for_win_and_linux_only',
+      'linux_chromeos_lacros_gtests',
+      'linux_chromeos_specific_gtests',
+      'linux_flavor_specific_chromium_gtests',
+      'non_android_chromium_gtests',
+    ],
+
+    'linux_chromeos_gtests_oobe': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_chromeos_only',
+      'chromium_gtests_for_win_and_linux_only',
+      'linux_chromeos_lacros_gtests',
+      'linux_chromeos_oobe_specific_tests',
+      'linux_chromeos_specific_gtests',
+      'linux_flavor_specific_chromium_gtests',
+      'non_android_chromium_gtests',
+    ],
+
+    'linux_chromeos_specific_and_lacros_dependent_gtests': [
+      'aura_gtests',
+      'chromium_gtests',
+      'chromium_gtests_for_devices_with_graphical_output',
+      'chromium_gtests_for_linux_and_chromeos_only',
+      'chromium_gtests_for_win_and_linux_only',
+      'linux_chromeos_lacros_gtests',
+      'linux_chromeos_specific_gtests',
+      'linux_chromeos_browser_tests_require_lacros',
+      'linux_flavor_specific_chromium_gtests',
+      'non_android_chromium_gtests',
+      'pixel_experimental_browser_tests_gtests',
+      'ash_pixel_gtests',
+    ],
+
+    'linux_viz_gtests': [
+      'gpu_fyi_vulkan_swiftshader_gtests',
+    ],
+
+    'network_service_extra_gtests': [
+      'network_service_fyi_gtests',
+    ],
+
+    'nougat_isolated_scripts': [
+      'android_isolated_scripts',
+      'chromium_junit_tests_scripts',
+      'components_perftests_isolated_scripts',
+      'monochrome_public_apk_checker_isolated_script',
+      'telemetry_android_minidump_unittests_isolated_scripts',
+      'telemetry_perf_unittests_isolated_scripts_android',
+    ],
+
+    'rust_host_gtests': [
+      'rust_common_gtests',
+    ],
+
+    'webrtc_chromium_tests_with_baremetal_tests': [
+      'webrtc_chromium_baremetal_gtests',
+      'webrtc_chromium_gtests',
+    ],
+
+    'webview_bot_all_gtests': [
+      'system_webview_shell_instrumentation_tests',
+      'webview_bot_instrumentation_test_apk_gtest',
+      'webview_bot_instrumentation_test_apk_no_field_trial_gtest',
+      'webview_bot_unittests_gtest',
+      'webview_cts_tests_gtest',
+      'webview_cts_tests_gtest_no_field_trial',
+      'webview_ui_instrumentation_tests',
+      'webview_ui_instrumentation_tests_no_field_trial',
+    ],
+
+    'webview_trichrome_64_cts_gtests': [
+      'webview_trichrome_64_cts_tests',
+      'webview_trichrome_64_cts_tests_no_field_trial',
+    ],
+
+    'win_specific_isolated_scripts_and_sizes': [
+      'chrome_sizes',
+      'win_specific_isolated_scripts',
+    ],
+
+    'wpt_web_tests_content_shell_multiple_flags': [
+      'wpt_web_tests_content_shell',
+      'wpt_web_tests_not_site_per_process',
+      'wpt_web_tests_highdpi',
+    ],
+  },
+
+  'matrix_compound_suites': {
+
+    'android_11_emulator_gtests': {
+      'android_emulator_specific_chrome_public_tests': {},
+      'android_trichrome_smoke_tests': {},
+      'android_smoke_tests': {},
+      'android_specific_chromium_gtests': {},
+      'chromium_gtests': {},
+      'chromium_gtests_for_devices_with_graphical_output': {},
+      'linux_flavor_specific_chromium_gtests': {},
+      'system_webview_shell_instrumentation_tests': {},
+      'webview_trichrome_cts_tests': {
+        'variants': [
+          'WEBVIEW_TRICHROME_FULL_CTS_TESTS',
+          'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS',
+        ],
+      },
+      'webview_ui_instrumentation_tests': {},
+    },
+
+    'android_12_emulator_fyi_gtests': {
+      'oop_network_service_tests': {},
+    },
+
+    'android_12_emulator_gtests': {
+      'android_12_fieldtrial_webview_tests': {},
+      'android_emulator_specific_chrome_public_tests': {},
+      'android_trichrome_smoke_tests': {},
+      'android_smoke_tests': {},
+      'android_specific_chromium_gtests': {},
+      'chrome_profile_generator_tests': {},
+      'chromium_gtests': {},
+      'chromium_gtests_for_devices_with_graphical_output': {},
+      'fieldtrial_android_tests': {},
+      'linux_flavor_specific_chromium_gtests': {},
+      'minidump_uploader_tests': {},
+      'system_webview_shell_instrumentation_tests': {},
+      'webview_trichrome_64_cts_tests': {
+        'variants': [
+          'WEBVIEW_TRICHROME_FULL_CTS_TESTS',
+          'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS',
+        ],
+      },
+      'webview_ui_instrumentation_tests': {},
+    },
+
+    'android_12l_emulator_gtests': {
+      'android_emulator_specific_chrome_public_tests': {},
+      'android_trichrome_smoke_tests': {},
+      'android_smoke_tests': {},
+      'android_specific_chromium_gtests': {},
+      'chromium_gtests': {},
+      'chromium_gtests_for_devices_with_graphical_output': {},
+      'linux_flavor_specific_chromium_gtests': {},
+      'system_webview_shell_instrumentation_tests': {},
+      'webview_ui_instrumentation_tests': {},
+    },
+
+    'android_13_emulator_gtests': {
+      'android_emulator_specific_chrome_public_tests': {},
+      'android_trichrome_smoke_tests': {},
+      'android_smoke_tests': {},
+      'android_specific_chromium_gtests': {},
+      'chromium_gtests': {},
+      'chromium_gtests_for_devices_with_graphical_output': {},
+      'linux_flavor_specific_chromium_gtests': {},
+      'system_webview_shell_instrumentation_tests': {},
+      'webview_trichrome_64_cts_tests': {
+        'variants': [
+          'WEBVIEW_TRICHROME_FULL_CTS_TESTS',
+          'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS',
+        ],
+      },
+      'webview_trichrome_64_cts_tests_no_field_trial': {},
+      'webview_ui_instrumentation_tests': {},
+    },
+
+    'android_fieldtrial_rel_webview_tests': {
+      'fieldtrial_android_tests': {},
+      'webview_bot_instrumentation_test_apk_gtest': {
+        'variants': [
+          'DISABLE_FIELD_TRIAL_CONFIG',
+          'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR',
+          'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR',
+        ],
+      },
+      'webview_trichrome_64_cts_field_trial_tests': {
+        'variants': [
+          'DISABLE_FIELD_TRIAL_CONFIG',
+          'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR',
+          'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR',
+        ],
+      },
+      'webview_ui_instrumentation_tests': {
+        'variants': [
+          'DISABLE_FIELD_TRIAL_CONFIG',
+          'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR',
+          'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR',
+        ],
+      },
+      'system_webview_shell_instrumentation_tests': {
+        'variants': [
+          'DISABLE_FIELD_TRIAL_CONFIG_WEBVIEW_COMMANDLINE',
+          'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR_WEBVIEW_COMMANDLINE',
+          'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR_WEBVIEW_COMMANDLINE',
+        ],
+      },
+    },
+
+    'chromeos_brya_skylab_tests': {
+      'chromeos_chrome_all_tast_tests': {
+        'variants': [
+          'CROS_BRYA_RELEASE_ASH_LKGM',
+        ],
+      },
+      'chromeos_chrome_criticalstaging_tast_tests': {
+        'variants': [
+          'CROS_BRYA_RELEASE_ASH_LKGM',
+        ],
+      },
+      'chromeos_chrome_disabled_tast_tests': {
+        'variants': [
+          'CROS_BRYA_RELEASE_ASH_LKGM',
+        ],
+      },
+    },
+
+    'chromeos_jacuzzi_skylab_tests': {
+      'chromeos_chrome_all_tast_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM',
+        ],
+      },
+      'chromeos_chrome_criticalstaging_tast_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM',
+        ],
+      },
+      'chromeos_chrome_disabled_tast_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM',
+        ],
+      },
+    },
+
+    'chromeos_octopus_skylab_tests': {
+      'chromeos_chrome_all_tast_tests': {
+        'variants': [
+          'CROS_OCTOPUS_RELEASE_CHROME_FROM_TLS_ASH_LKGM',
+        ],
+      },
+    },
+
+    'chromeos_trogdor_skylab_tests': {
+      'chromeos_chrome_all_tast_tests': {
+        'variants': [
+          'CROS_TROGDOR_RELEASE_ASH_LKGM',
+        ],
+      },
+    },
+
+    'chromeos_volteer_skylab_tests': {
+      'chromeos_chrome_all_tast_tests': {
+        'variants': [
+          'CROS_VOLTEER_RELEASE_ASH_LKGM',
+        ],
+      },
+      'chromeos_chrome_criticalstaging_tast_tests': {
+        'variants': [
+          'CROS_VOLTEER_RELEASE_ASH_LKGM',
+        ],
+      },
+      'chromeos_chrome_disabled_tast_tests': {
+        'variants': [
+          'CROS_VOLTEER_RELEASE_ASH_LKGM',
+        ],
+      },
+    },
+
+    'fieldtrial_ios_simulator_tests': {
+      'ios_eg2_cq_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'disable_field_trial_config_for_earl_grey',
+        ],
+        'variants': [
+          'SIM_IPAD_AIR_2_15_5',
+          'SIM_IPHONE_13_15_5',
+        ],
+      },
+      'ios_eg2_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'disable_field_trial_config_for_earl_grey',
+        ],
+        'variants': [
+          'SIM_IPAD_AIR_2_15_5',
+          'SIM_IPHONE_13_15_5',
+        ],
+      },
+    },
+
+    'gpu_angle_ios_gtests': {
+      'gpu_angle_ios_end2end_gtests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+      'gpu_angle_ios_white_box_gtests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+    },
+
+    'gpu_fyi_chromeos_release_telemetry_tests_skylab': {
+      'gpu_common_and_optional_telemetry_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+      'gpu_mediapipe_validating_telemetry_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+      'gpu_validating_telemetry_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+      'gpu_webcodecs_validating_telemetry_test': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+      'gpu_webgl_conformance_validating_telemetry_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+      'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+      'gpu_webgl2_conformance_validating_telemetry_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_LKGM',
+        ],
+      },
+    },
+
+    'gpu_fyi_lacros_device_release_telemetry_tests': {
+      'gpu_pixel_passthrough_telemetry_tests': {
+        'variants': [
+          'LACROS_ASH_TOT',
+        ],
+      },
+      'gpu_webgl_conformance_gles_passthrough_telemetry_tests': {
+        'variants': [
+          'LACROS_ASH_TOT',
+        ],
+      },
+      'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': {
+        'variants': [
+          'LACROS_ASH_TOT',
+        ],
+      },
+    },
+
+    'ios16_beta_simulator_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+        ],
+      },
+      'ios_eg2_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_10TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+        ],
+      },
+      'ios_eg2_cq_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_10TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_PRO_MAX_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+        ],
+      },
+      'ios_crash_xcuitests': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+        ],
+      },
+    },
+
+    'ios16_sdk_simulator_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+        ],
+      },
+      'ios_crash_xcuitests': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+        ],
+      },
+      'ios_eg2_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+        ],
+      },
+      'ios_eg2_cq_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_SE_3RD_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+        ],
+      },
+    },
+
+    'ios17_beta_simulator_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPHONE_SE_3RD_GEN_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_crash_xcuitests': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+    },
+
+    'ios17_sdk_simulator_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_tests_parallel': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests_parallel': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPHONE_SE_3RD_GEN_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+    },
+
+    'ios_asan_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_X_15_5',
+          'SIM_IPAD_AIR_2_15_5',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_X_15_5',
+          'SIM_IPAD_AIR_2_15_5',
+        ],
+      },
+    },
+
+    'ios_blink_dbg_tests': {
+      'ios_blink_tests': {
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+    },
+
+    'ios_clang_tot_device_tests': {
+      'clang_tot_gtests': {
+        'variants': [
+          'IPHONE_7_15_4_1',
+        ],
+      },
+    },
+
+    'ios_clang_tot_sim_tests': {
+      'clang_tot_gtests': {
+        'variants': [
+          'SIM_IPHONE_6S_15_5',
+        ],
+      },
+    },
+
+    'ios_code_coverage_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_PLUS_16_4',
+          'SIM_IPHONE_14_PLUS_17_0',
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests_parallel': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_13_15_5',
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+          'SIM_IPAD_PRO_5TH_GEN_15_5',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_tests_parallel': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_13_15_5',
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+          'SIM_IPAD_PRO_5TH_GEN_15_5',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_13_15_5',
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPHONE_SE_3RD_GEN_15_5',
+          'SIM_IPHONE_SE_3RD_GEN_16_4',
+          'SIM_IPHONE_SE_3RD_GEN_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+          'SIM_IPAD_PRO_5TH_GEN_15_5',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+        ],
+      },
+    },
+
+    'ios_m1_simulator_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+      'ios_eg2_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_10TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_10TH_GEN_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_14_PRO_MAX_16_4',
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_SE_3RD_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPHONE_14_PRO_MAX_17_0',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPHONE_SE_3RD_GEN_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+    },
+
+    'ios_simulator_cronet_tests': {
+      'ios_cronet_tests': {
+        'variants': [
+          'SIM_IPHONE_13_15_5',
+        ],
+      },
+    },
+
+    'ios_simulator_full_configs_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_PLUS_16_4',
+          'SIM_IPHONE_14_PLUS_17_0',
+        ],
+      },
+      'ios_eg2_tests_parallel': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests_parallel': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+    },
+
+    'ios_simulator_multi_window_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_tests': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+    },
+
+    'ios_simulator_noncq_tests': {
+      'ios_eg2_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_13_15_5',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests': {
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
+        'variants': [
+          'SIM_IPHONE_13_15_5',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_SE_3RD_GEN_15_5',
+          'SIM_IPAD_AIR_5TH_GEN_15_5',
+          'SIM_IPHONE_14_PLUS_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPHONE_SE_3RD_GEN_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPHONE_14_PLUS_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+          'SIM_IPHONE_SE_3RD_GEN_17_0',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+        ],
+      },
+      'ios_crash_xcuitests': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_13_15_5',
+          'SIM_IPHONE_SE_3RD_GEN_16_4',
+          'SIM_IPHONE_SE_3RD_GEN_17_0',
+        ],
+      },
+    },
+
+    'ios_simulator_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests_parallel': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPHONE_14_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_PRO_6TH_GEN_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_PRO_6TH_GEN_17_0',
+        ],
+      },
+    },
+
+    'ios_webkit_tot_tests': {
+      'ios_common_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_cq_tests_parallel': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_eg2_tests': {
+        'mixins': [
+          'xcode_parallelization',
+        ],
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+      'ios_screen_size_dependent_tests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+    },
+
+    'ios_webrtc_fyi_tests': {
+      'ios_remoting_fyi_unittests': {
+        'variants': [
+          'SIM_IPHONE_14_16_4',
+          'SIM_IPAD_AIR_5TH_GEN_16_4',
+          'SIM_IPHONE_14_17_0',
+          'SIM_IPAD_AIR_5TH_GEN_17_0',
+        ],
+      },
+    },
+
+    'lacros_amd64_generic_rel_skylab_fyi': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_OCTOPUS_PUBLIC_LKGM',
+          'CROS_EVE_PUBLIC_LKGM',
+        ],
+      },
+    },
+
+    'lacros_arm64_generic_rel_skylab': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_TROGDOR_PUBLIC_LKGM',
+        ],
+      },
+    },
+
+    'lacros_arm64_generic_rel_skylab_fyi': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_JACUZZI_PUBLIC_LKGM',
+          'CROS_JACUZZI_CQ_PUBLIC_LKGM',
+          'CROS_TROGDOR_PUBLIC_LKGM',
+        ],
+      },
+    },
+
+    'lacros_arm_generic_rel_skylab': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_JACUZZI_PUBLIC_LKGM',
+        ],
+      },
+      'lacros_skylab_tests_with_gtests': {
+        'variants': [
+          'CROS_JACUZZI_PUBLIC_LKGM',
+        ],
+      },
+    },
+
+    'lacros_arm_generic_rel_skylab_fyi': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_JACUZZI_PUBLIC_LKGM',
+          'CROS_TROGDOR_PUBLIC_LKGM',
+        ],
+      },
+    },
+
+    'lacros_device_or_vm_tests': {
+      'chromeos_integration_tests': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+          'LACROS_EVE',
+        ],
+      },
+      'lacros_all_tast_tests': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+          'LACROS_EVE',
+        ],
+      },
+      'lacros_cq_tast_tests_eve': {
+        'variants': [
+          'LACROS_EVE',
+        ],
+      },
+      'lacros_device_or_vm_gtests': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+          'LACROS_EVE',
+        ],
+      },
+      'lacros_vm_gtests': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+        ],
+      },
+    },
+
+    'lacros_device_or_vm_tests_fyi': {
+      'lacros_all_tast_tests_informational': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+          'LACROS_EVE',
+        ],
+      },
+      'lacros_device_or_vm_gtests': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+          'LACROS_EVE',
+        ],
+      },
+      'lacros_fyi_tast_tests': {
+        'variants': [
+          'LACROS_AMD64_GENERIC',
+          'LACROS_EVE',
+        ],
+      },
+    },
+
+    'lacros_skylab_arm': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_JACUZZI_RELEASE_LKGM',
+          'CROS_JACUZZI_RELEASE_DEV',
+          'CROS_JACUZZI_RELEASE_BETA',
+          'CROS_JACUZZI_RELEASE_STABLE',
+        ],
+      },
+    },
+
+    'lacros_skylab_arm64': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_STRONGBAD_RELEASE_LKGM',
+        ],
+      },
+    },
+
+    'lacros_skylab_arm_fyi': {
+      'lacros_skylab_arm_tests_fyi': {
+        'variants': [
+          'CROS_HANA_RELEASE_LKGM',
+          'CROS_HANA_RELEASE_DEV',
+          'CROS_HANA_RELEASE_BETA',
+          'CROS_HANA_RELEASE_STABLE',
+          'CROS_STRONGBAD_RELEASE_LKGM',
+          'CROS_STRONGBAD_RELEASE_DEV',
+          'CROS_STRONGBAD_RELEASE_BETA',
+          'CROS_STRONGBAD_RELEASE_STABLE',
+        ],
+      },
+    },
+
+    'lacros_skylab_tests_amd64_generic': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_BRYA_RELEASE_LKGM',
+          'CROS_BRYA_RELEASE_DEV',
+          'CROS_BRYA_RELEASE_BETA',
+          'CROS_BRYA_RELEASE_STABLE',
+          'CROS_DEDEDE_RELEASE_LKGM',
+          'CROS_DEDEDE_RELEASE_DEV',
+          'CROS_DEDEDE_RELEASE_BETA',
+          'CROS_DEDEDE_RELEASE_STABLE',
+          'CROS_FIZZ_RELEASE_LKGM',
+          'CROS_FIZZ_RELEASE_DEV',
+          'CROS_FIZZ_RELEASE_BETA',
+          'CROS_FIZZ_RELEASE_STABLE',
+          'CROS_GUYBRUSH_RELEASE_LKGM',
+          'CROS_GUYBRUSH_RELEASE_DEV',
+          'CROS_GUYBRUSH_RELEASE_BETA',
+          'CROS_GUYBRUSH_RELEASE_STABLE',
+          'CROS_PUFF_RELEASE_LKGM',
+          'CROS_PUFF_RELEASE_DEV',
+          'CROS_PUFF_RELEASE_BETA',
+          'CROS_PUFF_RELEASE_STABLE',
+        ],
+      },
+    },
+
+    'lacros_skylab_tests_amd64_generic_fyi': {
+      'lacros_skylab_amd64_fyi': {
+        'variants': [
+          'CROS_OCTOPUS_RELEASE_LKGM',
+          'CROS_OCTOPUS_RELEASE_DEV',
+          'CROS_OCTOPUS_RELEASE_BETA',
+          'CROS_OCTOPUS_RELEASE_STABLE',
+        ],
+      },
+    },
+
+    'lacros_skylab_tests_amd64_generic_rel': {
+      'lacros_skylab_tests': {
+        'variants': [
+          'CROS_VOLTEER_PUBLIC_LKGM',
+        ],
+      },
+    },
+
+    'linux_lacros_gtests': {
+      'aura_gtests': {},
+      'chromium_gtests': {},
+      'chromium_gtests_for_devices_with_graphical_output': {},
+      'chromium_gtests_for_linux_and_chromeos_only': {},
+      'chromium_gtests_for_win_and_linux_only': {},
+      'linux_chromeos_lacros_gtests': {},
+      'linux_flavor_specific_chromium_gtests': {},
+      'linux_lacros_specific_gtests': {},
+      'non_android_chromium_gtests': {},
+      'linux_lacros_chrome_browsertests_non_version_skew': {},
+      'linux_lacros_chrome_browsertests_version_skew': {
+        'variants': [
+          'LACROS_VERSION_SKEW_CANARY',
+          'LACROS_VERSION_SKEW_DEV',
+          'LACROS_VERSION_SKEW_BETA',
+          'LACROS_VERSION_SKEW_STABLE',
+        ],
+      },
+      'linux_lacros_chrome_interactive_ui_tests_version_skew': {
+        'variants': [
+          'LACROS_VERSION_SKEW_CANARY',
+        ],
+      },
+      'linux_lacros_chrome_interactive_ui_tests_version_skew_beta': {
+        'variants': [
+          'LACROS_VERSION_SKEW_BETA',
+        ],
+      },
+      'linux_lacros_chrome_interactive_ui_tests_version_skew_dev': {
+        'variants': [
+          'LACROS_VERSION_SKEW_DEV',
+        ],
+      },
+      'linux_lacros_chrome_interactive_ui_tests_version_skew_stable': {
+        'variants': [
+          'LACROS_VERSION_SKEW_STABLE',
+        ],
+      },
+    },
+
+    'linux_lacros_version_skew_tests': {
+      'linux_lacros_chrome_interactive_ui_tests_version_skew': {
+        'variants': [
+          'LACROS_VERSION_SKEW_CANARY',
+          'LACROS_VERSION_SKEW_DEV',
+          'LACROS_VERSION_SKEW_BETA',
+          'LACROS_VERSION_SKEW_STABLE',
+        ],
+      },
+    },
+
+    'linux_optional_gpu_tests_rel_gpu_telemetry_tests': {
+      'gpu_common_and_optional_telemetry_tests': {
+        'variants': [
+          'LINUX_INTEL_UHD_630_STABLE',
+          'LINUX_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_mediapipe_passthrough_telemetry_tests': {
+        'variants': [
+          'LINUX_INTEL_UHD_630_STABLE',
+          'LINUX_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_webcodecs_telemetry_test': {
+        'variants': [
+          'LINUX_INTEL_UHD_630_STABLE',
+          'LINUX_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests': {
+        'variants': [
+          'LINUX_INTEL_UHD_630_STABLE',
+          'LINUX_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests': {
+        'variants': [
+          'LINUX_INTEL_UHD_630_STABLE',
+          'LINUX_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+    },
+
+    'linux_optional_gpu_tests_rel_gtests': {
+      'gpu_gles2_conform_gtests': {
+        'variants': [
+          'LINUX_INTEL_UHD_630_STABLE',
+          'LINUX_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+    },
+
+    'mac_optional_gpu_tests_rel_gpu_telemetry_tests': {
+      'gpu_common_and_optional_telemetry_tests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+          'MAC_RETINA_NVIDIA_GPU_STABLE',
+        ],
+      },
+      'gpu_mediapipe_passthrough_telemetry_tests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+          'MAC_RETINA_NVIDIA_GPU_STABLE',
+        ],
+      },
+      'gpu_gl_passthrough_ganesh_telemetry_tests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+        ],
+      },
+      'gpu_metal_passthrough_graphite_telemetry_tests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+        ],
+      },
+      'gpu_webcodecs_telemetry_test': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+          'MAC_RETINA_NVIDIA_GPU_STABLE',
+        ],
+      },
+      'gpu_webgl2_conformance_metal_passthrough_telemetry_tests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+        ],
+      },
+      'gpu_webgl_conformance_gl_passthrough_telemetry_tests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+        ],
+      },
+      'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+        ],
+      },
+    },
+
+    'mac_optional_gpu_tests_rel_gtests': {
+      'gpu_fyi_and_optional_non_linux_gtests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+          'MAC_RETINA_NVIDIA_GPU_STABLE',
+        ],
+      },
+      'gpu_fyi_mac_specific_gtests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+          'MAC_RETINA_NVIDIA_GPU_STABLE',
+        ],
+      },
+      'gpu_gles2_conform_gtests': {
+        'variants': [
+          'MAC_MINI_INTEL_GPU_STABLE',
+          'MAC_RETINA_AMD_GPU_STABLE',
+          'MAC_RETINA_NVIDIA_GPU_STABLE',
+        ],
+      },
+    },
+
+    'model_validation_tests_full': {
+      'model_validation_tests': {
+        'variants': [
+          'MODEL_VALIDATION_BASE',
+          'MODEL_VALIDATION_TRUNK',
+        ],
+      },
+    },
+
+    'model_validation_tests_trunk': {
+      'model_validation_tests': {
+        'variants': [
+          'MODEL_VALIDATION_TRUNK',
+        ],
+      },
+    },
+
+    'webview_trichrome_10_cts_tests_gtest': {
+      'webview_trichrome_cts_tests': {
+        'variants': [
+          'WEBVIEW_TRICHROME_FULL_CTS_TESTS',
+          'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS',
+        ],
+      },
+    },
+
+    'win_optional_gpu_tests_rel_gpu_telemetry_tests': {
+      'gpu_common_and_optional_telemetry_tests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_mediapipe_passthrough_telemetry_tests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_webcodecs_telemetry_test': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+    },
+
+    'win_optional_gpu_tests_rel_gtests': {
+      'gpu_default_and_optional_win_media_foundation_specific_gtests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+        ],
+      },
+      'gpu_default_and_optional_win_specific_gtests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_fyi_and_optional_non_linux_gtests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_fyi_and_optional_win_specific_gtests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+      'gpu_gles2_conform_gtests': {
+        'variants': [
+          'WIN10_INTEL_UHD_630_STABLE',
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+    },
+
+    'win_optional_gpu_tests_rel_isolated_scripts': {
+      'gpu_command_buffer_perf_passthrough_isolated_scripts': {
+        'variants': [
+          'WIN10_NVIDIA_GTX_1660_STABLE',
+        ],
+      },
+    },
+  },
+}
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl
index c0117ce2..cc87d404 100644
--- a/infra/config/generated/testing/variants.pyl
+++ b/infra/config/generated/testing/variants.pyl
@@ -70,16 +70,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 119.0.6029.0',
+    'description': 'Run with ash-chrome version 119.0.6030.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v119.0.6029.0',
-          'revision': 'version:119.0.6029.0',
+          'location': 'lacros_version_skew_tests_v119.0.6030.0',
+          'revision': 'version:119.0.6030.0',
         },
       ],
     },
@@ -787,7 +787,6 @@
       'cros_board': 'volteer',
       'cros_model': 'voxel',
       'cros_img': 'volteer-public/R119-15623.0.0',
-      'autotest_name': 'tast.lacros-from-gcs',
       'bucket': 'chromiumos-image-archive',
       'dut_pool': 'chromium',
       'public_builder': 'cros_test_platform_public',
diff --git a/infra/config/lib/nodes.star b/infra/config/lib/nodes.star
index d873bcd..bccec7ad 100644
--- a/infra/config/lib/nodes.star
+++ b/infra/config/lib/nodes.star
@@ -118,16 +118,17 @@
         get = get,
     )
 
-def _create_bucket_scoped_node_type(kind):
-    """Create a node type scoped to a bucket.
+def _create_scoped_node_type(kind, scope_kind):
+    """Create a node type scoped to another kind.
 
-    Bucket-scoped node types allow for one node to exist with a given key_value
-    per bucket. Key values are arbitrary, it is up to the calling code to assign
-    meaning to the key values and enforce validity.
+    Scoped node types allow for a node to exist with a given key value per key
+    value of the scope kind. Key values are arbitrary, it is up to the calling
+    code to assign meaning to the key values and enforce validity.
 
     Args:
-        kind: (str) An identifier for the kind of the node. Must be unique
-            within the chromium namespace.
+        kind: (str) An identifier for the kind of the node. Must be unique within
+            the chromium namespace.
+        scope_kind: (str) An identifier for the scope kind.
 
     Returns:
         A node type that can be used for creating and getting nodes of
@@ -137,25 +138,25 @@
         * kind: The kind of nodes of the type.
 
         The node types has the following methods:
-        * key(bucket_name, key_value): Creates a key with the given bucket and
-            value.
-        * add(bucket_name, key_value, **kwargs): Adds a node with a key created
-            via `key(bucket_name, key_value)`. `graph.add_node` will be called
-            with the key and `**kwargs`. Returns the key.
-        * get(key_value): Gets the node with the key given by
-            `key(bucket_name, key_value)`.
+        * key(scope_key_value, key_value): Creates a key with the given scope
+            value as the container and key_value as the ID.
+        * add(scope_key_value, key_value, **kwargs): Adds a node with a key
+            created via `key(scope_key_value, key_value)`. `graph.add_node` will
+            be called with the key and `**kwargs`. Returns the key.
+        * get(scope_key_value, key_value): Gets the node with the key given by
+            `key(scope_key_value, key_value)`.
     """
 
-    def key(bucket_name, key_value):
-        return graph.key(_CHROMIUM_NS_KIND, "", kinds.BUCKET, bucket_name, kind, key_value)
+    def key(scope_key_value, key_value):
+        return graph.key(_CHROMIUM_NS_KIND, "", scope_kind, scope_key_value, kind, key_value)
 
-    def add(bucket_name, key_value, **kwargs):
-        k = key(bucket_name, key_value)
+    def add(scope_key_value, key_value, **kwargs):
+        k = key(scope_key_value, key_value)
         graph.add_node(k, **kwargs)
         return k
 
-    def get(bucket_name, key_value):
-        return graph.node(key(bucket_name, key_value))
+    def get(scope_key_value, key_value):
+        return graph.node(key(scope_key_value, key_value))
 
     return struct(
         kind = kind,
@@ -387,7 +388,8 @@
     BUILDER = _BUILDER,
     create_singleton_node_type = _create_singleton_node_type,
     create_unscoped_node_type = _create_unscoped_node_type,
-    create_bucket_scoped_node_type = _create_bucket_scoped_node_type,
+    create_scoped_node_type = _create_scoped_node_type,
+    create_bucket_scoped_node_type = lambda kind: _create_scoped_node_type(kind, kinds.BUCKET),
     create_node_type_with_builder_ref = _create_node_type_with_builder_ref,
     create_link_node_type = _create_link_node_type,
 )
diff --git a/infra/config/lib/targets.star b/infra/config/lib/targets.star
index 7c7af0e..f7f52f9 100644
--- a/infra/config/lib/targets.star
+++ b/infra/config/lib/targets.star
@@ -12,6 +12,11 @@
 _TARGET_MIXIN = nodes.create_unscoped_node_type("target-mixin")
 _TARGET_VARIANT = nodes.create_unscoped_node_type("target-variant")
 
+_LEGACY_BASIC_SUITE = nodes.create_unscoped_node_type("legacy-basic-suite")
+_LEGACY_COMPOUND_SUITE = nodes.create_unscoped_node_type("legacy-compound-suite")
+_LEGACY_MATRIX_COMPOUND_SUITE = nodes.create_unscoped_node_type("legacy-matrix-compound-suite")
+_LEGACY_MATRIX_CONFIG = nodes.create_scoped_node_type("legacy-matrix-config", _LEGACY_MATRIX_COMPOUND_SUITE.kind)
+
 def _create_target(
         *,
         name,
@@ -244,7 +249,9 @@
 def _resultdb(
         *,
         enable = False,
-        has_native_resultdb_integration = False):
+        has_native_resultdb_integration = False,
+        result_format = None,
+        result_file = None):
     """Define the ResultDB integration to be used for a test.
 
     Args:
@@ -253,6 +260,8 @@
             native integration with resultdb. If not, result_adapter
             will be used, which parses output to determine results to
             upload results to ResultDB.
+        result_format: The format of the test results.
+        result_file: The file to write out test results to.
 
     Return:
         A struct that can be passed to the resultdb argument of
@@ -261,10 +270,13 @@
     return struct(
         enable = enable,
         has_native_resultdb_integration = has_native_resultdb_integration,
+        result_format = result_format,
+        result_file = result_file,
     )
 
 def _swarming(
         *,
+        enable = None,
         dimensions = None,
         optional_dimensions = None,
         containment_type = None,
@@ -273,6 +285,7 @@
         hard_timeout_sec = None,
         io_timeout_sec = None,
         shards = None,
+        idempotent = None,
         service_account = None,
         named_caches = None):
     """Define the swarming details for a test.
@@ -281,6 +294,7 @@
     unless otherwise indicated.
 
     Args:
+        enable: Whether swarming should be enabled for the test.
         dimensions: A dict of dimensions to apply to all dimension sets
             for the test. This can only be specified in a mixin. After
             any dimension sets from the mixin are added to the test, the
@@ -301,12 +315,15 @@
         io_timeout_sec: The maximum time that can elapse between output
             from tasks for the test.
         shards: The number of tasks to split the test into.
+        idempotent: Whether the test task should be considered
+            idempotent.
         service_account: The service account used to run the test's
             tasks.
         named_caches: A list of swarming.cache that detail the named
             caches that should be mounted for the test's tasks.
     """
     return struct(
+        enable = enable,
         dimensions = dimensions,
         optional_dimensions = optional_dimensions,
         containment_type = containment_type,
@@ -315,6 +332,7 @@
         hard_timeout_sec = hard_timeout_sec,
         io_timeout_sec = io_timeout_sec,
         shards = shards,
+        idempotent = idempotent,
         service_account = service_account,
         named_caches = named_caches,
     )
@@ -347,11 +365,15 @@
         args = None,
         precommit_args = None,
         android_args = None,
+        chromeos_args = None,
+        desktop_args = None,
+        lacros_args = None,
         linux_args = None,
         mac_args = None,
         win64_args = None,
         swarming = None,
         android_swarming = None,
+        chromeos_swarming = None,
         skylab = None,
         use_isolated_scripts_api = None,
         ci_only = None,
@@ -359,7 +381,9 @@
         resultdb = None,
         isolate_profile_data = None,
         merge = None,
-        timeout_sec = None):
+        timeout_sec = None,
+        shards = None,
+        experiment_percentage = None):
     """Define values to be mixed into a target.
 
     Unless otherwise specified, each field will overwrite an existing
@@ -379,9 +403,18 @@
         android_args: Arguments to be passed to the test when the
             builder is targeting android. Will be appended to any
             existing android_args for the test.
+        chromeos_args: Arguments to be passed to the test when the
+            builder is targeting chromeos. Will be appended to any
+            existing chromeos_args for the test.
+        desktop_args: Arguments to be passed to the test when the
+            builder is targeting linux, mac or windows. Will be appended
+            to any existing desktop_args for the test.
         linux_args: Arguments to be passed to the test when the builder
             is targeting linux. Will be appended to any existing
             linux_args for the test.
+        lacros_args: Arguments to be passed to the test when the
+            builder is targeting lacros. Will be appended to any
+            existing lacros_args for the test.
         mac_args: Arguments to be passed to the test when the builder is
             targeting mac. Will be appended to any existing mac_args for
             the test.
@@ -393,6 +426,8 @@
             to the test's swarming details.
         android_swarming: A targets.swarming to be applied to the test
             when the builder is targeting android.
+        chromeos_swarming: A targets.swarming to be applied to the test
+            when the builder is targeting chromeos.
         skylab: A targets.skylab to be applied to the test. See
             targets.skylab for details about how each field is applied
             to the test.
@@ -412,6 +447,12 @@
         merge: A targets.merge describing the invocation to merge the
             results from the test's tasks.
         timeout_sec: The maximum time the test can take to run.
+        shards: The number of shards to use for running the test on
+            skylab.
+        experiment_percentage: An integer in the range [0, 100]
+            indicating the percentage chance that the test will be run,
+            with failures in the test not resulting in failures in the
+            build.
 
     Returns:
         A dict containing the values to be mixed in.
@@ -420,12 +461,16 @@
         description = description,
         args = args,
         precommit_args = precommit_args,
+        android_args = android_args,
+        chromeos_args = chromeos_args,
+        desktop_args = desktop_args,
+        lacros_args = lacros_args,
         linux_args = linux_args,
         mac_args = mac_args,
         win64_args = win64_args,
         swarming = swarming,
-        android_args = android_args,
         android_swarming = android_swarming,
+        chromeos_swarming = chromeos_swarming,
         skylab = skylab,
         use_isolated_scripts_api = use_isolated_scripts_api,
         ci_only = ci_only,
@@ -434,10 +479,12 @@
         isolate_profile_data = isolate_profile_data,
         merge = merge,
         timeout_sec = timeout_sec,
+        shards = shards,
+        experiment_percentage = experiment_percentage,
     )
     return {k: v for k, v in mixin_values.items() if v != None}
 
-def _mixin(*, name, **kwargs):
+def _mixin(*, name = None, **kwargs):
     """Define a mixin used for defining tests.
 
     //infra/config/generated/testing/mixins.pyl will be generated from
@@ -465,7 +512,7 @@
     """Define a variant used for defining tests.
 
     //infra/config/generated/testing/variants.pyl will be generated from
-    the declared mixins to be copied to //testing/buildbot and consumed
+    the declared variants to be copied to //testing/buildbot and consumed
     by //testing/buildbot/generate_buildbot_json.py.
 
     Args:
@@ -493,6 +540,162 @@
 
     graph.add_edge(keys.project(), key)
 
+def _legacy_basic_suite(*, name, tests):
+    """Define a basic suite.
+
+    //infra/config/generated/testing/test_suites.pyl will be generated from the
+    declared basic suites, as well as declared compound suites (see
+    _legacy_compound_suite) and declared matrix compound suites (see
+    _legacy_matrix_compound_suite) to be copied to //testing/buildbot and
+    consumed by //testing/buildbot/generate_buildbot_json.py.
+
+    A basic suite is a collection of tests that can be specified in
+    waterfalls.pyl as the test suite for one of the test types or collected into
+    a compound suite or matrix compound suite.
+
+    Args:
+        name: The name of the suite.
+        tests: A dict mapping the name of the test to the base definition for
+            the test, which must be an instance returned from
+            targets.legacy_test_config or None. A None value is equivalent to
+            targets.legacy_test_config(), which results in a test that uses the
+            isolate with the same name as the test.
+    """
+    key = _LEGACY_BASIC_SUITE.add(name, props = dict(
+        tests = tests,
+    ))
+    graph.add_edge(keys.project(), key)
+
+def _legacy_test_config(
+        *,
+        script = None,
+        test = None,
+        override_compile_targets = [],
+        results_handler = None,
+        telemetry_test_name = None,
+        tast_expr = None,
+        test_level_retries = None,
+        mixins = [],
+        remove_mixins = [],
+        **kwargs):
+    """Define the details of a test in a basic suite.
+
+    Args:
+        script: The name of the file within the //testing/scripts directory to
+            run as the test. Only applicable to script tests.
+        test: The name of the isolate to run as the test. Only applicable to
+            gtests, isolated script tests and junit tests.
+        override_compile_targets: A list of compile targets that need to be
+            built to run the test instead of whatever the standard set of
+            compile targets would be. Only applicable to gtests, isolated
+            script tests and script tests.
+        results_handler: The name of the results handler to use for the test.
+            Only applicable to isolated script tests and gtests that set
+            use_isolated_scripts_api.
+        telemetry_test_name: The telemetry test to run. Only applicable to
+            telemetry test types.
+        tast_expr: The tast expression to run. Only applicable to skylab tests.
+        test_level_retries: The number of times to retry tests. Only applicable
+            to skylab tests.
+        mixins: A list of names of mixins to apply to the test.
+        remove_mixins: A list of names of mixins to skip applying to the test.
+        **kwargs: The mixin values, see _mixin_values for allowed keywords and
+            their meanings.
+
+    Returns:
+        An object that can be used as a value in the dict passed to the
+        tests argument of targets.legacy_basic_suite.
+    """
+    return struct(
+        script = script,
+        test = test,
+        override_compile_targets = override_compile_targets,
+        telemetry_test_name = telemetry_test_name,
+        results_handler = results_handler,
+        tast_expr = tast_expr,
+        test_level_retries = test_level_retries,
+        mixins = mixins,
+        remove_mixins = remove_mixins,
+        mixin_values = _mixin_values(**kwargs),
+    )
+
+def _legacy_compound_suite(*, name, basic_suites):
+    """Define a matrix compound suite.
+
+    //infra/config/generated/testing/test_suites.pyl will be generated from the
+    declared compound suites, as well as declared basic suites (see
+    _legacy_basic_suite) and declared matrix compound suites (see
+    _legacy_matrix_compound_suite) to be copied to //testing/buildbot and
+    consumed by //testing/buildbot/generate_buildbot_json.py.
+
+    A compound suite is a collection of basic suites that can be specified in
+    waterfalls.pyl as the test suite for one of the test types.
+
+    Args:
+        name: The name of the matrix compound suite.
+        basic_suites: A list of names of basic suites to compose.
+    """
+    key = _LEGACY_COMPOUND_SUITE.add(name)
+    graph.add_edge(keys.project(), key)
+
+    for s in basic_suites:
+        graph.add_edge(key, _LEGACY_BASIC_SUITE.key(s))
+
+def _legacy_matrix_compound_suite(*, name, basic_suites):
+    """Define a matrix compound suite.
+
+    //infra/config/generated/testing/test_suites.pyl will be generated from the
+    declared matrix compound suites, as well as declared basic suites (see
+    _legacy_basic_suite) and declared compound suites (see
+    _legacy_compound_suite) to be copied to //testing/buildbot and
+    consumed by //testing/buildbot/generate_buildbot_json.py.
+
+    A matrix compound suite is a suite that composes multiple basic suites, with
+    the capability to expand the tests of basic suites with specified variants.
+    A matrix compound suite can be specified in waterfalls.pyl as the test suite
+    for one of the test suite types.
+
+    Args:
+        name: The name of the matrix compound suite.
+        basic_suites: A dict mapping the name of a basic suite to the matrix
+            config for the suite, which must be an instance returned from
+            targets.legacy_matrix_config. A None value is equivalent to
+            targets.legacy_matrix_config(), which will add the tests from the
+            basic suite without performing any variant expansion.
+    """
+    key = _LEGACY_MATRIX_COMPOUND_SUITE.add(name)
+    graph.add_edge(keys.project(), key)
+
+    for basic_suite_name, config in basic_suites.items():
+        # This edge won't actually be used, but it ensures that the basic suite exists
+        graph.add_edge(key, _LEGACY_BASIC_SUITE.key(basic_suite_name))
+        matrix_config_key = _LEGACY_MATRIX_CONFIG.add(name, basic_suite_name)
+        graph.add_edge(key, matrix_config_key)
+        config = config or _legacy_matrix_config()
+        for m in config.mixins:
+            graph.add_edge(matrix_config_key, _TARGET_MIXIN.key(m))
+        for v in config.variants:
+            graph.add_edge(matrix_config_key, _TARGET_VARIANT.key(v))
+
+def _legacy_matrix_config(*, mixins = [], variants = []):
+    """Define the matrix details for a basic suite.
+
+    Args:
+        mixins: An optional list of mixins to apply to the tests of the
+            corresponding basic suite.
+        variants: An optional list of variants with which to expand the tests of
+            the corresponding basic suite. If not provided, then the tests from
+            the basic suite will be used without any variants applied.
+
+    Returns:
+        An object that can be used as a value in the dict passed to the
+        basic_suites argument of targets.legacy_matrix_compound_suite.
+    """
+    return struct(
+        mixins = mixins,
+        variants = variants,
+    )
+
 targets = struct(
     # Functions for declaring isolates
     compile_target = _compile_target,
@@ -503,6 +706,11 @@
     windowed_test_launcher = _windowed_test_launcher,
 
     # Functions for declaring bundles
+    legacy_basic_suite = _legacy_basic_suite,
+    legacy_test_config = _legacy_test_config,
+    legacy_compound_suite = _legacy_compound_suite,
+    legacy_matrix_compound_suite = _legacy_matrix_compound_suite,
+    legacy_matrix_config = _legacy_matrix_config,
     mixin = _mixin,
     variant = _variant,
     cipd_package = _cipd_package,
@@ -515,7 +723,7 @@
 _PYL_HEADER_FMT = """\
 # THIS IS A GENERATED FILE DO NOT EDIT!!!
 # Instead:
-# 1. Modify //infra/config/targets/{star_file}
+# 1. Modify {star_file}
 # 2. Run //infra/config/main.star
 # 3. Run //infra/config/scripts/sync-pyl-files.py
 
@@ -547,7 +755,7 @@
             entries.append("    ],")
         entries.append("  },")
     ctx.output["testing/gn_isolate_map.pyl"] = _PYL_HEADER_FMT.format(
-        star_file = "targets.star",
+        star_file = "//infra/config/targets/targets.star",
         entries = "\n".join(entries),
     )
 
@@ -560,7 +768,10 @@
     )
 
     def add_line(s):
-        state["lines"].append(" " * state["indent"] + s)
+        if s:
+            state["lines"].append(" " * state["indent"] + s)
+        else:
+            state["lines"].append("")
 
     def open_scope(s):
         add_line(s)
@@ -580,8 +791,75 @@
         output = output,
     )
 
+def _generate_swarming_values(formatter, swarming):
+    """Generate the pyl definitions for swarming fields.
+
+    Swarming fields are the fields contained in values for the swarming,
+    android_swarming and chromeos_swarming fields in mixins/variants/tests.
+
+    Args:
+      formatter: The formatter object used for generating indented
+        output.
+      swarming: The swarming value to generate the fields for.
+    """
+
+    def dimension_value(x):
+        if x == None:
+            return x
+        return "'{}'".format(x)
+
+    if swarming.enable != None:
+        formatter.add_line("'can_use_on_swarming_builders': {},".format(swarming.enable))
+    if swarming.shards:
+        formatter.add_line("'shards': {},".format(swarming.shards))
+    if swarming.dimensions:
+        formatter.open_scope("'dimensions': {")
+        for dim, value in swarming.dimensions.items():
+            formatter.add_line("'{}': {},".format(dim, dimension_value(value)))
+        formatter.close_scope("},")
+    if swarming.optional_dimensions:
+        formatter.open_scope("'optional_dimensions': {")
+        for timeout, dimensions in swarming.optional_dimensions.items():
+            formatter.open_scope("'{}': {{".format(timeout))
+            for dim, value in dimensions.items():
+                formatter.add_line("'{}': {},".format(dim, dimension_value(value)))
+            formatter.close_scope("},")
+        formatter.close_scope("},")
+    if swarming.containment_type:
+        formatter.add_line("'containment_type': '{}',".format(swarming.containment_type))
+    if swarming.cipd_packages:
+        formatter.open_scope("'cipd_packages': [")
+        for package in swarming.cipd_packages:
+            formatter.open_scope("{")
+            formatter.add_line("'cipd_package': '{}',".format(package.package))
+            formatter.add_line("'location': '{}',".format(package.location))
+            formatter.add_line("'revision': '{}',".format(package.revision))
+            formatter.close_scope("},")
+        formatter.close_scope("],")
+    if swarming.expiration_sec:
+        formatter.add_line("'expiration': {},".format(swarming.expiration_sec))
+    if swarming.hard_timeout_sec:
+        formatter.add_line("'hard_timeout': {},".format(swarming.hard_timeout_sec))
+    if swarming.io_timeout_sec:
+        formatter.add_line("'io_timeout': {},".format(swarming.io_timeout_sec))
+    if swarming.idempotent != None:
+        formatter.add_line("'idempotent': {},".format(swarming.idempotent))
+    if swarming.named_caches:
+        formatter.open_scope("'named_caches': [")
+        for cache in swarming.named_caches:
+            formatter.open_scope("{")
+            formatter.add_line("'name': '{}',".format(cache.name))
+            formatter.add_line("'path': '{}',".format(cache.path))
+            formatter.close_scope("},")
+        formatter.close_scope("],")
+    if swarming.service_account:
+        formatter.add_line("'service_account': '{}',".format(swarming.service_account))
+
 def _generate_mixin_values(formatter, mixin, generate_skylab_container = False):
-    """Generate the pyl definitions for mixin/variant fields.
+    """Generate the pyl definitions for mixin fields.
+
+    Mixin fields are fields that are common to mixins, variants and test
+    definitions within basic suites.
 
     Args:
       formatter: The formatter object used for generating indented
@@ -598,6 +876,10 @@
     for args_attr in (
         "args",
         "precommit_args",
+        "android_args",
+        "chromeos_args",
+        "desktop_args",
+        "lacros_args",
         "linux_args",
         "mac_args",
         "win64_args",
@@ -620,6 +902,13 @@
     if "timeout_sec" in mixin:
         formatter.add_line("'timeout_sec': {},".format(mixin["timeout_sec"]))
 
+    for swarming_attr in ("swarming", "android_swarming", "chromeos_swarming"):
+        if swarming_attr in mixin:
+            swarming = mixin[swarming_attr]
+            formatter.open_scope("'{}': {{".format(swarming_attr))
+            _generate_swarming_values(formatter, swarming)
+            formatter.close_scope("},")
+
     if "merge" in mixin:
         merge = mixin["merge"]
         formatter.open_scope("'merge': {")
@@ -631,67 +920,6 @@
             formatter.close_scope("],")
         formatter.close_scope("},")
 
-    if "resultdb" in mixin:
-        resultdb = mixin["resultdb"]
-        formatter.open_scope("'resultdb': {")
-        if resultdb.enable:
-            formatter.add_line("'enable': True,")
-        if resultdb.has_native_resultdb_integration:
-            formatter.add_line("'has_native_resultdb_integration': True,")
-        formatter.close_scope("},")
-
-    def dimension_value(x):
-        if x == None:
-            return x
-        return "'{}'".format(x)
-
-    if "swarming" in mixin:
-        swarming = mixin["swarming"]
-        formatter.open_scope("'swarming': {")
-        if swarming.shards:
-            formatter.add_line("'shards': {},".format(swarming.shards))
-        if swarming.dimensions:
-            formatter.open_scope("'dimensions': {")
-            for dim, value in swarming.dimensions.items():
-                formatter.add_line("'{}': {},".format(dim, dimension_value(value)))
-            formatter.close_scope("},")
-        if swarming.optional_dimensions:
-            formatter.open_scope("'optional_dimensions': {")
-            for timeout, dimensions in swarming.optional_dimensions.items():
-                formatter.open_scope("'{}': {{".format(timeout))
-                for dim, value in dimensions.items():
-                    formatter.add_line("'{}': {},".format(dim, dimension_value(value)))
-                formatter.close_scope("},")
-            formatter.close_scope("},")
-        if swarming.containment_type:
-            formatter.add_line("'containment_type': '{}',".format(swarming.containment_type))
-        if swarming.cipd_packages:
-            formatter.open_scope("'cipd_packages': [")
-            for package in swarming.cipd_packages:
-                formatter.open_scope("{")
-                formatter.add_line("'cipd_package': '{}',".format(package.package))
-                formatter.add_line("'location': '{}',".format(package.location))
-                formatter.add_line("'revision': '{}',".format(package.revision))
-                formatter.close_scope("},")
-            formatter.close_scope("],")
-        if swarming.expiration_sec:
-            formatter.add_line("'expiration': {},".format(swarming.expiration_sec))
-        if swarming.hard_timeout_sec:
-            formatter.add_line("'hard_timeout': {},".format(swarming.hard_timeout_sec))
-        if swarming.io_timeout_sec:
-            formatter.add_line("'io_timeout': {},".format(swarming.io_timeout_sec))
-        if swarming.named_caches:
-            formatter.open_scope("'named_caches': [")
-            for cache in swarming.named_caches:
-                formatter.open_scope("{")
-                formatter.add_line("'name': '{}',".format(cache.name))
-                formatter.add_line("'path': '{}',".format(cache.path))
-                formatter.close_scope("},")
-            formatter.close_scope("],")
-        if swarming.service_account:
-            formatter.add_line("'service_account': '{}',".format(swarming.service_account))
-        formatter.close_scope("},")
-
     if "skylab" in mixin:
         skylab = mixin["skylab"]
         if generate_skylab_container:
@@ -715,6 +943,28 @@
         if generate_skylab_container:
             formatter.close_scope("},")
 
+    if "resultdb" in mixin:
+        resultdb = mixin["resultdb"]
+        formatter.open_scope("'resultdb': {")
+        if resultdb.enable:
+            formatter.add_line("'enable': True,")
+        if resultdb.has_native_resultdb_integration:
+            formatter.add_line("'has_native_resultdb_integration': True,")
+        if resultdb.result_format != None:
+            formatter.add_line("'result_format': '{}',".format(resultdb.result_format))
+        if resultdb.result_file != None:
+            formatter.add_line("'result_file': '{}',".format(resultdb.result_file))
+        formatter.close_scope("},")
+
+    if "use_isolated_scripts_api" in mixin:
+        formatter.add_line("'use_isolated_scripts_api': {},".format(mixin["use_isolated_scripts_api"]))
+
+    if "shards" in mixin:
+        formatter.add_line("'shards': {},".format(mixin["shards"]))
+
+    if "experiment_percentage" in mixin:
+        formatter.add_line("'experiment_percentage': {},".format(mixin["experiment_percentage"]))
+
 def _generate_mixins_pyl(ctx):
     formatter = _formatter()
 
@@ -727,7 +977,7 @@
         formatter.close_scope("},")
 
     ctx.output["testing/mixins.pyl"] = _PYL_HEADER_FMT.format(
-        star_file = "mixins.star",
+        star_file = "//infra/config/targets/mixins.star",
         entries = formatter.output(),
     )
 
@@ -756,8 +1006,113 @@
         formatter.close_scope("},")
 
     ctx.output["testing/variants.pyl"] = _PYL_HEADER_FMT.format(
-        star_file = "variants.star",
+        star_file = "//infra/config/targets/variants.star",
         entries = formatter.output(),
     )
 
 lucicfg.generator(_generate_variants_pyl)
+
+def _generate_test_suites_pyl(ctx):
+    formatter = _formatter()
+
+    formatter.open_scope("'basic_suites': {")
+
+    for suite in graph.children(keys.project(), _LEGACY_BASIC_SUITE.kind, graph.DEFINITION_ORDER):
+        formatter.add_line("")
+        formatter.open_scope("'{}': {{".format(suite.key.id))
+
+        for test_name, test_config in suite.props.tests.items():
+            if not test_config:
+                formatter.add_line("'{}': {{}},".format(test_name))
+                continue
+
+            formatter.open_scope("'{}': {{".format(test_name))
+
+            if test_config.script:
+                formatter.add_line("'script': '{}',".format(test_config.script))
+
+            if test_config.test:
+                formatter.add_line("'test': '{}',".format(test_config.test))
+            if test_config.override_compile_targets:
+                formatter.open_scope("'override_compile_targets': [")
+                for t in test_config.override_compile_targets:
+                    formatter.add_line("'{}',".format(t))
+                formatter.close_scope("],")
+            if test_config.results_handler:
+                formatter.add_line("'results_handler': '{}',".format(test_config.results_handler))
+
+            if test_config.telemetry_test_name:
+                formatter.add_line("'telemetry_test_name': '{}',".format(test_config.telemetry_test_name))
+
+            if test_config.tast_expr:
+                formatter.add_line("'tast_expr': '{}',".format(test_config.tast_expr))
+            if test_config.test_level_retries:
+                formatter.add_line("'test_level_retries': {},".format(test_config.test_level_retries))
+
+            if test_config.mixins:
+                formatter.open_scope("'mixins': [")
+                for m in test_config.mixins:
+                    formatter.add_line("'{}',".format(m))
+                formatter.close_scope("],")
+            if test_config.remove_mixins:
+                formatter.open_scope("'remove_mixins': [")
+                for m in test_config.remove_mixins:
+                    formatter.add_line("'{}',".format(m))
+                formatter.close_scope("],")
+
+            _generate_mixin_values(formatter, test_config.mixin_values)
+
+            formatter.close_scope("},")
+
+        formatter.close_scope("},")
+
+    formatter.close_scope("},")
+
+    formatter.add_line("")
+
+    formatter.open_scope("'compound_suites': {")
+
+    for suite in graph.children(keys.project(), _LEGACY_COMPOUND_SUITE.kind, graph.DEFINITION_ORDER):
+        formatter.add_line("")
+        formatter.open_scope("'{}': [".format(suite.key.id))
+        for basic_suite in graph.children(suite.key, _LEGACY_BASIC_SUITE.kind, graph.DEFINITION_ORDER):
+            formatter.add_line("'{}',".format(basic_suite.key.id))
+        formatter.close_scope("],")
+
+    formatter.close_scope("},")
+
+    formatter.add_line("")
+
+    formatter.open_scope("'matrix_compound_suites': {")
+
+    for suite in graph.children(keys.project(), _LEGACY_MATRIX_COMPOUND_SUITE.kind, graph.DEFINITION_ORDER):
+        formatter.add_line("")
+        formatter.open_scope("'{}': {{".format(suite.key.id))
+        for matrix_config in graph.children(suite.key, _LEGACY_MATRIX_CONFIG.kind, graph.DEFINITION_ORDER):
+            mixins = graph.children(matrix_config.key, _TARGET_MIXIN.kind, graph.DEFINITION_ORDER)
+            variants = graph.children(matrix_config.key, _TARGET_VARIANT.kind, graph.DEFINITION_ORDER)
+            if not (mixins or variants):
+                formatter.add_line("'{}': {{}},".format(matrix_config.key.id))
+                continue
+            formatter.open_scope("'{}': {{".format(matrix_config.key.id))
+            if mixins:
+                formatter.open_scope("'mixins': [")
+                for m in mixins:
+                    formatter.add_line("'{}',".format(m.key.id))
+                formatter.close_scope("],")
+            if variants:
+                formatter.open_scope("'variants': [")
+                for v in variants:
+                    formatter.add_line("'{}',".format(v.key.id))
+                formatter.close_scope("],")
+            formatter.close_scope("},")
+        formatter.close_scope("},")
+
+    formatter.close_scope("},")
+
+    ctx.output["testing/test_suites.pyl"] = _PYL_HEADER_FMT.format(
+        star_file = "//infra/config/targets/basic_suites.star, //infra/config/targets/compound_suites.star and/or //infra/config/targets/matrix_compound_suites.star",
+        entries = formatter.output(),
+    )
+
+lucicfg.generator(_generate_test_suites_pyl)
diff --git a/infra/config/main.star b/infra/config/main.star
index 31bfd5a..5d1a9d6f 100755
--- a/infra/config/main.star
+++ b/infra/config/main.star
@@ -239,6 +239,9 @@
 
 exec("//recipes.star")
 exec("//gn_args/gn_args.star")
+exec("//targets/basic_suites.star")
+exec("//targets/compound_suites.star")
+exec("//targets/matrix_compound_suites.star")
 exec("//targets/mixins.star")
 exec("//targets/targets.star")
 exec("//targets/variants.star")
diff --git a/infra/config/scripts/sync-pyl-files.py b/infra/config/scripts/sync-pyl-files.py
index 0de35e1..6dd357d 100755
--- a/infra/config/scripts/sync-pyl-files.py
+++ b/infra/config/scripts/sync-pyl-files.py
@@ -58,7 +58,12 @@
 
 
 def main(args):
-  for f in ('gn_isolate_map.pyl', 'mixins.pyl', 'variants.pyl'):
+  for f in (
+      'gn_isolate_map.pyl',
+      'mixins.pyl',
+      'test_suites.pyl',
+      'variants.pyl',
+  ):
     error = args.func(os.path.normpath(f'{GENERATED_TESTING_DIR}/{f}'),
                       os.path.normpath(f'{TESTING_BUILDBOT_DIR}/{f}'))
     if error is not None:
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star
index e18c268..ac81c42 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -65,7 +65,8 @@
     ),
     builderless = False,
     cores = None,
-    tree_closing = True,
+    # TODO(crbug.com/1486663): Restore tree-closing when bot is fixed.
+    # tree_closing = True,
     console_view_entry = consoles.console_view_entry(
         category = "builder|arm",
         short_name = "san",
diff --git a/infra/config/targets/basic_suites.star b/infra/config/targets/basic_suites.star
new file mode 100644
index 0000000..39278073
--- /dev/null
+++ b/infra/config/targets/basic_suites.star
@@ -0,0 +1,6900 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file contains suite definitions that can be used in
+# //testing/buildbot/waterfalls.pyl and will also be usable for builders that
+# set their tests in starlark (once that is ready). The legacy_ prefix on the
+# declarations indicates the capability to be used in //testing/buildbot. Once a
+# suite is no longer needed in //testing/buildbot, targets.bundle (which does
+# not yet exist) can be used for grouping tests in a more flexible manner.
+
+load("//lib/targets.star", "targets")
+
+targets.legacy_basic_suite(
+    name = "android_12_fieldtrial_webview_tests",
+    tests = {
+        "webview_trichrome_64_cts_tests_no_field_trial": targets.legacy_test_config(
+            test = "webview_trichrome_64_cts_tests",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 2,
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "chromium/android_webview/tools/cts_archive",
+                        location = "android_webview/tools/cts_archive",
+                        revision = "akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC",
+                    ),
+                ],
+            ),
+        ),
+        "webview_ui_test_app_test_apk_no_field_trial": targets.legacy_test_config(
+            test = "webview_ui_test_app_test_apk",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            ci_only = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_ar_gtests",
+    tests = {
+        "monochrome_public_test_ar_apk": None,
+        # Name is vr_*, but actually has AR tests.
+        "vr_android_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_ddready_vr_gtests",
+    tests = {
+        "chrome_public_test_vr_apk-ddready-cardboard": targets.legacy_test_config(
+            test = "chrome_public_test_vr_apk",
+            mixins = [
+                "vr_instrumentation_test",
+            ],
+            args = [
+                "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "chrome_public_test_vr_apk-ddready-ddview": targets.legacy_test_config(
+            test = "chrome_public_test_vr_apk",
+            mixins = [
+                "skia_gold_test",
+                "vr_instrumentation_test",
+            ],
+            args = [
+                "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json",
+                "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk",
+            ],
+            swarming = targets.swarming(
+                shards = 4,
+            ),
+        ),
+        "chrome_public_test_vr_apk-ddready-don-enabled": targets.legacy_test_config(
+            test = "chrome_public_test_vr_apk",
+            mixins = [
+                "vr_instrumentation_test",
+            ],
+            args = [
+                "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_don_setupcomplete.json",
+                "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk",
+                "--annotation=Restriction=VR_DON_Enabled",
+                "--vr-don-enabled",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_emulator_specific_chrome_public_tests",
+    tests = {
+        "chrome_public_test_apk": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+                "emulator-8-cores",  # Use 8-core to shorten test runtime.
+            ],
+            # These tests launch external intent thus require playstore to be
+            # present. See crbug.com/1056330 for more details.
+            # Exclude them here since this test suite will run on emulator
+            # on images that do not have playstore.
+            # They will be ran in chrome_public_test_apk_with_playstore below.
+            args = [
+                "--gtest_filter=-org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*",
+            ],
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+        "chrome_public_test_apk_with_playstore": targets.legacy_test_config(
+            test = "chrome_public_test_apk",
+            mixins = [
+                "skia_gold_test",
+            ],
+            # These tests launch external intent thus require playstore to be
+            # present. See crbug.com/1056330 for more details.
+            # They should be ran in emulator on images that have playstore.
+            args = [
+                "--gtest_filter=org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*",
+            ],
+        ),
+        "chrome_public_unit_test_apk": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            swarming = targets.swarming(
+                shards = 4,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_finch_smoke_tests",
+    tests = {
+        "chrome_finch_smoke_tests": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            args = [
+                "--finch-seed-path",
+                "../../variations_seed",
+            ],
+        ),
+        "monochrome_finch_smoke_tests": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            args = [
+                "--finch-seed-path",
+                "../../variations_seed",
+            ],
+        ),
+        "variations_smoke_tests": targets.legacy_test_config(
+            test = "variations_desktop_smoke_tests",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--target-platform=android",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_isolated_scripts",
+    tests = {
+        "content_shell_crash_test": targets.legacy_test_config(
+            args = [
+                "--platform=android",
+            ],
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_monochrome_smoke_tests",
+    tests = {
+        "monochrome_public_bundle_smoke_test": None,
+        "monochrome_public_smoke_test": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_oreo_standard_gtests",
+    tests = {
+        "chrome_public_test_apk": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            swarming = targets.swarming(
+                shards = 5,
+            ),
+        ),
+        "chrome_public_unit_test_apk": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+        ),
+        "webview_instrumentation_test_apk": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 5,
+                expiration_sec = 10800,
+            ),
+        ),
+    },
+)
+
+# TODO(crbug.com/1111436): Deprecate this group in favor of
+# android_pie_rel_gtests if/when android Pie capacity is fully restored.
+targets.legacy_basic_suite(
+    name = "android_pie_rel_reduced_capacity_gtests",
+    tests = {
+        "android_browsertests": None,
+        "blink_platform_unittests": None,
+        "cc_unittests": None,
+        "content_browsertests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+        "viz_unittests": None,
+        "webview_instrumentation_test_apk": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 7,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_smoke_tests",
+    tests = {
+        "chrome_public_smoke_test": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_specific_chromium_gtests",
+    tests = {
+        "android_browsertests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "android_sync_integration_tests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-batch-limit=1",
+            ],
+            swarming = targets.swarming(
+                shards = 1,
+            ),
+        ),
+        "android_webview_unittests": None,
+        "content_shell_test_apk": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        # TODO(kbr): these are actually run on many of the GPU bots, which have
+        # physical hardware for several of the desktop OSs. Once the GPU JSON
+        # generation script is merged with this one, this should be promoted from
+        # the Android-specific section.
+        "gl_tests_validating": targets.legacy_test_config(
+            test = "gl_tests",
+            args = [
+                "--use-cmd-decoder=validating",
+            ],
+        ),
+        # TODO(kbr): these are actually run on many of the GPU bots, which have
+        # physical hardware for several of the desktop OSs. Once the GPU JSON
+        # generation script is merged with this one, this should be promoted from
+        # the Android-specific section.
+        "gl_unittests": None,
+        "mojo_test_apk": None,
+        "ui_android_unittests": None,
+        "webview_instrumentation_test_apk": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 7,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_specific_coverage_java_tests",
+    tests = {
+        "content_shell_test_apk": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "mojo_test_apk": None,
+        "webview_instrumentation_test_apk": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 7,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_trichrome_smoke_tests",
+    tests = {
+        "trichrome_chrome_bundle_smoke_test": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_webview_gpu_telemetry_tests",
+    tests = {
+        "android_webview_pixel_skia_gold_test": targets.legacy_test_config(
+            telemetry_test_name = "pixel",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "android_wpr_record_replay_tests",
+    tests = {
+        "chrome_java_test_wpr_tests": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ash_pixel_gtests",
+    tests = {
+        "ash_pixeltests": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            args = [
+                "--enable-pixel-output-in-tests",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "aura_gtests",
+    tests = {
+        "aura_unittests": None,
+        "compositor_unittests": None,
+        "wm_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "bfcache_android_specific_gtests",
+    tests = {
+        "bf_cache_android_browsertests": targets.legacy_test_config(
+            test = "android_browsertests",
+            args = [
+                "--disable-features=BackForwardCache",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "bfcache_generic_gtests",
+    tests = {
+        "bf_cache_content_browsertests": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--disable-features=BackForwardCache",
+            ],
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "bfcache_linux_specific_gtests",
+    tests = {
+        "bf_cache_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--disable-features=BackForwardCache",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "blink_unittests",
+    tests = {
+        "blink_unit_tests": targets.legacy_test_config(
+            test = "blink_unittests",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cast_audio_specific_chromium_gtests",
+    tests = {
+        "cast_audio_backend_unittests": None,
+        "cast_base_unittests": None,
+        "cast_cast_core_unittests": None,
+        "cast_crash_unittests": None,
+        "cast_media_unittests": None,
+        "cast_shell_browsertests": targets.legacy_test_config(
+            args = [
+                "--enable-local-file-accesses",
+                "--ozone-platform=headless",
+                "--no-sandbox",
+                "--test-launcher-jobs=1",
+            ],
+            swarming = targets.swarming(
+                enable = False,  # https://crbug.com/861753
+            ),
+        ),
+        "cast_shell_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cast_junit_tests",
+    tests = {
+        "cast_base_junit_tests": None,
+        "cast_shell_junit_tests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cast_video_specific_chromium_gtests",
+    tests = {
+        "cast_display_settings_unittests": targets.legacy_test_config(
+            experiment_percentage = 100,
+        ),
+        "cast_graphics_unittests": None,
+        "views_unittests": targets.legacy_test_config(
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_android_finch_smoke_tests",
+    tests = {
+        "variations_android_smoke_tests": targets.legacy_test_config(
+            test = "variations_desktop_smoke_tests",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--target-platform=android",
+            ],
+        ),
+        "variations_webview_smoke_tests": targets.legacy_test_config(
+            test = "variations_desktop_smoke_tests",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--target-platform=webview",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_finch_smoke_tests",
+    tests = {
+        "variations_desktop_smoke_tests": targets.legacy_test_config(
+            test = "variations_desktop_smoke_tests",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            chromeos_args = [
+                "--target-platform=cros",
+            ],
+            lacros_args = [
+                "--target-platform=lacros",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_isolated_script_tests",
+    tests = {
+        "chrome_sizes": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+            ),
+        ),
+        "variations_smoke_tests": targets.legacy_test_config(
+            test = "variations_smoke_tests",
+            mixins = [
+                "skia_gold_test",
+            ],
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_private_code_test_isolated_scripts",
+    tests = {
+        "chrome_private_code_test": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_profile_generator_tests",
+    tests = {
+        "chrome_public_apk_profile_tests": targets.legacy_test_config(
+            test = "chrome_public_apk_baseline_profile_generator",
+            ci_only = True,
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_public_tests",
+    tests = {
+        "chrome_public_test_apk": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            swarming = targets.swarming(
+                shards = 19,
+            ),
+        ),
+        "chrome_public_unit_test_apk": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_public_wpt",
+    tests = {
+        "chrome_public_wpt": targets.legacy_test_config(
+            results_handler = "layout tests",
+            args = [
+                "--no-wpt-internal",
+            ],
+            swarming = targets.swarming(
+                shards = 36,
+                expiration_sec = 18000,
+                hard_timeout_sec = 14400,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_sizes",
+    tests = {
+        "chrome_sizes": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chrome_sizes_android",
+    tests = {
+        "chrome_sizes": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            remove_mixins = [
+                "android_r",
+                "bullhead",
+                "flame",
+                "marshmallow",
+                "mdarcy",
+                "oreo_fleet",
+                "oreo_mr1_fleet",
+                "pie_fleet",
+                "walleye",
+            ],
+            args = [
+                "--platform=android",
+            ],
+            swarming = targets.swarming(
+                dimensions = {
+                    "cpu": "x86-64",
+                    "os": "Ubuntu-22.04",
+                },
+            ),
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromedriver_py_tests_isolated_scripts",
+    tests = {
+        "chromedriver_py_tests": targets.legacy_test_config(
+            args = [
+                "--test-type=integration",
+            ],
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "chromedriver_replay_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromeos_annotation_scripts",
+    tests = {
+        "check_network_annotations": targets.legacy_test_config(
+            script = "check_network_annotations.py",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromeos_browser_all_tast_tests",
+    tests = {
+        "chrome_all_tast_tests": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--tast-retries=1",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+                # Tast test doesn't always output. See crbug.com/1306300
+                io_timeout_sec = 3600,
+                idempotent = False,  # https://crbug.com/923426#c27
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromeos_browser_integration_tests",
+    tests = {
+        "disk_usage_tast_test": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # Stripping gives more accurate disk usage data.
+                "--strip-chrome",
+            ],
+            swarming = targets.swarming(
+                idempotent = False,  # https://crbug.com/923426#c27
+            ),
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromeos_chrome_all_tast_tests",
+    tests = {
+        "chrome_all_tast_tests": targets.legacy_test_config(
+            # `tast_expr` must be a non-empty string to run the tast tests. But the value of
+            # would be overridden by `tast_arrt_expr` defined in chromeos/BUILD.gn, so that we
+            # put the stub string here.
+            tast_expr = "STUB_STRING_TO_RUN_TAST_TESTS",
+            test_level_retries = 2,
+            timeout_sec = 21600,
+            shards = 10,
+        ),
+    },
+)
+
+# Test suite for running critical Tast tests.
+targets.legacy_basic_suite(
+    name = "chromeos_chrome_criticalstaging_tast_tests",
+    tests = {
+        "chrome_criticalstaging_tast_tests": targets.legacy_test_config(
+            # `tast_expr` must be a non-empty string to run the tast tests. But the value of
+            # would be overridden by `tast_arrt_expr` defined in chromeos/BUILD.gn, so that we
+            # put the stub string here.
+            tast_expr = "STUB_STRING_TO_RUN_TAST_TESTS",
+            test_level_retries = 2,
+            timeout_sec = 7200,
+            experiment_percentage = 100,
+            shards = 3,
+        ),
+    },
+)
+
+# Test suite for running disabled Tast tests to collect data to re-enable
+# them. The test suite should not be critical to builders.
+targets.legacy_basic_suite(
+    name = "chromeos_chrome_disabled_tast_tests",
+    tests = {
+        "chrome_disabled_tast_tests": targets.legacy_test_config(
+            # `tast_expr` must be a non-empty string to run the tast tests. But the value of
+            # would be overridden by `tast_arrt_expr` defined in chromeos/BUILD.gn, so that we
+            # put the stub string here.
+            tast_expr = "STUB_STRING_TO_RUN_TAST_TESTS",
+            test_level_retries = 1,
+            timeout_sec = 7200,
+            experiment_percentage = 100,
+            shards = 2,
+        ),
+    },
+)
+
+# GTests to run on Chrome OS devices, but not Chrome OS VMs. Any differences
+# between this and chromeos_system_friendly_gtests below should only be due
+# to resource constraints (ie: not enough devices).
+targets.legacy_basic_suite(
+    name = "chromeos_device_only_gtests",
+    tests = {
+        "base_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.base_unittests.filter",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromeos_integration_tests",
+    tests = {
+        "chromeos_integration_tests": targets.legacy_test_config(
+            ci_only = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromeos_isolated_scripts",
+    tests = {
+        "telemetry_perf_unittests": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--browser=cros-chrome",
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+                "--xvfb",
+                # 3 is arbitrary, but if we're having more than 3 of these tests
+                # fail in a single shard, then something is probably wrong, so fail
+                # fast.
+                "--typ-max-failures=3",
+            ],
+            swarming = targets.swarming(
+                shards = 12,
+                idempotent = False,  # https://crbug.com/549140
+            ),
+        ),
+        "telemetry_unittests": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--jobs=1",
+                "--browser=cros-chrome",
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+                # 3 is arbitrary, but if we're having more than 3 of these tests
+                # fail in a single shard, then something is probably wrong, so fail
+                # fast.
+                "--typ-max-failures=3",
+            ],
+            swarming = targets.swarming(
+                shards = 24,
+                idempotent = False,  # https://crbug.com/549140
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromeos_js_code_coverage_browser_tests",
+    tests = {
+        "chromeos_js_code_coverage_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            swarming = targets.swarming(
+                shards = 16,
+            ),
+        ),
+    },
+)
+
+# Tests that run on Chrome OS systems (ie: VMs, Chromebooks), *not*
+# linux-chromeos.
+# NOTE: We only want a small subset of test suites here, because most
+# suites assume that they stub out the underlying device hardware.
+# https://crbug.com/865693
+targets.legacy_basic_suite(
+    name = "chromeos_system_friendly_gtests",
+    tests = {
+        "aura_unittests": targets.legacy_test_config(
+            args = [
+                "--ozone-platform=headless",
+            ],
+        ),
+        "base_unittests": None,
+        "capture_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-jobs=1",
+                # Don't run CaptureMJpeg tests on ChromeOS VM because vivid,
+                # which is the virtual video capture device, doesn't support MJPEG.
+                "--gtest_filter=-*UsingRealWebcam_CaptureMjpeg*",
+            ],
+        ),
+        "cc_unittests": None,
+        "crypto_unittests": None,
+        "display_unittests": None,
+        "fake_libva_driver_unittest": targets.legacy_test_config(
+            args = [
+                "--env-var",
+                "LIBVA_DRIVERS_PATH",
+                "./",
+                "--env-var",
+                "LIBVA_DRIVER_NAME",
+                "libfake",
+            ],
+            experiment_percentage = 100,
+        ),
+        "google_apis_unittests": None,
+        "ipc_tests": None,
+        "latency_unittests": None,
+        "libcups_unittests": None,
+        "media_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.media_unittests.filter",
+            ],
+        ),
+        "midi_unittests": None,
+        "mojo_unittests": None,
+        # net_unittests has a test-time dependency on vpython. So add a CIPD'ed
+        # vpython of the right arch to the task, and tell the test runner to copy
+        # it over to the VM before the test runs.
+        "net_unittests": targets.legacy_test_config(
+            args = [
+                "--vpython-dir=../../vpython_dir_linux_amd64",
+                # PythonUtils.PythonRunTime (as opposed to Python3RunTime) requires a
+                # copy of Python 2, but it's testing test helpers that are only used
+                # outside of net_unittests. This bot runs out of space if trying to
+                # ship two vpythons, so we exclude Python 2 and the one test which
+                # uses it.
+                "--gtest_filter=-PythonUtils.PythonRunTime",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "infra/3pp/tools/cpython3/linux-amd64",
+                        location = "vpython_dir_linux_amd64",
+                        revision = "version:2@3.8.10.chromium.21",
+                    ),
+                    targets.cipd_package(
+                        package = "infra/tools/luci/vpython/linux-amd64",
+                        location = "vpython_dir_linux_amd64",
+                        revision = "git_revision:0f694cdc06ba054b9960aa1ae9766e45b53d02c1",
+                    ),
+                ],
+            ),
+        ),
+        "ozone_gl_unittests": targets.legacy_test_config(
+            args = [
+                "--stop-ui",
+            ],
+        ),
+        "ozone_unittests": None,
+        "pdf_unittests": None,
+        "printing_unittests": None,
+        "profile_provider_unittest": targets.legacy_test_config(
+            args = [
+                "--stop-ui",
+                "--test-launcher-jobs=1",
+            ],
+        ),
+        "rust_gtest_interop_unittests": None,
+        "sql_unittests": None,
+        "url_unittests": None,
+        "vaapi_unittest": targets.legacy_test_config(
+            args = [
+                "--stop-ui",
+                # Tell libva to do dummy encoding/decoding. For more info, see:
+                # https://github.com/intel/libva/blob/master/va/va_fool.c#L47
+                "--env-var",
+                "LIBVA_DRIVERS_PATH",
+                "./",
+                "--env-var",
+                "LIBVA_DRIVER_NAME",
+                "libfake",
+                "--gtest_filter=\"VaapiTest.*\"",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_android_scripts",
+    tests = {
+        "check_network_annotations": targets.legacy_test_config(
+            script = "check_network_annotations.py",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_android_webkit_gtests",
+    tests = {
+        "blink_heap_unittests": None,
+        "webkit_unit_tests": targets.legacy_test_config(
+            test = "blink_unittests",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_dev_android_gtests",
+    tests = {
+        "chrome_public_smoke_test": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_dev_desktop_gtests",
+    tests = {
+        "base_unittests": None,
+        "content_browsertests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 4,
+            ),
+        ),
+        "content_unittests": None,
+        "interactive_ui_tests": None,
+        "net_unittests": None,
+        "rust_gtest_interop_unittests": None,
+        "unit_tests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_dev_linux_gtests",
+    tests = {
+        "base_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "cores": "8",
+                },
+            ),
+        ),
+        "browser_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 8,
+                dimensions = {
+                    "cores": "8",
+                },
+            ),
+        ),
+        "content_browsertests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 5,
+                dimensions = {
+                    "cores": "8",
+                },
+            ),
+        ),
+        "content_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "cores": "2",
+                },
+            ),
+        ),
+        "interactive_ui_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+                dimensions = {
+                    "cores": "8",
+                },
+            ),
+        ),
+        "net_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "cores": "8",
+                },
+            ),
+        ),
+        "rust_gtest_interop_unittests": None,
+        "unit_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "cores": "2",
+                },
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_gtests",
+    tests = {
+        "absl_hardening_tests": None,
+        "angle_unittests": targets.legacy_test_config(
+            android_args = [
+                "-v",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "base_unittests": None,
+        "blink_common_unittests": None,
+        "blink_heap_unittests": None,
+        "blink_platform_unittests": None,
+        "boringssl_crypto_tests": None,
+        "boringssl_ssl_tests": None,
+        "capture_unittests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=-*UsingRealWebcam*",
+            ],
+        ),
+        "cast_unittests": None,
+        "components_browsertests": None,
+        "components_unittests": targets.legacy_test_config(
+            android_swarming = targets.swarming(
+                shards = 6,
+            ),
+        ),
+        "content_browsertests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 8,
+            ),
+            android_swarming = targets.swarming(
+                shards = 15,
+            ),
+        ),
+        "content_unittests": targets.legacy_test_config(
+            android_swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "crashpad_tests": None,
+        "crypto_unittests": None,
+        "env_chromium_unittests": targets.legacy_test_config(
+            ci_only = True,
+        ),
+        "events_unittests": None,
+        "gcm_unit_tests": None,
+        "gin_unittests": None,
+        "google_apis_unittests": None,
+        "gpu_unittests": None,
+        "gwp_asan_unittests": None,
+        "ipc_tests": None,
+        "latency_unittests": None,
+        "leveldb_unittests": targets.legacy_test_config(
+            ci_only = True,
+        ),
+        "libjingle_xmpp_unittests": None,
+        "liburlpattern_unittests": None,
+        "media_unittests": None,
+        "midi_unittests": None,
+        "mojo_unittests": None,
+        "net_unittests": targets.legacy_test_config(
+            android_swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "perfetto_unittests": None,
+        # TODO(crbug.com/1459686): Enable this.
+        # "rust_gtest_interop_unittests": None,
+        "services_unittests": None,
+        "shell_dialogs_unittests": None,
+        "skia_unittests": None,
+        "sql_unittests": None,
+        "storage_unittests": None,
+        "ui_base_unittests": None,
+        "ui_touch_selection_unittests": None,
+        "url_unittests": None,
+        "webkit_unit_tests": targets.legacy_test_config(
+            test = "blink_unittests",
+            android_swarming = targets.swarming(
+                shards = 6,
+            ),
+        ),
+        "wtf_unittests": None,
+        "zlib_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_gtests_for_devices_with_graphical_output",
+    tests = {
+        "cc_unittests": None,
+        "device_unittests": None,
+        "display_unittests": None,
+        "gfx_unittests": None,
+        "unit_tests": targets.legacy_test_config(
+            android_swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "viz_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_gtests_for_linux_and_chromeos_only",
+    tests = {
+        "dbus_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_gtests_for_linux_and_mac_only",
+    tests = {
+        "openscreen_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_gtests_for_linux_only",
+    tests = {
+        "ozone_unittests": None,
+        "ozone_x11_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_gtests_for_win_and_linux_only",
+    tests = {
+        # pthreadpool is only built on Windows and Linux platforms, that is
+        # determined by `build_tflite_with_xnnpack` defined in
+        # third_party/tflite/features.gni.
+        "pthreadpool_unittests": targets.legacy_test_config(
+            ci_only = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_ios_scripts",
+    tests = {
+        "check_static_initializers": targets.legacy_test_config(
+            script = "check_static_initializers.py",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_junit_tests_no_swarming",
+    tests = {
+        "android_webview_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "base_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "build_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "chrome_java_test_pagecontroller_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "chrome_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "components_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "content_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "device_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "junit_unit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "keyboard_accessory_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "media_base_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "module_installer_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "net_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "paint_preview_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "password_check_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "password_manager_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "services_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "touch_to_fill_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "ui_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "webapk_client_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "webapk_shell_apk_h2o_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+        "webapk_shell_apk_junit_tests": targets.legacy_test_config(
+            remove_mixins = [
+                "nougat-x86-emulator",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_junit_tests_scripts",
+    tests = {
+        "android_webview_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "base_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "build_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "chrome_java_test_pagecontroller_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "chrome_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "components_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "content_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "device_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "junit_unit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "keyboard_accessory_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "media_base_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "module_installer_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "net_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "paint_preview_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "password_check_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "password_manager_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "services_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "touch_to_fill_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "ui_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "webapk_client_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "webapk_shell_apk_h2o_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "webapk_shell_apk_junit_tests": targets.legacy_test_config(
+            mixins = [
+                "x86-64",
+                "linux-jammy",
+                "junit-swarming",
+            ],
+            remove_mixins = [
+                "emulator-4-cores",
+                "nougat-x86-emulator",
+                "oreo-x86-emulator",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_linux_scripts",
+    tests = {
+        "check_network_annotations": targets.legacy_test_config(
+            script = "check_network_annotations.py",
+        ),
+        "check_static_initializers": targets.legacy_test_config(
+            script = "check_static_initializers.py",
+        ),
+        "checkdeps": targets.legacy_test_config(
+            script = "checkdeps.py",
+        ),
+        "checkperms": targets.legacy_test_config(
+            script = "checkperms.py",
+        ),
+        "headless_python_unittests": targets.legacy_test_config(
+            script = "headless_python_unittests.py",
+        ),
+        "metrics_python_tests": targets.legacy_test_config(
+            script = "metrics_python_tests.py",
+        ),
+        "webkit_lint": targets.legacy_test_config(
+            script = "blink_lint_expectations.py",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_mac_scripts",
+    tests = {
+        "check_static_initializers": targets.legacy_test_config(
+            script = "check_static_initializers.py",
+        ),
+        "metrics_python_tests": targets.legacy_test_config(
+            script = "metrics_python_tests.py",
+        ),
+        "webkit_lint": targets.legacy_test_config(
+            script = "blink_lint_expectations.py",
+        ),
+    },
+)
+
+# On some bots we don't have capacity to run all standard tests (for example
+# Android Pie), however there are tracing integration tests we want to
+# ensure are still working.
+targets.legacy_basic_suite(
+    name = "chromium_tracing_gtests",
+    tests = {
+        "services_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_web_tests_high_dpi_isolated_scripts",
+    tests = {
+        # high_dpi_blink_web_tests provides coverage for
+        # running Layout Tests with forced device scale factor.
+        "high_dpi_blink_web_tests": targets.legacy_test_config(
+            test = "blink_web_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                "--flag-specific=highdpi",
+                "--skipped=always",
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 1,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        # high_dpi_blink_wpt_tests provides coverage for
+        # running Layout Tests with forced device scale factor.
+        "high_dpi_blink_wpt_tests": targets.legacy_test_config(
+            test = "blink_wpt_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                "--flag-specific=highdpi",
+                "--skipped=always",
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_webkit_isolated_scripts",
+    tests = {
+        "blink_web_tests": targets.legacy_test_config(
+            test = "blink_web_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 5,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        "blink_wpt_tests": targets.legacy_test_config(
+            test = "blink_wpt_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 7,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "chromium_win_scripts",
+    tests = {
+        "check_network_annotations": targets.legacy_test_config(
+            script = "check_network_annotations.py",
+        ),
+        "metrics_python_tests": targets.legacy_test_config(
+            script = "metrics_python_tests.py",
+        ),
+        "webkit_lint": targets.legacy_test_config(
+            script = "blink_lint_expectations.py",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "clang_tot_gtests",
+    tests = {
+        "base_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "client_v8_chromium_gtests",
+    tests = {
+        "app_shell_unittests": None,
+        "browser_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "chrome_app_unittests": None,
+        "chromedriver_unittests": None,
+        "components_browsertests": None,
+        "components_unittests": None,
+        "compositor_unittests": None,
+        "content_browsertests": None,
+        "content_unittests": None,
+        "device_unittests": None,
+        "extensions_browsertests": None,
+        "extensions_unittests": None,
+        "gcm_unit_tests": None,
+        "gin_unittests": None,
+        "google_apis_unittests": None,
+        "gpu_unittests": None,
+        "headless_browsertests": None,
+        "headless_unittests": None,
+        "interactive_ui_tests": None,
+        "nacl_loader_unittests": None,
+        "net_unittests": None,
+        "pdf_unittests": None,
+        "ppapi_unittests": None,
+        "remoting_unittests": None,
+        "services_unittests": None,
+        "sync_integration_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "unit_tests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "client_v8_chromium_isolated_scripts",
+    tests = {
+        "content_shell_crash_test": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+            ),
+        ),
+        "telemetry_gpu_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "telemetry_perf_unittests": targets.legacy_test_config(
+            args = [
+                "--xvfb",
+                # TODO(crbug.com/1077284): Remove this once Crashpad is the default.
+                "--extra-browser-args=--enable-crashpad",
+            ],
+            swarming = targets.swarming(
+                shards = 12,
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "telemetry_unittests": targets.legacy_test_config(
+            args = [
+                "--jobs=1",
+                # Disable GPU compositing, telemetry_unittests runs on VMs.
+                # https://crbug.com/871955
+                "--extra-browser-args=--disable-gpu",
+            ],
+            swarming = targets.swarming(
+                shards = 4,
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "components_perftests_isolated_scripts",
+    tests = {
+        "components_perftests": targets.legacy_test_config(
+            args = [
+                "--gtest-benchmark-name=components_perftests",
+            ],
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+                args = [
+                    "--smoke-test-mode",
+                ],
+            ),
+        ),
+    },
+)
+
+# TODO(crbug.com/1444855): Delete the cr23_{linux,mac,win}_gtest suites
+# after the ChromeRefresh2023 is fully rolled out.
+targets.legacy_basic_suite(
+    name = "cr23_linux_gtests",
+    tests = {
+        "cr23_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+        "cr23_interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "cr23_views_unittests": targets.legacy_test_config(
+            test = "views_unittests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            ci_only = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cr23_mac_gtests",
+    tests = {
+        "cr23_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+        "cr23_interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "cr23_views_unittests": targets.legacy_test_config(
+            test = "views_unittests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            ci_only = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cr23_pixel_browser_tests_gtests",
+    tests = {
+        "cr23_pixel_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            mixins = [
+                "skia_gold_test",
+                "chrome-refresh-2023",
+            ],
+            args = [
+                "--browser-ui-tests-verify-pixels",
+                "--enable-pixel-output-in-tests",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter",
+                "--test-launcher-jobs=1",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "cr23_pixel_interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            mixins = [
+                "skia_gold_test",
+                "chrome-refresh-2023",
+            ],
+            args = [
+                "--browser-ui-tests-verify-pixels",
+                "--enable-pixel-output-in-tests",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cr23_win_gtests",
+    tests = {
+        "cr23_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+        "cr23_interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "cr23_views_unittests": targets.legacy_test_config(
+            test = "views_unittests",
+            mixins = [
+                "chrome-refresh-2023",
+            ],
+            ci_only = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cronet_gtests",
+    tests = {
+        "cronet_sample_test_apk": None,
+        "cronet_smoketests_missing_native_library_instrumentation_apk": None,
+        "cronet_smoketests_platform_only_instrumentation_apk": None,
+        "cronet_test_instrumentation_apk": None,
+        "cronet_tests_android": None,
+        "cronet_unittests_android": None,
+        "net_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 4,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cronet_resource_sizes",
+    tests = {
+        "resource_sizes_cronet_sample_apk": targets.legacy_test_config(
+            swarming = targets.swarming(
+                # This suite simply analyzes build targets without running them.
+                # It can thus run on a standard linux machine w/o a device.
+                dimensions = {
+                    "os": "Ubuntu-22.04",
+                    "cpu": "x86-64",
+                },
+            ),
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "cronet_sizes",
+    tests = {
+        "cronet_sizes": targets.legacy_test_config(
+            remove_mixins = [
+                "android_r",
+                "bullhead",
+                "flame",
+                "marshmallow",
+                "mdarcy",
+                "oreo_fleet",
+                "oreo_mr1_fleet",
+                "pie_fleet",
+                "walleye",
+            ],
+            swarming = targets.swarming(
+                # This suite simply analyzes build targets without running them.
+                # It can thus run on a standard linux machine w/o a device.
+                dimensions = {
+                    "os": "Ubuntu-22.04",
+                    "cpu": "x86-64",
+                },
+            ),
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+                result_file = "${ISOLATED_OUTDIR}/sizes/test_results.json",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "desktop_chromium_isolated_scripts",
+    tests = {
+        "blink_python_tests": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "blink_web_tests": targets.legacy_test_config(
+            test = "blink_web_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 5,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        "blink_wpt_tests": targets.legacy_test_config(
+            test = "blink_wpt_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 7,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        "content_shell_crash_test": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+            ),
+        ),
+        "flatbuffers_unittests": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+            ),
+        ),
+        "grit_python_unittests": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "telemetry_gpu_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "telemetry_unittests": targets.legacy_test_config(
+            args = [
+                "--jobs=1",
+                # Disable GPU compositing, telemetry_unittests runs on VMs.
+                # https://crbug.com/871955
+                "--extra-browser-args=--disable-gpu",
+            ],
+            swarming = targets.swarming(
+                shards = 8,
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "views_perftests": targets.legacy_test_config(
+            args = [
+                "--gtest-benchmark-name=views_perftests",
+            ],
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+                args = [
+                    "--smoke-test-mode",
+                ],
+            ),
+        ),
+    },
+)
+
+# Script tests that only need to run on one builder per desktop platform.
+targets.legacy_basic_suite(
+    name = "desktop_once_isolated_scripts",
+    tests = {
+        "test_env_py_unittests": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "xvfb_py_unittests": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "devtools_browser_tests",
+    tests = {
+        "devtools_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--gtest_filter=*DevTools*",
+            ],
+            swarming = targets.swarming(
+                shards = 1,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "devtools_webkit_and_tab_target_isolated_scripts",
+    tests = {
+        "blink_web_tests": targets.legacy_test_config(
+            test = "blink_web_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 5,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        "blink_web_tests_dt_tab_target": targets.legacy_test_config(
+            test = "blink_web_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                "--flag-specific=devtools-tab-target",
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+                "http/tests/devtools",
+            ],
+            swarming = targets.swarming(
+                shards = 5,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        "blink_wpt_tests": targets.legacy_test_config(
+            test = "blink_wpt_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 7,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "devtools_webkit_isolated_scripts",
+    tests = {
+        "blink_web_tests": targets.legacy_test_config(
+            test = "blink_web_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 5,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        "blink_wpt_tests": targets.legacy_test_config(
+            test = "blink_wpt_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 7,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "fieldtrial_android_tests",
+    tests = {
+        "android_browsertests_no_fieldtrial": targets.legacy_test_config(
+            test = "android_browsertests",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "fieldtrial_browser_tests",
+    tests = {
+        "browser_tests_no_field_trial": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "components_browsertests_no_field_trial": targets.legacy_test_config(
+            test = "components_browsertests",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            ci_only = True,
+        ),
+        "interactive_ui_tests_no_field_trial": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            ci_only = True,
+        ),
+        "sync_integration_tests_no_field_trial": targets.legacy_test_config(
+            test = "sync_integration_tests",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            ci_only = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "finch_smoke_tests",
+    tests = {
+        # TODO(crbug.com/1227222): Change this to the actual finch smoke test
+        # once it exists.
+        "base_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "fuchsia_accessibility_content_browsertests",
+    tests = {
+        "accessibility_content_browsertests": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--gtest_filter=*All/DumpAccessibility*/fuchsia*",
+                "--test-arg=--disable-gpu",
+                "--test-arg=--headless",
+                "--test-arg=--ozone-platform=headless",
+            ],
+            swarming = targets.swarming(
+                shards = 8,  # this may depend on runtime of a11y CQ
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "fuchsia_chrome_small_gtests",
+    tests = {
+        "courgette_unittests": None,
+        "extensions_unittests": None,
+        "headless_unittests": None,
+        "message_center_unittests": None,
+        "views_examples_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_examples_unittests.filter",
+            ],
+        ),
+        "views_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_unittests.filter",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "fuchsia_common_gtests",
+    tests = {
+        "absl_hardening_tests": None,
+        "accessibility_unittests": None,
+        "aura_unittests": None,
+        "base_unittests": None,
+        "blink_common_unittests": None,
+        "blink_fuzzer_unittests": None,
+        "blink_heap_unittests": None,
+        "blink_platform_unittests": None,
+        "blink_unittests": None,
+        "boringssl_crypto_tests": None,
+        "boringssl_ssl_tests": None,
+        "capture_unittests": None,
+        "components_browsertests": targets.legacy_test_config(
+            args = [
+                "--test-arg=--disable-gpu",
+                "--test-arg=--headless",
+                "--test-arg=--ozone-platform=headless",
+            ],
+        ),
+        "components_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "compositor_unittests": None,
+        "content_browsertests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=-All/DumpAccessibility*/fuchsia",
+                "--test-arg=--disable-gpu",
+                "--test-arg=--headless",
+                "--test-arg=--ozone-platform=headless",
+            ],
+            swarming = targets.swarming(
+                shards = 14,
+            ),
+        ),
+        "content_unittests": None,
+        "crypto_unittests": None,
+        "events_unittests": None,
+        "filesystem_service_unittests": None,
+        "gcm_unit_tests": None,
+        "gin_unittests": None,
+        "google_apis_unittests": None,
+        "gpu_unittests": None,
+        "gwp_asan_unittests": None,
+        "headless_browsertests": None,
+        "ipc_tests": None,
+        "latency_unittests": None,
+        "media_unittests": None,
+        "midi_unittests": None,
+        "mojo_unittests": None,
+        "native_theme_unittests": None,
+        "net_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 4,
+            ),
+        ),
+        "ozone_gl_unittests": targets.legacy_test_config(
+            args = [
+                "--test-arg=--ozone-platform=headless",
+            ],
+        ),
+        "ozone_unittests": None,
+        "perfetto_unittests": None,
+        # TODO(crbug.com/1459686): Enable this.
+        # "rust_gtest_interop_unittests": None,
+        "service_manager_unittests": None,
+        "services_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.services_unittests.filter",
+            ],
+        ),
+        "shell_dialogs_unittests": None,
+        "skia_unittests": None,
+        "snapshot_unittests": None,
+        "sql_unittests": None,
+        "storage_unittests": None,
+        "ui_base_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter",
+            ],
+        ),
+        "ui_touch_selection_unittests": None,
+        "ui_unittests": None,
+        "url_unittests": None,
+        "wm_unittests": None,
+        "wtf_unittests": None,
+        "zlib_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "fuchsia_common_gtests_with_graphical_output",
+    tests = {
+        "cc_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "display_unittests": None,
+        "gfx_unittests": None,
+        "viz_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.viz_unittests.filter",
+            ],
+        ),
+    },
+)
+
+# This is a set of selected tests to test the test facility only. The
+# principle of the selection includes time cost, scenario coverage,
+# stability, etc; and it's subject to change. In theory, it should only be
+# used by the EngProd team to verify a new test facility setup.
+targets.legacy_basic_suite(
+    name = "fuchsia_facility_gtests",
+    tests = {
+        "aura_unittests": None,
+        "blink_common_unittests": None,
+        "courgette_unittests": None,
+        "crypto_unittests": None,
+        "filesystem_service_unittests": None,
+        "web_engine_integration_tests": targets.legacy_test_config(
+            args = [
+                "--test-arg=--vmodule=test_navigation_listener=1",
+            ],
+        ),
+        "web_engine_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "fuchsia_sizes_tests",
+    tests = {
+        "fuchsia_sizes": targets.legacy_test_config(
+            args = [
+                "--sizes-path",
+                "tools/fuchsia/size_tests/fyi_sizes_smoketest.json",
+            ],
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gl_gtests_passthrough",
+    tests = {
+        "gl_tests_passthrough": targets.legacy_test_config(
+            test = "gl_tests",
+            args = [
+                "--use-cmd-decoder=passthrough",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "gl_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "goma_gtests",
+    tests = {
+        "base_unittests": None,
+        "content_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "goma_mac_gtests",
+    tests = {
+        "base_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "cpu": "x86-64",
+                    "os": "Mac-13",
+                },
+            ),
+        ),
+        "content_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "cpu": "x86-64",
+                    "os": "Mac-13",
+                },
+            ),
+        ),
+    },
+)
+
+# BEGIN tests which run on the GPU bots
+
+targets.legacy_basic_suite(
+    name = "gpu_angle_fuchsia_unittests_isolated_scripts",
+    tests = {
+        "angle_unittests": targets.legacy_test_config(
+            mixins = [
+                "fuchsia_logs",
+            ],
+            args = [
+                "bin/run_angle_unittests",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_angle_ios_end2end_gtests",
+    tests = {
+        "angle_end2end_tests": targets.legacy_test_config(
+            args = [
+                "--release",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_angle_ios_white_box_gtests",
+    tests = {
+        "angle_white_box_tests": targets.legacy_test_config(
+            args = [
+                "--release",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_angle_unit_gtests",
+    tests = {
+        "angle_unittests": targets.legacy_test_config(
+            android_args = [
+                "-v",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+    },
+)
+
+# The command buffer perf tests are only run on Windows.
+# They are mostly driver and platform independent.
+targets.legacy_basic_suite(
+    name = "gpu_command_buffer_perf_passthrough_isolated_scripts",
+    tests = {
+        "passthrough_command_buffer_perftests": targets.legacy_test_config(
+            test = "command_buffer_perftests",
+            args = [
+                "--gtest-benchmark-name=passthrough_command_buffer_perftests",
+                "-v",
+                "--use-cmd-decoder=passthrough",
+                "--use-angle=gl-null",
+                "--fast-run",
+            ],
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+                args = [
+                    "--smoke-test-mode",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_common_and_optional_telemetry_tests",
+    tests = {
+        "info_collection_tests": targets.legacy_test_config(
+            telemetry_test_name = "info_collection",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--expected-vendor-id",
+                "${gpu_vendor_id}",
+                "$$MAGIC_SUBSTITUTION_GPUExpectedDeviceId",
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--force_high_performance_gpu",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "trace_test": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+    },
+)
+
+# GPU gtests which run on both the main and FYI waterfalls.
+targets.legacy_basic_suite(
+    name = "gpu_common_gtests_passthrough",
+    tests = {
+        "gl_tests_passthrough": targets.legacy_test_config(
+            test = "gl_tests",
+            args = [
+                "--use-cmd-decoder=passthrough",
+                "--use-gl=angle",
+            ],
+            chromeos_args = [
+                "--stop-ui",
+            ],
+            desktop_args = [
+                "--use-gpu-in-tests",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "gl_unittests": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            chromeos_args = [
+                "--stop-ui",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.gl_unittests.filter",
+            ],
+            desktop_args = [
+                "--use-gpu-in-tests",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_common_gtests_validating",
+    tests = {
+        "gl_tests_validating": targets.legacy_test_config(
+            test = "gl_tests",
+            args = [
+                "--use-cmd-decoder=validating",
+            ],
+            chromeos_args = [
+                "--stop-ui",
+                "$$MAGIC_SUBSTITUTION_ChromeOSGtestFilterFile",
+            ],
+            desktop_args = [
+                "--use-gpu-in-tests",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+        "gl_unittests": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+            chromeos_args = [
+                "--stop-ui",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.gl_unittests.filter",
+            ],
+            desktop_args = [
+                "--use-gpu-in-tests",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_common_isolated_scripts",
+    tests = {
+        # Test that expectations files are well-formed.
+        "telemetry_gpu_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+# GPU gtests that test only Dawn
+targets.legacy_basic_suite(
+    name = "gpu_dawn_gtests",
+    tests = {
+        "dawn_end2end_implicit_device_sync_tests": targets.legacy_test_config(
+            test = "dawn_end2end_tests",
+            mixins = [
+                "dawn_end2end_gpu_test",
+            ],
+            args = [
+                "--enable-implicit-device-sync",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+            ci_only = True,  # https://crbug.com/dawn/1749
+        ),
+        "dawn_end2end_skip_validation_tests": targets.legacy_test_config(
+            test = "dawn_end2end_tests",
+            mixins = [
+                "dawn_end2end_gpu_test",
+            ],
+            args = [
+                "--enable-toggles=skip_validation",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+        "dawn_end2end_tests": targets.legacy_test_config(
+            mixins = [
+                "dawn_end2end_gpu_test",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+        "dawn_end2end_wire_tests": targets.legacy_test_config(
+            test = "dawn_end2end_tests",
+            mixins = [
+                "dawn_end2end_gpu_test",
+            ],
+            args = [
+                "--use-wire",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_gtests_no_dxc",
+    tests = {
+        "dawn_end2end_no_dxc_tests": targets.legacy_test_config(
+            test = "dawn_end2end_tests",
+            mixins = [
+                "dawn_end2end_gpu_test",
+            ],
+            args = [
+                "--disable-toggles=use_dxc",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_gtests_no_dxc_with_validation",
+    tests = {
+        "dawn_end2end_no_dxc_validation_layers_tests": targets.legacy_test_config(
+            test = "dawn_end2end_tests",
+            mixins = [
+                "dawn_end2end_gpu_test",
+            ],
+            args = [
+                "--disable-toggles=use_dxc",
+                "--enable-backend-validation",
+            ],
+        ),
+    },
+)
+
+# GPU gtests that test only Dawn with backend validation layers
+targets.legacy_basic_suite(
+    name = "gpu_dawn_gtests_with_validation",
+    tests = {
+        "dawn_end2end_validation_layers_tests": targets.legacy_test_config(
+            test = "dawn_end2end_tests",
+            mixins = [
+                "dawn_end2end_gpu_test",
+            ],
+            args = [
+                "--enable-backend-validation",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_perf_smoke_isolated_scripts",
+    tests = {
+        "dawn_perf_tests": targets.legacy_test_config(
+            args = [
+                # Tell the tests to only run one step for faster iteration.
+                "--override-steps=1",
+                "--gtest-benchmark-name=dawn_perf_tests",
+                "-v",
+            ],
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+                args = [
+                    # Does not upload to the perf dashboard
+                    "--smoke-test-mode",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_web_platform_webgpu_cts_force_swiftshader",
+    tests = {
+        "webgpu_swiftshader_web_platform_cts_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgpu_cts",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_telemetry_cts",
+            ],
+            args = [
+                "--use-webgpu-adapter=swiftshader",
+                "--test-filter=*web_platform*",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "webgpu_swiftshader_web_platform_cts_with_validation_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgpu_cts",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_telemetry_cts",
+            ],
+            args = [
+                "--use-webgpu-adapter=swiftshader",
+                "--test-filter=*web_platform*",
+                "--enable-dawn-backend-validation",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_webgpu_blink_web_tests",
+    tests = {
+        "webgpu_blink_web_tests": targets.legacy_test_config(
+            test = "webgpu_blink_web_tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_cts",
+            ],
+            args = [
+                "--flag-specific=webgpu",
+            ],
+        ),
+        "webgpu_blink_web_tests_with_backend_validation": targets.legacy_test_config(
+            test = "webgpu_blink_web_tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_cts",
+            ],
+            args = [
+                "--flag-specific=webgpu-with-backend-validation",
+                # Increase the timeout when using backend validation layers (crbug.com/1208253)
+                "--timeout-ms=30000",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_webgpu_blink_web_tests_force_swiftshader",
+    tests = {
+        "webgpu_swiftshader_blink_web_tests": targets.legacy_test_config(
+            test = "webgpu_blink_web_tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_cts",
+            ],
+            args = [
+                "--flag-specific=webgpu-swiftshader",
+            ],
+        ),
+        "webgpu_swiftshader_blink_web_tests_with_backend_validation": targets.legacy_test_config(
+            test = "webgpu_blink_web_tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_cts",
+            ],
+            args = [
+                "--flag-specific=webgpu-swiftshader-with-backend-validation",
+                # Increase the timeout when using backend validation layers (crbug.com/1208253)
+                "--timeout-ms=30000",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_webgpu_cts",
+    tests = {
+        "webgpu_cts_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgpu_cts",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_telemetry_cts",
+            ],
+            swarming = targets.swarming(
+                shards = 14,
+            ),
+            android_swarming = targets.swarming(
+                shards = 36,
+            ),
+        ),
+        "webgpu_cts_with_validation_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgpu_cts",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_telemetry_cts",
+            ],
+            args = [
+                "--enable-dawn-backend-validation",
+            ],
+            swarming = targets.swarming(
+                shards = 14,
+            ),
+            android_swarming = targets.swarming(
+                shards = 36,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_webgpu_cts_asan",
+    tests = {
+        "webgpu_cts_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgpu_cts",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_telemetry_cts",
+            ],
+            swarming = targets.swarming(
+                shards = 8,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_dawn_webgpu_cts_dxc",
+    tests = {
+        "webgpu_cts_dxc_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgpu_cts",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_telemetry_cts",
+            ],
+            args = [
+                "--use-dxc",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 14,
+            ),
+        ),
+        "webgpu_cts_dxc_with_validation_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgpu_cts",
+            mixins = [
+                "has_native_resultdb_integration",
+                "webgpu_telemetry_cts",
+            ],
+            args = [
+                "--enable-dawn-backend-validation",
+                "--use-dxc",
+            ],
+            ci_only = True,
+            swarming = targets.swarming(
+                shards = 14,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_default_and_optional_win_media_foundation_specific_gtests",
+    tests = {
+        # MediaFoundation browser tests, which currently only run on Windows OS,
+        # and require physical hardware.
+        "media_foundation_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--gtest_filter=MediaFoundationEncryptedMediaTest*",
+                "--use-gpu-in-tests",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_default_and_optional_win_specific_gtests",
+    tests = {
+        "xr_browser_tests": targets.legacy_test_config(
+            test = "xr_browser_tests",
+            args = [
+                # The Windows machines this is run on should always meet all the
+                # requirements, so skip the runtime checks to help catch issues, e.g.
+                # if we're incorrectly being told a DirectX 11.1 device isn't
+                # available
+                "--ignore-runtime-requirements=*",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_desktop_specific_gtests",
+    tests = {
+        "tab_capture_end2end_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--enable-gpu",
+                "--test-launcher-bot-mode",
+                "--test-launcher-jobs=1",
+                "--gtest_filter=TabCaptureApiPixelTest.EndToEnd*",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_fyi_and_optional_non_linux_gtests",
+    tests = {
+        # gpu_unittests is killing the Swarmed Linux GPU bots similarly to
+        # how content_unittests was: http://crbug.com/763498 .
+        "gpu_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_fyi_and_optional_win_specific_gtests",
+    tests = {
+        "gles2_conform_d3d9_test": targets.legacy_test_config(
+            test = "gles2_conform_test",
+            args = [
+                "--use-gpu-in-tests",
+                "--use-angle=d3d9",
+            ],
+        ),
+        "gles2_conform_gl_test": targets.legacy_test_config(
+            test = "gles2_conform_test",
+            args = [
+                "--use-gpu-in-tests",
+                "--use-angle=gl",
+                "--disable-gpu-sandbox",
+            ],
+        ),
+        # WebNN DirectML backend unit tests, which currently only run on
+        # Windows OS, and require physical hardware.
+        "services_webnn_unittests": targets.legacy_test_config(
+            test = "services_unittests",
+            args = [
+                "--gtest_filter=WebNN*",
+                "--use-gpu-in-tests",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_fyi_mac_specific_gtests",
+    tests = {
+        # Face and barcode detection unit tests, which currently only run on
+        # Mac OS, and require physical hardware.
+        "services_unittests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=*Detection*",
+                "--use-gpu-in-tests",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_fyi_vulkan_swiftshader_gtests",
+    tests = {
+        "vulkan_swiftshader_content_browsertests": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--enable-gpu",
+                "--test-launcher-bot-mode",
+                "--test-launcher-jobs=1",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter",
+                "--enable-features=UiGpuRasterization,Vulkan",
+                "--use-vulkan=swiftshader",
+                "--enable-gpu-rasterization",
+                "--disable-software-compositing-fallback",
+                "--disable-vulkan-fallback-to-gl-for-testing",
+                "--disable-headless-mode",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_gl_passthrough_ganesh_telemetry_tests",
+    tests = {
+        "context_lost_gl_passthrough_ganesh_tests": targets.legacy_test_config(
+            telemetry_test_name = "context_lost",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+        ),
+        "expected_color_pixel_gl_passthrough_ganesh_test": targets.legacy_test_config(
+            telemetry_test_name = "expected_color",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite",
+            ],
+        ),
+        "gpu_process_launch_tests": targets.legacy_test_config(
+            telemetry_test_name = "gpu_process",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "hardware_accelerated_feature_tests": targets.legacy_test_config(
+            telemetry_test_name = "hardware_accelerated_feature",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "pixel_skia_gold_gl_passthrough_ganesh_test": targets.legacy_test_config(
+            telemetry_test_name = "pixel",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+        ),
+        "screenshot_sync_gl_passthrough_ganesh_tests": targets.legacy_test_config(
+            telemetry_test_name = "screenshot_sync",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_gles2_conform_gtests",
+    tests = {
+        # The gles2_conform_tests are closed-source and deliberately only
+        # run on the FYI waterfall and the optional tryservers.
+        "gles2_conform_test": targets.legacy_test_config(
+            args = [
+                "--use-gpu-in-tests",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_info_collection_telemetry_tests",
+    tests = {
+        "info_collection_tests": targets.legacy_test_config(
+            telemetry_test_name = "info_collection",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--expected-vendor-id",
+                "${gpu_vendor_id}",
+                "$$MAGIC_SUBSTITUTION_GPUExpectedDeviceId",
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--force_high_performance_gpu",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_mediapipe_passthrough_telemetry_tests",
+    tests = {
+        "mediapipe_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "mediapipe",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--force_higher_performance_gpu --use-cmd-decoder=passthrough --use-gl=angle",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_mediapipe_validating_telemetry_tests",
+    tests = {
+        "mediapipe_validating_tests": targets.legacy_test_config(
+            telemetry_test_name = "mediapipe",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--force_higher_performance_gpu --use-cmd-decoder=validating",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_metal_passthrough_ganesh_telemetry_tests",
+    tests = {
+        "context_lost_metal_passthrough_ganesh_tests": targets.legacy_test_config(
+            telemetry_test_name = "context_lost",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+        ),
+        "expected_color_pixel_metal_passthrough_ganesh_test": targets.legacy_test_config(
+            telemetry_test_name = "expected_color",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite",
+            ],
+        ),
+        "gpu_process_launch_tests": targets.legacy_test_config(
+            telemetry_test_name = "gpu_process",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "hardware_accelerated_feature_tests": targets.legacy_test_config(
+            telemetry_test_name = "hardware_accelerated_feature",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "pixel_skia_gold_metal_passthrough_ganesh_test": targets.legacy_test_config(
+            telemetry_test_name = "pixel",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+        ),
+        "screenshot_sync_metal_passthrough_ganesh_tests": targets.legacy_test_config(
+            telemetry_test_name = "screenshot_sync",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_metal_passthrough_graphite_telemetry_tests",
+    tests = {
+        "context_lost_metal_passthrough_graphite_tests": targets.legacy_test_config(
+            telemetry_test_name = "context_lost",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+        ),
+        "expected_color_pixel_metal_passthrough_graphite_test": targets.legacy_test_config(
+            telemetry_test_name = "expected_color",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite",
+            ],
+        ),
+        "gpu_process_launch_tests": targets.legacy_test_config(
+            telemetry_test_name = "gpu_process",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "hardware_accelerated_feature_tests": targets.legacy_test_config(
+            telemetry_test_name = "hardware_accelerated_feature",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "pixel_skia_gold_metal_passthrough_graphite_test": targets.legacy_test_config(
+            telemetry_test_name = "pixel",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+        ),
+        "screenshot_sync_metal_passthrough_graphite_tests": targets.legacy_test_config(
+            telemetry_test_name = "screenshot_sync",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_noop_sleep_telemetry_test",
+    tests = {
+        # The former GPU-specific generator script contained logic to
+        # detect whether the so-called "experimental" GPU bots, which test
+        # newer driver versions, were identical to the "stable" versions
+        # of the bots, and if so to mirror their configurations. We prefer
+        # to keep this new script simpler and to just configure this by
+        # hand in waterfalls.pyl.
+        "noop_sleep_tests": targets.legacy_test_config(
+            telemetry_test_name = "noop_sleep",
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_passthrough_telemetry_tests",
+    tests = {
+        "context_lost_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "context_lost",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                # TODO(crbug.com/1093085): Remove this once we fix the tests.
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "expected_color_pixel_passthrough_test": targets.legacy_test_config(
+            telemetry_test_name = "expected_color",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle",
+            ],
+            android_args = [
+                "--extra-browser-args=--force-online-connection-state-for-indicator",
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "gpu_process_launch_tests": targets.legacy_test_config(
+            telemetry_test_name = "gpu_process",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "hardware_accelerated_feature_tests": targets.legacy_test_config(
+            telemetry_test_name = "hardware_accelerated_feature",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "pixel_skia_gold_passthrough_test": targets.legacy_test_config(
+            telemetry_test_name = "pixel",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                # TODO(crbug.com/1093085): Remove this once we fix the tests.
+                "--extra-browser-args=--force-online-connection-state-for-indicator",
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "screenshot_sync_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "screenshot_sync",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle",
+            ],
+            android_args = [
+                # TODO(crbug.com/1093085): Remove this once we fix the tests.
+                "--extra-browser-args=--force-online-connection-state-for-indicator",
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_pixel_passthrough_telemetry_tests",
+    tests = {
+        "expected_color_pixel_passthrough_test": targets.legacy_test_config(
+            telemetry_test_name = "expected_color",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+        ),
+        "pixel_skia_gold_passthrough_test": targets.legacy_test_config(
+            telemetry_test_name = "pixel",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_skia_renderer_vulkan_passthrough_telemetry_tests",
+    tests = {
+        "vulkan_pixel_skia_gold_test": targets.legacy_test_config(
+            telemetry_test_name = "pixel",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-vulkan=native --disable-vulkan-fallback-to-gl-for-testing --enable-features=Vulkan --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                # TODO(crbug.com/1093085): Remove this once we fix the tests.
+                "--extra-browser-args=--force-online-connection-state-for-indicator",
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_validating_telemetry_tests",
+    tests = {
+        "context_lost_validating_tests": targets.legacy_test_config(
+            telemetry_test_name = "context_lost",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--use-cmd-decoder=validating",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "expected_color_pixel_validating_test": targets.legacy_test_config(
+            telemetry_test_name = "expected_color",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=validating",
+            ],
+            android_args = [
+                # TODO(crbug.com/1093085): Remove this once we fix the tests.
+                "--extra-browser-args=--force-online-connection-state-for-indicator",
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "gpu_process_launch_tests": targets.legacy_test_config(
+            telemetry_test_name = "gpu_process",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "hardware_accelerated_feature_tests": targets.legacy_test_config(
+            telemetry_test_name = "hardware_accelerated_feature",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "pixel_skia_gold_validating_test": targets.legacy_test_config(
+            telemetry_test_name = "pixel",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--test-machine-name",
+                "${buildername}",
+                "--extra-browser-args=--use-cmd-decoder=validating",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                # TODO(crbug.com/1093085): Remove this once we fix the tests.
+                "--extra-browser-args=--force-online-connection-state-for-indicator",
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+        "screenshot_sync_validating_tests": targets.legacy_test_config(
+            telemetry_test_name = "screenshot_sync",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--dont-restore-color-profile-after-test",
+                "--extra-browser-args=--use-cmd-decoder=validating",
+            ],
+            android_args = [
+                # TODO(crbug.com/1093085): Remove this once we fix the tests.
+                "--extra-browser-args=--force-online-connection-state-for-indicator",
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_vulkan_gtests",
+    tests = {
+        "vulkan_tests": targets.legacy_test_config(
+            desktop_args = [
+                "--use-gpu-in-tests",
+            ],
+            linux_args = [
+                "--no-xvfb",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webcodecs_telemetry_test",
+    tests = {
+        "webcodecs_tests": targets.legacy_test_config(
+            telemetry_test_name = "webcodecs",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            # TODO(https://crbug.com/1359405): having --xvfb and --no-xvfb is confusing.
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webcodecs_validating_telemetry_test",
+    tests = {
+        "webcodecs_tests": targets.legacy_test_config(
+            telemetry_test_name = "webcodecs",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--use-cmd-decoder=validating",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            # TODO(https://crbug.com/1359405): having --xvfb and --no-xvfb is confusing.
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests",
+    tests = {
+        "webgl2_conformance_d3d11_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl2_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--webgl-conformance-version=2.0.1",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            swarming = targets.swarming(
+                # These tests currently take about an hour and fifteen minutes
+                # to run. Split them into roughly 5-minute shards.
+                shards = 20,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl2_conformance_gl_passthrough_telemetry_tests",
+    tests = {
+        "webgl2_conformance_gl_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl2_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--webgl-conformance-version=2.0.1",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+            swarming = targets.swarming(
+                # These tests currently take about an hour and fifteen minutes
+                # to run. Split them into roughly 5-minute shards.
+                shards = 20,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl2_conformance_gles_passthrough_telemetry_tests",
+    tests = {
+        "webgl2_conformance_gles_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl2_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--webgl-conformance-version=2.0.1",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            swarming = targets.swarming(
+                # These tests currently take about an hour and fifteen minutes
+                # to run. Split them into roughly 5-minute shards.
+                shards = 20,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl2_conformance_metal_passthrough_telemetry_tests",
+    tests = {
+        "webgl2_conformance_metal_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl2_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--webgl-conformance-version=2.0.1",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+                "--enable-metal-debug-layers",
+            ],
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl2_conformance_validating_telemetry_tests",
+    tests = {
+        "webgl2_conformance_validating_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl2_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--webgl-conformance-version=2.0.1",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+            swarming = targets.swarming(
+                # These tests currently take about an hour and fifteen minutes
+                # to run. Split them into roughly 5-minute shards.
+                shards = 20,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_d3d11_passthrough_telemetry_tests",
+    tests = {
+        "webgl_conformance_d3d11_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_d3d9_passthrough_telemetry_tests",
+    tests = {
+        "webgl_conformance_d3d9_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=d3d9 --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+    tests = {
+        "webgl_conformance_gl_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_gles_passthrough_telemetry_tests",
+    tests = {
+        "webgl_conformance_gles_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+            swarming = targets.swarming(
+                shards = 6,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_metal_passthrough_telemetry_tests",
+    tests = {
+        "webgl_conformance_metal_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+                "--enable-metal-debug-layers",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests",
+    tests = {
+        "webgl_conformance_swangle_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                # We are only interested in running a 'smoketest' to test swangle
+                # integration, not the full conformance suite.
+                "--test-filter=conformance/rendering/gl-drawelements.html",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            swarming = targets.swarming(
+                shards = 1,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_swangle_passthrough_telemetry_tests",
+    tests = {
+        "webgl_conformance_swangle_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough",
+                "--xvfb",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            swarming = targets.swarming(
+                shards = 1,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_telemetry_tests",
+    tests = {
+        "webgl_conformance_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+            android_swarming = targets.swarming(
+                shards = 12,
+            ),
+            chromeos_swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_validating_telemetry_tests",
+    tests = {
+        "webgl_conformance_validating_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            android_args = [
+                "$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices",
+            ],
+            chromeos_args = [
+                "$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote",
+            ],
+            lacros_args = [
+                "--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland",
+                "--xvfb",
+                "--no-xvfb",
+                "--use-weston",
+                "--weston-use-gl",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+            android_swarming = targets.swarming(
+                shards = 6,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "gpu_webgl_conformance_vulkan_passthrough_telemetry_tests",
+    tests = {
+        "webgl_conformance_vulkan_passthrough_tests": targets.legacy_test_config(
+            telemetry_test_name = "webgl1_conformance",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                # On dual-GPU devices we want the high-performance GPU to be active
+                "--extra-browser-args=--use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu",
+                "$$MAGIC_SUBSTITUTION_GPUParallelJobs",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "headless_browser_gtests",
+    tests = {
+        "headless_browsertests": None,
+        "headless_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ios_blink_tests",
+    tests = {
+        "absl_hardening_tests": None,
+        "angle_unittests": targets.legacy_test_config(
+            use_isolated_scripts_api = True,
+        ),
+        "base_unittests": None,
+        "blink_common_unittests": None,
+        "blink_fuzzer_unittests": None,
+        "blink_heap_unittests": None,
+        "blink_platform_unittests": None,
+        "blink_unittests": None,
+        "boringssl_crypto_tests": None,
+        "boringssl_ssl_tests": None,
+        "capture_unittests": None,
+        "cast_unittests": None,
+        "cc_unittests": None,
+        "components_browsertests": None,
+        "components_unittests": None,
+        "content_browsertests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-bot-mode",
+                "--test-launcher-filter-file=testing/buildbot/filters/ios.content_browsertests.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 8,
+                expiration_sec = 10800,
+                hard_timeout_sec = 14400,
+            ),
+            timeout_sec = 14400,
+        ),
+        "content_unittests": None,
+        "crashpad_tests": None,
+        "crypto_unittests": None,
+        "device_unittests": None,
+        "display_unittests": None,
+        "env_chromium_unittests": None,
+        "events_unittests": None,
+        "gcm_unit_tests": None,
+        "gfx_unittests": None,
+        "gin_unittests": None,
+        "gl_unittests": None,
+        "google_apis_unittests": None,
+        "gpu_unittests": None,
+        "gwp_asan_unittests": None,
+        "ipc_tests": None,
+        "latency_unittests": None,
+        "leveldb_unittests": None,
+        "libjingle_xmpp_unittests": None,
+        "liburlpattern_unittests": None,
+        "media_unittests": None,
+        "midi_unittests": None,
+        "mojo_unittests": None,
+        "net_unittests": None,
+        "perfetto_unittests": None,
+        "printing_unittests": None,
+        "services_unittests": None,
+        "shell_dialogs_unittests": None,
+        "skia_unittests": None,
+        "sql_unittests": None,
+        "storage_unittests": None,
+        "ui_base_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=testing/buildbot/filters/ios.ui_base_unittests.filter",
+            ],
+        ),
+        "ui_touch_selection_unittests": None,
+        "ui_unittests": None,
+        "url_unittests": None,
+        "viz_unittests": None,
+        "wtf_unittests": None,
+        "zlib_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ios_common_tests",
+    tests = {
+        "absl_hardening_tests": None,
+        "boringssl_crypto_tests": None,
+        "boringssl_ssl_tests": None,
+        "crashpad_tests": None,
+        "crypto_unittests": None,
+        "google_apis_unittests": None,
+        "ios_components_unittests": None,
+        "ios_net_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "ios_remoting_unittests": None,
+        "ios_testing_unittests": None,
+        "net_unittests": None,
+        # TODO(https://bugs.chromium.org/p/gn/issues/detail?id=340): Enable this.
+        # "rust_gtest_interop_unittests": None,
+        "services_unittests": None,
+        "sql_unittests": None,
+        "url_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ios_crash_xcuitests",
+    tests = {
+        "ios_crash_xcuitests_module": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ios_cronet_tests",
+    tests = {
+        "cronet_test": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ios_eg2_cq_tests",
+    tests = {
+        "ios_chrome_integration_eg2tests_module": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 8,
+            ),
+        ),
+        "ios_web_shell_eg2tests_module": None,
+    },
+)
+
+# Test suites in ios_eg2_cq_tests_parallel should be the same test suites as
+# ios_eg2_cq_tests. The swarming shards between the versions can differ.
+# Effectiveness of ios_parallel_simulators is determined by
+# the number of test classes in the suite and the number of swarming shards.
+# For ios_parallel_simulators to be most effective there should be twice as
+# many test classes in the suite as there are swarming shards.
+targets.legacy_basic_suite(
+    name = "ios_eg2_cq_tests_parallel",
+    tests = {
+        "ios_chrome_integration_eg2tests_module": targets.legacy_test_config(
+            mixins = [
+                "ios_parallel_simulators",
+            ],
+            swarming = targets.swarming(
+                shards = 8,
+            ),
+        ),
+        "ios_web_shell_eg2tests_module": None,
+    },
+)
+
+# Test suites in ios_eg2_tests_parallel should be the same test suites as
+# ios_eg2_tests. The swarming shards between the versions can differ.
+# Effectiveness of ios_parallel_simulators is determined by
+# the number of test classes in the suite and the number of swarming shards.
+# For ios_parallel_simulators to be most effective there should be twice as
+# many test classes in the suite as there are swarming shards.
+targets.legacy_basic_suite(
+    name = "ios_eg2_tests",
+    tests = {
+        "ios_chrome_bookmarks_eg2tests_module": None,
+        "ios_chrome_settings_eg2tests_module": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 6,
+            ),
+        ),
+        "ios_chrome_signin_eg2tests_module": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 6,
+            ),
+        ),
+        "ios_chrome_smoke_eg2tests_module": None,
+        "ios_chrome_ui_eg2tests_module": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 12,
+            ),
+        ),
+        "ios_chrome_web_eg2tests_module": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "ios_showcase_eg2tests_module": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ios_eg2_tests_parallel",
+    tests = {
+        "ios_chrome_bookmarks_eg2tests_module": None,
+        "ios_chrome_settings_eg2tests_module": targets.legacy_test_config(
+            mixins = [
+                "ios_parallel_simulators",
+            ],
+            swarming = targets.swarming(
+                shards = 4,
+            ),
+        ),
+        "ios_chrome_signin_eg2tests_module": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 6,
+            ),
+        ),
+        "ios_chrome_smoke_eg2tests_module": None,
+        "ios_chrome_ui_eg2tests_module": targets.legacy_test_config(
+            mixins = [
+                "ios_parallel_simulators",
+            ],
+            swarming = targets.swarming(
+                shards = 12,
+            ),
+        ),
+        "ios_chrome_web_eg2tests_module": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "ios_showcase_eg2tests_module": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ios_remoting_fyi_unittests",
+    tests = {
+        "ios_remoting_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "ios_screen_size_dependent_tests",
+    tests = {
+        "base_unittests": None,
+        "components_unittests": None,
+        "gfx_unittests": None,
+        "ios_chrome_unittests": None,
+        "ios_web_inttests": None,
+        "ios_web_unittests": None,
+        "ios_web_view_inttests": None,
+        "ios_web_view_unittests": None,
+        "skia_unittests": None,
+        "ui_base_unittests": None,
+    },
+)
+
+# END tests which run on the GPU bots
+
+targets.legacy_basic_suite(
+    name = "js_code_coverage_browser_tests",
+    tests = {
+        "js_code_coverage_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            swarming = targets.swarming(
+                shards = 16,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "lacros_all_tast_tests",
+    tests = {
+        "lacros_all_tast_tests": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            swarming = targets.swarming(
+                idempotent = False,  # https://crbug.com/923426#c27
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "lacros_all_tast_tests_informational",
+    tests = {
+        "lacros_all_tast_tests_informational": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            swarming = targets.swarming(
+                idempotent = False,  # https://crbug.com/923426#c27
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "lacros_cq_tast_tests_eve",
+    tests = {
+        "lacros_cq_tast_tests_eve": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            swarming = targets.swarming(
+                idempotent = False,  # https://crbug.com/923426#c27
+            ),
+            experiment_percentage = 5,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "lacros_device_or_vm_gtests",
+    tests = {
+        "aura_unittests": None,
+        "cc_unittests": None,
+        "interactive_ui_tests": None,
+        "ozone_unittests": None,
+        "vaapi_unittest": targets.legacy_test_config(
+            args = [
+                "--stop-ui",
+                # Tell libva to do dummy encoding/decoding. For more info, see:
+                # https://github.com/intel/libva/blob/master/va/va_fool.c#L47
+                "--env-var",
+                "LIBVA_DRIVERS_PATH",
+                "./",
+                "--env-var",
+                "LIBVA_DRIVER_NAME",
+                "libfake",
+                "--gtest_filter=\"VaapiTest.*\"",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "lacros_fyi_tast_tests",
+    tests = {
+        "lacros_fyi_tast_tests": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            swarming = targets.swarming(
+                idempotent = False,  # https://crbug.com/923426#c27
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "lacros_skylab_amd64_fyi",
+    tests = {
+        "lacros_fyi_tast_tests": targets.legacy_test_config(
+            tast_expr = "(\"group:mainline\" && \"dep:lacros\" && !informational)",
+            timeout_sec = 10800,
+        ),
+        "ozone_unittests": targets.legacy_test_config(
+            timeout_sec = 3600,
+        ),
+    },
+)
+
+# create this temporary lacros arm test suites that runs on skylab
+# TODO(crbug.com/1247425): remove it if it is the same as
+# lacros_skylab
+targets.legacy_basic_suite(
+    name = "lacros_skylab_arm_tests_fyi",
+    tests = {
+        "lacros_all_tast_tests": targets.legacy_test_config(
+            tast_expr = "(\"group:mainline\" && \"dep:lacros\" && !informational)",
+            timeout_sec = 10800,
+        ),
+        "ozone_unittests": targets.legacy_test_config(
+            timeout_sec = 3600,
+        ),
+        "viz_unittests": targets.legacy_test_config(
+            timeout_sec = 3600,
+        ),
+    },
+)
+
+# Lacros tests that run on Skylab, and these tests are usually HW sensative,
+# Currently we only run Tast tests.
+targets.legacy_basic_suite(
+    name = "lacros_skylab_tests",
+    tests = {
+        "lacros_all_tast_tests": targets.legacy_test_config(
+            tast_expr = "(\"group:mainline\" && (\"dep:lacros_stable\" || \"dep:lacros\") && !informational)",
+            test_level_retries = 2,
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            timeout_sec = 10800,
+            shards = 2,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "lacros_skylab_tests_with_gtests",
+    tests = {
+        "chromeos_integration_tests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "lacros_vm_gtests",
+    tests = {
+        "base_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "leak_detection_isolated_scripts",
+    tests = {
+        "memory.leak_detection": targets.legacy_test_config(
+            test = "performance_test_suite",
+            override_compile_targets = [
+                "performance_test_suite",
+            ],
+            args = [
+                "--pageset-repeat=1",
+                "--test-shard-map-filename=linux_leak_detection_shard_map.json",
+                "--upload-results",
+                "--output-format=histograms",
+                "--browser=release",
+                "--xvfb",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+                expiration_sec = 36000,
+                hard_timeout_sec = 10800,
+                io_timeout_sec = 3600,
+            ),
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+                args = [
+                    "--smoke-test-mode",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_cfm_gtests",
+    tests = {
+        "chromeos_unittests": None,
+        "unit_tests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_chromeos_browser_tests_require_lacros",
+    tests = {
+        "browser_tests_require_lacros": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter",
+                "--lacros-chrome-path=lacros_clang_x64",
+            ],
+            swarming = targets.swarming(
+                shards = 8,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_chromeos_lacros_gtests",
+    tests = {
+        # Chrome OS (Ash) and Lacros only.
+        "chromeos_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_chromeos_oobe_specific_tests",
+    tests = {
+        # TODO(crbug.com/1071693): Merge this suite back in to the main
+        # browser_tests when the tests no longer fail on MSAN.
+        "oobe_only_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_chromeos_specific_gtests",
+    tests = {
+        # Chrome OS only.
+        "ash_components_unittests": None,
+        # TODO(crbug.com/1351793) Enable on CQ when stable.
+        "ash_crosapi_tests": targets.legacy_test_config(
+            ci_only = True,
+        ),
+        "ash_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 5,
+            ),
+        ),
+        "ash_webui_unittests": None,
+        "aura_unittests": None,
+        "chromeos_components_unittests": None,
+        "exo_unittests": None,
+        "gl_unittests_ozone": None,
+        "keyboard_unittests": None,
+        "ozone_gl_unittests": targets.legacy_test_config(
+            args = [
+                "--ozone-platform=headless",
+            ],
+        ),
+        "ozone_unittests": None,
+        "ozone_x11_unittests": None,
+        "shell_encryption_unittests": None,
+        "ui_chromeos_unittests": None,
+        "usage_time_limit_unittests": targets.legacy_test_config(
+            experiment_percentage = 100,
+        ),
+        "wayland_client_perftests": None,
+        "wayland_client_tests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_flavor_specific_chromium_gtests",
+    tests = {
+        # Android, Chrome OS and Linux
+        "sandbox_linux_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_lacros_chrome_browsertests_non_version_skew",
+    tests = {
+        "lacros_chrome_browsertests": targets.legacy_test_config(
+            test = "lacros_chrome_browsertests",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter",
+            ],
+        ),
+        "lacros_chrome_browsertests_run_in_series": targets.legacy_test_config(
+            test = "lacros_chrome_browsertests_run_in_series",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_lacros_chrome_browsertests_version_skew",
+    tests = {
+        "lacros_chrome_browsertests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
+            ],
+        ),
+        "lacros_chrome_browsertests_run_in_series": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_lacros_chrome_interactive_ui_tests_version_skew",
+    tests = {
+        "interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_lacros_chrome_interactive_ui_tests_version_skew_beta",
+    tests = {
+        "interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_lacros_chrome_interactive_ui_tests_version_skew_dev",
+    tests = {
+        "interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_lacros_chrome_interactive_ui_tests_version_skew_stable",
+    tests = {
+        "interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_lacros_specific_gtests",
+    tests = {
+        "lacros_chrome_unittests": None,
+        "ozone_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_specific_chromium_isolated_scripts",
+    tests = {
+        # not_site_per_process_blink_web_tests provides coverage for
+        # running Layout Tests without site-per-process.  This is the mode used
+        # on Android and Android bots currently do not run the full set of
+        # layout tests.  Running in this mode on linux compensates for lack of
+        # direct Android coverage.
+        "not_site_per_process_blink_web_tests": targets.legacy_test_config(
+            test = "blink_web_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                "--flag-specific=disable-site-isolation-trials",
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 8,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        # not_site_per_process_blink_wpt_tests provides coverage for
+        # running WPTs without site-per-process.  This is the mode used
+        # on Android and Android bots currently do not run the full set of
+        # layout tests.  Running in this mode on linux compensates for lack of
+        # direct Android coverage.
+        "not_site_per_process_blink_wpt_tests": targets.legacy_test_config(
+            test = "blink_wpt_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                "--flag-specific=disable-site-isolation-trials",
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        "webdriver_tests_suite": targets.legacy_test_config(
+            test = "chrome_wpt_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--test-type=wdspec",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "linux_specific_xr_gtests",
+    tests = {
+        "xr_browser_tests": targets.legacy_test_config(
+            test = "xr_browser_tests",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "live_companion_tests",
+    tests = {
+        "live_companion_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            override_compile_targets = [
+                "browser_tests",
+            ],
+            args = [
+                "--gtest_filter=CompanionLiveTest.*",
+                "--run-live-tests",
+                "--run-manual",
+                "--sync-status-change-checker-timeout=600",
+                # Timeout values below are in milliseconds.
+                "--test-tiny-timeout=85000",
+                "--ui-test-action-timeout=90000",
+                "--ui-test-action-max-timeout=95000",
+                "--test-launcher-timeout=100000",
+                "--isolated-script-test-launcher-retry-limit=5",
+            ],
+            swarming = targets.swarming(
+                expiration_sec = 3600,
+                hard_timeout_sec = 3600,
+            ),
+        ),
+    },
+)
+
+# TODO(crbug.com/1320449): Remove this set of test suites when LSan can be
+# enabled Mac ASan bots. This list will be gradually filled with more tests
+# until the bot has parity with ASan bots, and the ASan bot can then enable
+# LSan and the mac-lsan-fyi-rel bot go away.
+targets.legacy_basic_suite(
+    name = "mac_lsan_fyi_gtests",
+    tests = {
+        "absl_hardening_tests": None,
+        "accessibility_unittests": None,
+        "app_shell_unittests": None,
+        "base_unittests": None,
+        "blink_heap_unittests": None,
+        "blink_platform_unittests": None,
+        "blink_unittests": None,
+        "cc_unittests": None,
+        "components_unittests": None,
+        "content_unittests": None,
+        "crashpad_tests": None,
+        "cronet_unittests": None,
+        "device_unittests": None,
+        "net_unittests": None,
+        # TODO(crbug.com/1459686): Enable this.
+        # "rust_gtest_interop_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "mac_specific_chromium_gtests",
+    tests = {
+        "power_sampler_unittests": None,
+        "sandbox_unittests": None,
+        "updater_tests": None,
+        "xr_browser_tests": targets.legacy_test_config(
+            test = "xr_browser_tests",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "mac_specific_isolated_scripts",
+    tests = {
+        "mac_signing_tests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "minidump_uploader_tests",
+    tests = {
+        "minidump_uploader_test": targets.legacy_test_config(
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "model_validation_tests",
+    tests = {
+        "model_validation_tests": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "mojo_python_unittests_isolated_scripts",
+    tests = {
+        "mojo_python_unittests": targets.legacy_test_config(
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "monochrome_public_apk_checker_isolated_script",
+    tests = {
+        "monochrome_public_apk_checker": targets.legacy_test_config(
+            remove_mixins = [
+                "android_r",
+                "bullhead",
+                "flame",
+                "marshmallow",
+                "mdarcy",
+                "oreo_fleet",
+                "oreo_mr1_fleet",
+                "pie_fleet",
+                "walleye",
+            ],
+            swarming = targets.swarming(
+                dimensions = {
+                    "os": "Ubuntu-18.04",
+                    "cpu": "x86-64",
+                    "device_os": None,
+                    "device_os_flavor": None,
+                    "device_playstore_version": None,
+                    "device_type": None,
+                },
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "network_sandbox_browser_tests",
+    tests = {
+        "browser_tests_network_sandbox": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--enable-features=NetworkServiceSandbox",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "components_browsertests_network_sandbox": targets.legacy_test_config(
+            test = "components_browsertests",
+            args = [
+                "--enable-features=NetworkServiceSandbox",
+            ],
+        ),
+        "content_browsertests_network_sandbox": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--enable-features=NetworkServiceSandbox",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "interactive_ui_tests_network_sandbox": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            args = [
+                "--enable-features=NetworkServiceSandbox",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "sync_integration_tests_network_sandbox": targets.legacy_test_config(
+            test = "sync_integration_tests",
+            args = [
+                "--enable-features=NetworkServiceSandbox",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "network_service_fyi_gtests",
+    tests = {
+        "network_service_web_request_proxy_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--enable-features=ForceWebRequestProxyForTest",
+            ],
+            swarming = targets.swarming(
+                shards = 15,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "non_android_and_cast_and_chromeos_chromium_gtests",
+    tests = {
+        "cronet_tests": None,
+        "cronet_unittests": None,
+        "headless_browsertests": None,
+        "headless_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "non_android_chromium_gtests",
+    tests = {
+        "accessibility_unittests": None,
+        "app_shell_unittests": None,
+        "blink_fuzzer_unittests": None,
+        "browser_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "chrome_app_unittests": None,
+        "chromedriver_unittests": None,
+        "extensions_browsertests": None,
+        "extensions_unittests": None,
+        "filesystem_service_unittests": None,  # https://crbug.com/862712
+        "interactive_ui_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "message_center_unittests": None,
+        "nacl_loader_unittests": None,
+        "native_theme_unittests": None,
+        "pdf_unittests": None,
+        "ppapi_unittests": None,
+        "printing_unittests": None,
+        "remoting_unittests": None,
+        "service_manager_unittests": None,  # https://crbug.com/843134
+        "snapshot_unittests": None,
+        "sync_integration_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "ui_unittests": None,
+        "views_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "non_android_chromium_gtests_no_nacl",
+    tests = {
+        "accessibility_unittests": None,
+        "app_shell_unittests": None,
+        "blink_fuzzer_unittests": None,
+        "browser_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "chrome_app_unittests": None,
+        "chromedriver_unittests": None,
+        "extensions_browsertests": None,
+        "extensions_unittests": None,
+        "filesystem_service_unittests": None,  # https://crbug.com/862712
+        "interactive_ui_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "message_center_unittests": None,
+        "native_theme_unittests": None,
+        "pdf_unittests": None,
+        "printing_unittests": None,
+        "remoting_unittests": None,
+        "service_manager_unittests": None,  # https://crbug.com/843134
+        "snapshot_unittests": None,
+        "sync_integration_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "ui_unittests": None,
+        "views_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "non_android_chromium_gtests_skia_gold",
+    tests = {
+        "views_examples_unittests": targets.legacy_test_config(
+            mixins = [
+                "skia_gold_test",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "oop_network_service_tests",
+    tests = {
+        "oop_network_service_content_browsertests": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--enable-features=NetworkServiceOutOfProcessMemoryThreshold:network_service_oop_threshold_mb/1077",
+                "--disable-features=NetworkServiceInProcess2",
+            ],
+            swarming = targets.swarming(
+                shards = 25,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "optimization_guide_android_gtests",
+    tests = {
+        "optimization_guide_components_unittests": targets.legacy_test_config(
+            test = "components_unittests",
+            args = [
+                "--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*",
+            ],
+        ),
+        # TODO(mgeorgaklis): Add optimization_guide_unittests when they become Android compatible.
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "optimization_guide_gtests",
+    tests = {
+        "optimization_guide_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--gtest_filter=*OptimizationGuide*:*PageContentAnnotations*",
+            ],
+        ),
+        "optimization_guide_components_unittests": targets.legacy_test_config(
+            test = "components_unittests",
+            args = [
+                "--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*",
+            ],
+        ),
+        "optimization_guide_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "perfetto_gtests",
+    tests = {
+        "base_unittests": None,
+        "browser_tests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=ChromeTracingDelegateBrowserTest.*",
+            ],
+        ),
+        "content_browsertests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 8,
+            ),
+            android_swarming = targets.swarming(
+                shards = 15,
+            ),
+        ),
+        "perfetto_unittests": None,
+        "services_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "perfetto_gtests_android",
+    tests = {
+        "android_browsertests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=StartupMetricsTest.*",
+            ],
+        ),
+        "base_unittests": None,
+        "content_browsertests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 8,
+            ),
+            android_swarming = targets.swarming(
+                shards = 15,
+            ),
+        ),
+        "perfetto_unittests": None,
+        "services_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "performance_smoke_test_isolated_scripts",
+    tests = {
+        "performance_test_suite": targets.legacy_test_config(
+            args = [
+                "--pageset-repeat=1",
+                "--test-shard-map-filename=smoke_test_benchmark_shard_map.json",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+                hard_timeout_sec = 960,
+            ),
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+                args = [
+                    "--smoke-test-mode",
+                ],
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "pixel_browser_tests_gtests",
+    tests = {
+        "pixel_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            mixins = [
+                "skia_gold_test",
+            ],
+            args = [
+                "--browser-ui-tests-verify-pixels",
+                "--enable-pixel-output-in-tests",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter",
+                "--test-launcher-jobs=1",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "pixel_interactive_ui_tests": targets.legacy_test_config(
+            test = "interactive_ui_tests",
+            mixins = [
+                "skia_gold_test",
+            ],
+            args = [
+                "--browser-ui-tests-verify-pixels",
+                "--enable-pixel-output-in-tests",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "pixel_experimental_browser_tests_gtests",
+    tests = {
+        "pixel_experimental_browser_tests": targets.legacy_test_config(
+            test = "browser_tests",
+            mixins = [
+                "skia_gold_test",
+            ],
+            args = [
+                "--browser-ui-tests-verify-pixels",
+                "--enable-pixel-output-in-tests",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.pixel_tests.filter",
+            ],
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "private_code_failure_test_isolated_scripts",
+    tests = {
+        "private_code_failure_test": None,
+    },
+)
+
+# TODO(dpranke): These are run on the p/chromium waterfall; they should
+# probably be run on other builders, and we should get rid of the p/chromium
+# waterfall.
+targets.legacy_basic_suite(
+    name = "public_build_scripts",
+    tests = {
+        "checkbins": targets.legacy_test_config(
+            script = "checkbins.py",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "pytype_tests",
+    tests = {
+        "blink_pytype": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "fuchsia_pytype": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "gold_common_pytype": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "gpu_pytype": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+        "testing_pytype": targets.legacy_test_config(
+            mixins = [
+                "has_native_resultdb_integration",
+            ],
+        ),
+    },
+)
+
+# Rust tests run on all targets.
+targets.legacy_basic_suite(
+    name = "rust_common_gtests",
+    tests = {
+        "base_unittests": None,
+        # For go/rusty-qr-code-generator
+        "components_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/rust.components_unittests.filter",
+            ],
+        ),
+        "mojo_rust_integration_unittests": None,
+        "mojo_rust_unittests": None,
+        "rust_gtest_interop_unittests": None,
+        "test_cpp_including_rust_unittests": targets.legacy_test_config(
+            test = "test_cpp_including_rust_unittests",
+        ),
+        "test_serde_json_lenient": targets.legacy_test_config(
+            test = "test_serde_json_lenient",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "rust_native_tests",
+    tests = {
+        "build_rust_tests": targets.legacy_test_config(
+            test = "build_rust_tests",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "site_isolation_android_fyi_gtests",
+    tests = {
+        "site_per_process_android_browsertests": targets.legacy_test_config(
+            test = "android_browsertests",
+            args = [
+                "--site-per-process",
+            ],
+            swarming = targets.swarming(
+                shards = 1,
+            ),
+        ),
+        "site_per_process_chrome_public_test_apk": targets.legacy_test_config(
+            test = "chrome_public_test_apk",
+            mixins = [
+                "skia_gold_test",
+                "has_native_resultdb_integration",
+            ],
+            args = [
+                "--site-per-process",
+            ],
+            swarming = targets.swarming(
+                shards = 20,
+            ),
+        ),
+        "site_per_process_chrome_public_unit_test_apk": targets.legacy_test_config(
+            test = "chrome_public_unit_test_apk",
+            mixins = [
+                "skia_gold_test",
+            ],
+            args = [
+                "--site-per-process",
+            ],
+        ),
+        "site_per_process_components_browsertests": targets.legacy_test_config(
+            test = "components_browsertests",
+            args = [
+                "--site-per-process",
+            ],
+        ),
+        "site_per_process_components_unittests": targets.legacy_test_config(
+            test = "components_unittests",
+            args = [
+                "--site-per-process",
+            ],
+            swarming = targets.swarming(
+                shards = 5,
+            ),
+        ),
+        "site_per_process_content_browsertests": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--site-per-process",
+                "--test-launcher-filter-file=../../testing/buildbot/filters/site_isolation_android.content_browsertests.filter",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+        "site_per_process_content_shell_test_apk": targets.legacy_test_config(
+            test = "content_shell_test_apk",
+            args = [
+                "--site-per-process",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+        ),
+        "site_per_process_content_unittests": targets.legacy_test_config(
+            test = "content_unittests",
+            args = [
+                "--site-per-process",
+            ],
+        ),
+        "site_per_process_unit_tests": targets.legacy_test_config(
+            test = "unit_tests",
+            args = [
+                "--site-per-process",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "swangle_gtests",
+    tests = {
+        "angle_deqp_egl_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles2_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles31_rotate180_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles31_rotate270_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles31_rotate90_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles31_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles3_rotate180_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles3_rotate270_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles3_rotate90_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_gles3_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            swarming = targets.swarming(
+                shards = 4,
+            ),
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_khr_gles2_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_khr_gles31_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_deqp_khr_gles3_tests": targets.legacy_test_config(
+            args = [
+                "--use-angle=swiftshader",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+        "angle_end2end_tests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=*Vulkan_SwiftShader*",
+            ],
+            use_isolated_scripts_api = True,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "system_webview_shell_instrumentation_tests",
+    tests = {
+        "system_webview_shell_layout_test_apk": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "system_webview_wpt",
+    tests = {
+        "system_webview_wpt": targets.legacy_test_config(
+            results_handler = "layout tests",
+            args = [
+                "--no-wpt-internal",
+            ],
+            swarming = targets.swarming(
+                shards = 25,
+                expiration_sec = 18000,
+                hard_timeout_sec = 14400,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "telemetry_android_minidump_unittests_isolated_scripts",
+    tests = {
+        "telemetry_chromium_minidump_unittests": targets.legacy_test_config(
+            test = "telemetry_perf_unittests_android_chrome",
+            args = [
+                "BrowserMinidumpTest",
+                "--browser=android-chromium",
+                "-v",
+                "--passthrough",
+                "--retry-limit=2",
+            ],
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+        "telemetry_monochrome_minidump_unittests": targets.legacy_test_config(
+            test = "telemetry_perf_unittests_android_monochrome",
+            args = [
+                "BrowserMinidumpTest",
+                "--browser=android-chromium-monochrome",
+                "-v",
+                "--passthrough",
+                "--retry-limit=2",
+            ],
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "telemetry_desktop_minidump_unittests_isolated_scripts",
+    tests = {
+        # Takes ~2.5 minutes of bot time to run.
+        "telemetry_desktop_minidump_unittests": targets.legacy_test_config(
+            test = "telemetry_perf_unittests",
+            args = [
+                "BrowserMinidumpTest",
+                "-v",
+                "--passthrough",
+                "--retry-limit=2",
+            ],
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "telemetry_perf_unittests_isolated_scripts",
+    tests = {
+        "telemetry_perf_unittests": targets.legacy_test_config(
+            args = [
+                # TODO(crbug.com/1077284): Remove this once Crashpad is the default.
+                "--extra-browser-args=--enable-crashpad",
+            ],
+            swarming = targets.swarming(
+                shards = 12,
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "telemetry_perf_unittests_isolated_scripts_android",
+    tests = {
+        "telemetry_perf_unittests": targets.legacy_test_config(
+            test = "telemetry_perf_unittests_android_chrome",
+            args = [
+                # TODO(crbug.com/1077284): Remove this once Crashpad is the default.
+                "--extra-browser-args=--enable-crashpad",
+            ],
+            swarming = targets.swarming(
+                shards = 12,
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "telemetry_perf_unittests_isolated_scripts_xvfb",
+    tests = {
+        "telemetry_perf_unittests": targets.legacy_test_config(
+            args = [
+                # TODO(crbug.com/1077284): Remove this once Crashpad is the default.
+                "--extra-browser-args=--enable-crashpad",
+                "--xvfb",
+            ],
+            swarming = targets.swarming(
+                shards = 12,
+                idempotent = False,  # https://crbug.com/549140
+            ),
+            resultdb = targets.resultdb(
+                enable = True,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "test_traffic_annotation_auditor_script",
+    tests = {
+        "test_traffic_annotation_auditor": targets.legacy_test_config(
+            script = "test_traffic_annotation_auditor.py",
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "updater_gtests_linux",
+    tests = {
+        "updater_tests": targets.legacy_test_config(
+            mixins = [
+                "updater-default-pool",
+            ],
+        ),
+        # 'updater_tests_system' is not yet supported on Linux.
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "updater_gtests_mac",
+    tests = {
+        "updater_tests": targets.legacy_test_config(
+            mixins = [
+                "updater-default-pool",
+            ],
+        ),
+        "updater_tests_system": targets.legacy_test_config(
+            mixins = [
+                "updater-mac-pool",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "updater_gtests_win",
+    tests = {
+        "updater_tests": targets.legacy_test_config(
+            mixins = [
+                "integrity_high",
+                "updater-default-pool",
+            ],
+        ),
+        "updater_tests_system": targets.legacy_test_config(
+            mixins = [
+                "integrity_high",
+                "updater-default-pool",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "updater_gtests_win_uac",
+    tests = {
+        "updater_tests_system": targets.legacy_test_config(
+            mixins = [
+                "integrity_high",
+                "updater-win-uac-pool",
+            ],
+        ),
+        "updater_tests_win_uac": targets.legacy_test_config(
+            mixins = [
+                "updater-win-uac-pool",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "upload_perfetto",
+    tests = {
+        "upload_trace_processor": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "variations_smoke_tests",
+    tests = {
+        "variations_smoke_tests": targets.legacy_test_config(
+            test = "variations_smoke_tests",
+            mixins = [
+                "skia_gold_test",
+            ],
+            resultdb = targets.resultdb(
+                enable = True,
+                result_format = "single",
+            ),
+        ),
+    },
+)
+
+# Not applicable for android x86 & x64 since the targets here assert
+# "enable_vr" in GN which is only true for android arm & arm64.
+# For details, see the following files:
+#  * //chrome/android/BUILD.gn
+#  * //chrome/browser/android/vr/BUILD.gn
+#  * //device/vr/buildflags/buildflags.gni
+targets.legacy_basic_suite(
+    name = "vr_android_specific_chromium_tests",
+    tests = {
+        "chrome_public_test_vr_apk": targets.legacy_test_config(
+            args = [
+                "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json",
+                "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+            ),
+        ),
+        "vr_android_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "vr_platform_specific_chromium_gtests",
+    tests = {
+        # Only run on platforms that intend to support WebVR in the near
+        # future.
+        "vr_common_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "vulkan_swiftshader_isolated_scripts",
+    tests = {
+        "vulkan_swiftshader_blink_web_tests": targets.legacy_test_config(
+            test = "blink_web_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+                "--skipped=always",
+                "--flag-specific=skia-vulkan-swiftshader",
+            ],
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "web_engine_gtests",
+    tests = {
+        "cast_runner_browsertests": None,
+        "cast_runner_integration_tests": None,
+        "cast_runner_unittests": None,
+        "web_engine_browsertests": None,
+        "web_engine_integration_tests": targets.legacy_test_config(
+            args = [
+                "--test-arg=--vmodule=test_navigation_listener=1",
+            ],
+        ),
+        "web_engine_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webrtc_chromium_baremetal_gtests",
+    tests = {
+        # Run capture unittests on bots that have real webcams.
+        "capture_unittests": targets.legacy_test_config(
+            args = [
+                "--enable-logging",
+                "--v=1",
+                "--test-launcher-jobs=1",
+                "--test-launcher-print-test-stdio=always",
+            ],
+            swarming = targets.swarming(
+                dimensions = {
+                    "pool": "WebRTC-chromium",
+                },
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webrtc_chromium_gtests",
+    tests = {
+        "browser_tests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=WebRtcStatsPerfBrowserTest.*:WebRtcVideoDisplayPerfBrowserTests*:WebRtcVideoQualityBrowserTests*:WebRtcVideoHighBitrateBrowserTest*:WebRtcWebcamBrowserTests*",
+                "--run-manual",
+                "--ui-test-action-max-timeout=300000",
+                "--test-launcher-timeout=350000",
+                "--test-launcher-jobs=1",
+                "--test-launcher-bot-mode",
+                "--test-launcher-print-test-stdio=always",
+            ],
+        ),
+        # TODO(b/246519185) - Py3 incompatible, decide if to keep test.:
+        # "browser_tests_apprtc": targets.legacy_test_config(
+        #     args = [
+        #         "--gtest_filter=WebRtcApprtcBrowserTest.*",
+        #         "--run-manual",
+        #         "--test-launcher-jobs=1",
+        #     ],
+        # ),
+        "browser_tests_functional": targets.legacy_test_config(
+            test = "browser_tests",
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/webrtc_functional.browser_tests.filter",
+                "--run-manual",
+                "--test-launcher-jobs=1",
+            ],
+        ),
+        # Run all normal WebRTC content_browsertests. This is mostly so
+        # the FYI bots can detect breakages.
+        "content_browsertests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=WebRtc*",
+            ],
+        ),
+        # These run a few tests on fake webcams. They need to run sequentially,
+        # otherwise tests may interfere with each other.
+        "content_browsertests_sequential": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--gtest_filter=UsingRealWebcam*",
+                "--run-manual",
+                "--test-launcher-jobs=1",
+            ],
+        ),
+        "content_browsertests_stress": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--gtest_filter=WebRtc*MANUAL*:-UsingRealWebcam*",
+                "--run-manual",
+                "--ui-test-action-max-timeout=110000",
+                "--test-launcher-timeout=120000",
+            ],
+        ),
+        "content_unittests": targets.legacy_test_config(
+            args = [
+                "--test-launcher-filter-file=../../testing/buildbot/filters/webrtc.content_unittests.filter",
+            ],
+        ),
+        "remoting_unittests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=Webrtc*",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webrtc_chromium_simple_gtests",
+    tests = {
+        "content_browsertests": targets.legacy_test_config(
+            args = [
+                "--gtest_filter=WebRtc*",
+            ],
+        ),
+        # These run a few tests on fake webcams. They need to run sequentially,
+        # otherwise tests may interfere with each other.
+        "content_browsertests_sequential": targets.legacy_test_config(
+            test = "content_browsertests",
+            args = [
+                "--gtest_filter=UsingRealWebcam*",
+                "--run-manual",
+                "--test-launcher-jobs=1",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webrtc_chromium_wpt_tests",
+    tests = {
+        "blink_wpt_tests": targets.legacy_test_config(
+            test = "blink_wpt_tests",
+            results_handler = "layout tests",
+            mixins = [
+                "has_native_resultdb_integration",
+                "blink_tests_write_run_histories",
+            ],
+            args = [
+                # layout test failures are retried 3 times when '--test-list' is not
+                # passed, but 0 times when '--test-list' is passed. We want to always
+                # retry 3 times, so we explicitly specify it.
+                "--num-retries=3",
+                "-t",
+                "Release",
+                "external/wpt/webrtc",
+                "external/wpt/webrtc-encoded-transform",
+                "external/wpt/webrtc-extensions",
+                "external/wpt/webrtc-priority",
+                "external/wpt/webrtc-stats",
+                "external/wpt/webrtc-svc",
+            ],
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_64_cts_tests_gtest",
+    tests = {
+        "webview_64_cts_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 2,
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "chromium/android_webview/tools/cts_archive",
+                        location = "android_webview/tools/cts_archive",
+                        revision = "akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC",
+                    ),
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_bot_instrumentation_test_apk_gtest",
+    tests = {
+        "webview_instrumentation_test_apk": targets.legacy_test_config(
+            args = [
+                "--use-apk-under-test-flags-file",
+            ],
+            swarming = targets.swarming(
+                shards = 12,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_bot_instrumentation_test_apk_no_field_trial_gtest",
+    tests = {
+        "webview_instrumentation_test_apk_no_field_trial": targets.legacy_test_config(
+            test = "webview_instrumentation_test_apk",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            swarming = targets.swarming(
+                shards = 12,
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_bot_unittests_gtest",
+    tests = {
+        "android_webview_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_cts_tests_gtest",
+    tests = {
+        "webview_cts_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 2,
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "chromium/android_webview/tools/cts_archive",
+                        location = "android_webview/tools/cts_archive",
+                        revision = "akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC",
+                    ),
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_cts_tests_gtest_no_field_trial",
+    tests = {
+        "webview_cts_tests_no_field_trial": targets.legacy_test_config(
+            test = "webview_cts_tests",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "chromium/android_webview/tools/cts_archive",
+                        location = "android_webview/tools/cts_archive",
+                        revision = "akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC",
+                    ),
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_trichrome_64_cts_field_trial_tests",
+    tests = {
+        "webview_trichrome_64_cts_tests": targets.legacy_test_config(
+            args = [
+                "--store-data-dependencies-in-temp",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "chromium/android_webview/tools/cts_archive",
+                        location = "android_webview/tools/cts_archive",
+                        revision = "akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC",
+                    ),
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_trichrome_64_cts_tests",
+    tests = {
+        "webview_trichrome_64_cts_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                shards = 2,
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "chromium/android_webview/tools/cts_archive",
+                        location = "android_webview/tools/cts_archive",
+                        revision = "akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC",
+                    ),
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_trichrome_64_cts_tests_no_field_trial",
+    tests = {
+        "webview_trichrome_64_cts_tests_no_field_trial": targets.legacy_test_config(
+            test = "webview_trichrome_64_cts_tests",
+            args = [
+                "--disable-field-trial-config",
+            ],
+            swarming = targets.swarming(
+                shards = 2,
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "chromium/android_webview/tools/cts_archive",
+                        location = "android_webview/tools/cts_archive",
+                        revision = "akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC",
+                    ),
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_trichrome_cts_tests",
+    tests = {
+        "webview_trichrome_cts_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                cipd_packages = [
+                    targets.cipd_package(
+                        package = "chromium/android_webview/tools/cts_archive",
+                        location = "android_webview/tools/cts_archive",
+                        revision = "akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC",
+                    ),
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_ui_instrumentation_tests",
+    tests = {
+        "webview_ui_test_app_test_apk": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "webview_ui_instrumentation_tests_no_field_trial",
+    tests = {
+        "webview_ui_test_app_test_apk_no_field_trial": targets.legacy_test_config(
+            test = "webview_ui_test_app_test_apk",
+            args = [
+                "--disable-field-trial-config",
+            ],
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "win_specific_chromium_gtests",
+    tests = {
+        "chrome_elf_unittests": None,
+        "courgette_unittests": None,
+        "delayloads_unittests": None,
+        "elevation_service_unittests": None,
+        "gcp_unittests": None,
+        "install_static_unittests": None,
+        "installer_util_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "integrity": "high",
+                },
+            ),
+        ),
+        "notification_helper_unittests": None,
+        "sbox_integration_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "integrity": "high",
+                },
+            ),
+        ),
+        "sbox_unittests": None,
+        "sbox_validation_tests": None,
+        "setup_unittests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "integrity": "high",
+                },
+            ),
+        ),
+        "updater_tests": None,
+        "updater_tests_system": None,
+        "zucchini_unittests": None,
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "win_specific_isolated_scripts",
+    tests = {
+        "mini_installer_tests": targets.legacy_test_config(
+            swarming = targets.swarming(
+                dimensions = {
+                    "integrity": "high",
+                },
+            ),
+        ),
+        "polymer_tools_python_unittests": targets.legacy_test_config(
+            experiment_percentage = 0,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "win_specific_xr_perf_tests",
+    tests = {
+        "xr.webxr.static": targets.legacy_test_config(
+            test = "vr_perf_tests",
+            args = [
+                "--benchmarks=xr.webxr.static",
+                "-v",
+                "--upload-results",
+                "--output-format=histograms",
+                "--browser=release_x64",
+            ],
+            merge = targets.merge(
+                script = "//tools/perf/process_perf_results.py",
+            ),
+            # Experimental until we're sure these are stable.
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_tests_ios",
+    tests = {
+        "wpt_tests_ios": targets.legacy_test_config(
+            test = "chrome_ios_wpt",
+            results_handler = "layout tests",
+            args = [
+                "--no-wpt-internal",
+            ],
+            swarming = targets.swarming(
+                shards = 15,
+                expiration_sec = 18000,
+                hard_timeout_sec = 14400,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_web_tests",
+    tests = {
+        "wpt_tests_suite": targets.legacy_test_config(
+            test = "chrome_wpt_tests",
+            results_handler = "layout tests",
+            swarming = targets.swarming(
+                shards = 15,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_web_tests_android",
+    tests = {
+        "chrome_public_wpt": targets.legacy_test_config(
+            results_handler = "layout tests",
+            swarming = targets.swarming(
+                shards = 15,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+        "system_webview_wpt": targets.legacy_test_config(
+            results_handler = "layout tests",
+            swarming = targets.swarming(
+                shards = 15,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_web_tests_content_shell",
+    tests = {
+        "wpt_tests_suite": targets.legacy_test_config(
+            test = "content_shell_wpt",
+            results_handler = "layout tests",
+            swarming = targets.swarming(
+                shards = 15,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_web_tests_enable_leak_detection",
+    tests = {
+        "wpt_tests_suite": targets.legacy_test_config(
+            test = "content_shell_wpt",
+            results_handler = "layout tests",
+            args = [
+                "--enable-leak-detection",
+            ],
+            swarming = targets.swarming(
+                shards = 15,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_web_tests_highdpi",
+    tests = {
+        "wpt_tests_suite_highdpi": targets.legacy_test_config(
+            test = "content_shell_wpt",
+            results_handler = "layout tests",
+            args = [
+                "--flag-specific",
+                "highdpi",
+            ],
+            swarming = targets.swarming(
+                shards = 3,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_web_tests_identity",
+    tests = {
+        "wpt_tests_suite": targets.legacy_test_config(
+            test = "chrome_wpt_tests",
+            results_handler = "layout tests",
+            args = [
+                "--no-wpt-internal",
+                "webauthn/",
+            ],
+            swarming = targets.swarming(
+                shards = 1,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_web_tests_input",
+    tests = {
+        "wpt_tests_suite": targets.legacy_test_config(
+            test = "chrome_wpt_tests",
+            results_handler = "layout tests",
+            args = [
+                "--no-wpt-internal",
+                "infrastructure/testdriver/actions/",
+                "input-events/",
+                "pointerevents/",
+                "touch-events/",
+                "uievents/",
+            ],
+            swarming = targets.swarming(
+                shards = 1,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+            experiment_percentage = 100,
+        ),
+    },
+)
+
+targets.legacy_basic_suite(
+    name = "wpt_web_tests_not_site_per_process",
+    tests = {
+        "wpt_tests_suite_not_site_per_process": targets.legacy_test_config(
+            test = "content_shell_wpt",
+            results_handler = "layout tests",
+            args = [
+                "--child-processes=8",
+                "--flag-specific",
+                "disable-site-isolation-trials",
+            ],
+            swarming = targets.swarming(
+                shards = 10,
+            ),
+            merge = targets.merge(
+                script = "//third_party/blink/tools/merge_web_test_results.py",
+                args = [
+                    "--verbose",
+                ],
+            ),
+        ),
+    },
+)
diff --git a/infra/config/targets/compound_suites.star b/infra/config/targets/compound_suites.star
new file mode 100644
index 0000000..11ce6069
--- /dev/null
+++ b/infra/config/targets/compound_suites.star
@@ -0,0 +1,1375 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file contains suite definitions that can be used in
+# //testing/buildbot/waterfalls.pyl and will also be usable for builders that
+# set their tests in starlark (once that is ready). The legacy_ prefix on the
+# declarations indicates the capability to be used in //testing/buildbot. Once a
+# suite is no longer needed in //testing/buildbot, targets.bundle (which does
+# not yet exist) can be used for grouping tests in a more flexible manner.
+
+load("//lib/targets.star", "targets")
+
+targets.legacy_compound_suite(
+    name = "android_10_rel_gtests",
+    basic_suites = [
+        "android_trichrome_smoke_tests",
+        "android_ar_gtests",
+        "android_ddready_vr_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "android_12_dbg_emulator_gtests",
+    basic_suites = [
+        "android_trichrome_smoke_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "android_marshmallow_gtests",
+    basic_suites = [
+        "android_smoke_tests",
+        "android_specific_chromium_gtests",  # Already includes gl_gtests.
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chrome_public_tests",
+        "linux_flavor_specific_chromium_gtests",
+        "vr_android_specific_chromium_tests",
+        "vr_platform_specific_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "android_nougat_emulator_gtests",
+    basic_suites = [
+        "android_emulator_specific_chrome_public_tests",
+        "android_monochrome_smoke_tests",
+        "android_smoke_tests",
+        "android_specific_chromium_gtests",  # Already includes gl_gtests.
+        "android_wpr_record_replay_tests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "linux_flavor_specific_chromium_gtests",
+        "system_webview_shell_instrumentation_tests",  # Not an experimental test
+        "webview_cts_tests_gtest",
+        "webview_ui_instrumentation_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "android_nougat_gtests",
+    basic_suites = [
+        "android_ar_gtests",
+        "android_ddready_vr_gtests",
+        "android_monochrome_smoke_tests",
+        "android_smoke_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "android_oreo_gtests",
+    basic_suites = [
+        "android_ar_gtests",
+        "android_ddready_vr_gtests",
+        "android_monochrome_smoke_tests",
+        "android_oreo_standard_gtests",
+        "android_smoke_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "android_pie_coverage_instrumentation_tests",
+    basic_suites = [
+        "android_smoke_tests",
+        "android_specific_coverage_java_tests",
+        "chrome_public_tests",
+        "vr_android_specific_chromium_tests",
+        "webview_ui_instrumentation_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "android_pie_gtests",
+    basic_suites = [
+        "android_ar_gtests",
+        "android_ddready_vr_gtests",
+        "android_monochrome_smoke_tests",
+        "android_smoke_tests",
+        "chromium_tracing_gtests",
+        # No standard tests due to capacity, no Vega tests since it's currently
+        # O only.
+    ],
+)
+
+# Keep in sync with android_pie_rel_gtests below, except for
+# vr_{android,platform}_specific_chromium_gtests which are not applicable
+# to android emulators on x86 & x64.
+targets.legacy_compound_suite(
+    name = "android_pie_rel_emulator_gtests",
+    basic_suites = [
+        "android_emulator_specific_chrome_public_tests",
+        "android_monochrome_smoke_tests",
+        "android_smoke_tests",
+        "android_specific_chromium_gtests",  # Already includes gl_gtests.
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "linux_flavor_specific_chromium_gtests",
+        "system_webview_shell_instrumentation_tests",  # Not an experimental test
+        "webview_cts_tests_gtest",
+        "webview_ui_instrumentation_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "android_pie_rel_gtests",
+    basic_suites = [
+        # TODO(crbug.com/1111436): Deprecate this when all the test suites below
+        # it are re-enabled.
+        "android_pie_rel_reduced_capacity_gtests",
+        "android_monochrome_smoke_tests",
+        "android_smoke_tests",
+        # "android_specific_chromium_gtests",  # Already includes gl_gtests.
+        # "chromium_gtests",
+        # "chromium_gtests_for_devices_with_graphical_output",
+        "chrome_public_tests",
+        # "linux_flavor_specific_chromium_gtests",
+        "system_webview_shell_instrumentation_tests",
+        # "vr_android_specific_chromium_tests",
+        # "vr_platform_specific_chromium_gtests",
+        "webview_64_cts_tests_gtest",
+        "webview_ui_instrumentation_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "bfcache_android_gtests",
+    basic_suites = [
+        "bfcache_android_specific_gtests",
+        "bfcache_generic_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "bfcache_linux_gtests",
+    basic_suites = [
+        "bfcache_generic_gtests",
+        "bfcache_linux_specific_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chrome_linux_isolated_script_tests",
+    basic_suites = [
+        "chrome_isolated_script_tests",
+        "chrome_private_code_test_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromeos_device_gtests",
+    basic_suites = [
+        "chromeos_browser_all_tast_tests",
+        "chromeos_browser_integration_tests",
+        "chromeos_device_only_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromeos_device_no_gtests",
+    basic_suites = [
+        "chromeos_browser_all_tast_tests",
+        "chromeos_browser_integration_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromeos_vm_gtests",
+    basic_suites = [
+        "chromeos_browser_all_tast_tests",
+        "chromeos_browser_integration_tests",
+        "chromeos_system_friendly_gtests",
+        "chromeos_integration_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_android_gtests",
+    basic_suites = [
+        "android_smoke_tests",
+        "android_specific_chromium_gtests",  # Already includes gl_gtests.
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chrome_public_tests",
+        "linux_flavor_specific_chromium_gtests",
+        "vr_android_specific_chromium_tests",
+        "vr_platform_specific_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_dbg_isolated_scripts",
+    basic_suites = [
+        "desktop_chromium_isolated_scripts",
+        "performance_smoke_test_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts",
+    ],
+)
+
+# This is meant to be a superset of 'chromium_linux_and_gl_gtests'. Any
+# changes there must be reflected here.
+targets.legacy_compound_suite(
+    name = "chromium_linux_and_gl_and_vulkan_gtests",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_chromeos_only",
+        "chromium_gtests_for_linux_and_mac_only",
+        "chromium_gtests_for_linux_only",
+        "chromium_gtests_for_win_and_linux_only",
+        "linux_flavor_specific_chromium_gtests",
+        "linux_specific_xr_gtests",
+        "gl_gtests_passthrough",
+        "gpu_fyi_vulkan_swiftshader_gtests",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests",
+        "vr_platform_specific_chromium_gtests",
+    ],
+)
+
+# gl_tests requires dedicated machines with GPUs on linux, so have a separate
+# test list with gl_tests included. This is chromium_linux_gtests + gl_gtests.
+targets.legacy_compound_suite(
+    name = "chromium_linux_and_gl_gtests",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_chromeos_only",
+        "chromium_gtests_for_linux_and_mac_only",
+        "chromium_gtests_for_linux_only",
+        "chromium_gtests_for_win_and_linux_only",
+        "linux_flavor_specific_chromium_gtests",
+        "linux_specific_xr_gtests",
+        "gl_gtests_passthrough",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests",
+        "vr_platform_specific_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_linux_blink_rel_isolated_scripts",
+    basic_suites = [
+        "chromium_webkit_isolated_scripts",
+        "linux_specific_chromium_isolated_scripts",
+        "vulkan_swiftshader_isolated_scripts",
+        "chromium_web_tests_high_dpi_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_linux_cast_audio_gtests",
+    basic_suites = [
+        "cast_audio_specific_chromium_gtests",
+        "chromium_gtests",
+        "linux_flavor_specific_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_linux_cast_video_gtests",
+    basic_suites = [
+        "cast_audio_specific_chromium_gtests",
+        "cast_video_specific_chromium_gtests",
+        "chromium_gtests",
+        "linux_flavor_specific_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_linux_dbg_isolated_scripts",
+    basic_suites = [
+        "desktop_chromium_isolated_scripts",
+        "linux_specific_chromium_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts",
+    ],
+)
+
+# When changing something here, change chromium_linux_and_gl_gtests,
+# chromium_linux_and_gl_and_vulkan_gtests, and
+# chromium_linux_rel_gtests_once in the same way.
+targets.legacy_compound_suite(
+    name = "chromium_linux_gtests",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_chromeos_only",
+        "chromium_gtests_for_linux_and_mac_only",
+        "chromium_gtests_for_linux_only",
+        "chromium_gtests_for_win_and_linux_only",
+        "linux_flavor_specific_chromium_gtests",
+        "linux_specific_xr_gtests",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests",
+        "vr_platform_specific_chromium_gtests",
+    ],
+)
+
+# TODO(crbug.com/1444855): This set should match chromium_linux_gtests,
+# except that it also runs tests that we can afford to run only once on
+# Linux machines (for now, this is just the cr23_linux_gtests).
+#
+# Delete this test suite after the ChromeRefresh2023 is fully rolled out
+# (assuming no other test suites are being run only once) and make sure
+# any bots go back to using chromium_linux_gtests.
+targets.legacy_compound_suite(
+    name = "chromium_linux_gtests_once",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_chromeos_only",
+        "chromium_gtests_for_linux_and_mac_only",
+        "chromium_gtests_for_linux_only",
+        "chromium_gtests_for_win_and_linux_only",
+        "cr23_linux_gtests",
+        "linux_flavor_specific_chromium_gtests",
+        "linux_specific_xr_gtests",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests",
+        "vr_platform_specific_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_linux_rel_isolated_scripts",
+    basic_suites = [
+        "chromedriver_py_tests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "linux_specific_chromium_isolated_scripts",
+        "mojo_python_unittests_isolated_scripts",
+        "pytype_tests",
+        "telemetry_perf_unittests_isolated_scripts",
+        "vulkan_swiftshader_isolated_scripts",
+        "chromium_web_tests_high_dpi_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_linux_rel_isolated_scripts_code_coverage",
+    basic_suites = [
+        "chromedriver_py_tests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "linux_specific_chromium_isolated_scripts",
+        "mojo_python_unittests_isolated_scripts",
+        "pytype_tests",
+        "telemetry_perf_unittests_isolated_scripts_xvfb",
+        "vulkan_swiftshader_isolated_scripts",
+        "chromium_web_tests_high_dpi_isolated_scripts",
+        "gpu_dawn_webgpu_blink_web_tests",
+    ],
+)
+
+# Like chromium_linux_rel_isolated_scripts above, but should only
+# include test suites that aren't affected by things like extra GN args
+# (e.g. is_debug) or OS versions (e.g. Mac-12 vs Mac-13). Note: use
+# chromium_linux_rel_isolated_scripts if you're setting up a new builder.
+# This group should only be used across ~3 builders.
+targets.legacy_compound_suite(
+    name = "chromium_linux_rel_isolated_scripts_once",
+    basic_suites = [
+        "chromedriver_py_tests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "desktop_once_isolated_scripts",
+        "linux_specific_chromium_isolated_scripts",
+        "mojo_python_unittests_isolated_scripts",
+        "pytype_tests",
+        "telemetry_perf_unittests_isolated_scripts",
+        "vulkan_swiftshader_isolated_scripts",
+        "chromium_web_tests_high_dpi_isolated_scripts",
+        # TODO(weizhong): Remove wptrunner steps once experimenting completes.
+        "wpt_web_tests_content_shell",
+        "wpt_web_tests_highdpi",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_mac_gtests",
+    basic_suites = [
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_mac_only",
+        "mac_specific_chromium_gtests",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests",
+    ],
+)
+
+# When changing something here, change
+# chromium_mac_gtests_no_nacl_once in the same way.
+targets.legacy_compound_suite(
+    name = "chromium_mac_gtests_no_nacl",
+    basic_suites = [
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_mac_only",
+        "mac_specific_chromium_gtests",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests_no_nacl",
+    ],
+)
+
+# TODO(crbug.com/1444855): This set should match
+# chromium_mac_gtests_no_nacl, except that it also runs tests that we can
+# only afford to run once on Mac machines (for now, this is just the
+# cr23_mac_gtests).
+#
+# Delete this test suite after the ChromeRefresh2023 is fully rolled out
+# and make sure any bots go back to using
+# chromium_mac_gtests_no_nacl_no_nocompile.
+targets.legacy_compound_suite(
+    name = "chromium_mac_gtests_no_nacl_once",
+    basic_suites = [
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "cr23_mac_gtests",
+        "mac_specific_chromium_gtests",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests_no_nacl",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_mac_rel_isolated_scripts",
+    basic_suites = [
+        "chromedriver_py_tests_isolated_scripts",
+        "components_perftests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "mac_specific_isolated_scripts",
+        "mojo_python_unittests_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_mac_rel_isolated_scripts_and_sizes",
+    basic_suites = [
+        "chrome_sizes",
+        "chromedriver_py_tests_isolated_scripts",
+        "components_perftests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "mac_specific_isolated_scripts",
+        "mojo_python_unittests_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_mac_rel_isolated_scripts_code_coverage",
+    basic_suites = [
+        # TODO(crbug.com/1399354): Enable gpu_dawn_webgpu_blink_web_tests
+    ],
+)
+
+# Like chromium_mac_rel_isolated_scripts above, but should only
+# include test suites that aren't affected by things like extra GN args
+# (e.g. is_debug) or OS versions (e.g. Mac-12 vs Mac-13). Note: use
+# chromium_mac_rel_isolated_scripts if you're setting up a new builder.
+# This group should only be used across ~3 builders.
+targets.legacy_compound_suite(
+    name = "chromium_mac_rel_isolated_scripts_once",
+    basic_suites = [
+        "chromedriver_py_tests_isolated_scripts",
+        "components_perftests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "desktop_once_isolated_scripts",
+        "mac_specific_isolated_scripts",
+        "mojo_python_unittests_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts",
+        # TODO(weizhong): Remove wptrunner steps once experimenting completes.
+        "wpt_web_tests_content_shell",
+    ],
+)
+
+# Pixel tests only enabled on Win 10. So this is
+# 'chromium_win_gtests' + 'pixel_browser_tests_gtests' +
+# 'non_android_chromium_gtests_skia_gold'. When changing
+# something here, also change chromium_win10_gtests_once in the same way.
+targets.legacy_compound_suite(
+    name = "chromium_win10_gtests",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_win_and_linux_only",
+        "cr23_pixel_browser_tests_gtests",
+        "fieldtrial_browser_tests",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests",
+        "non_android_chromium_gtests_skia_gold",
+        "pixel_browser_tests_gtests",
+        "vr_platform_specific_chromium_gtests",
+        "win_specific_chromium_gtests",
+    ],
+)
+
+# TODO(crbug.com/1444855): This set should match chromium_win10_gtests,
+# except that it also runs tests that we can afford to run only once
+# on Windows machines (for now this is just the cr23_win_gtests).
+#
+# Delete this test suite after the ChromeRefresh2023 is fully rolled out
+# and make sure any bots go back to using chromium_win10_gtests.
+targets.legacy_compound_suite(
+    name = "chromium_win10_gtests_once",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_win_and_linux_only",
+        "cr23_pixel_browser_tests_gtests",
+        "cr23_win_gtests",
+        "fieldtrial_browser_tests",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests",
+        "non_android_chromium_gtests_skia_gold",
+        "pixel_browser_tests_gtests",
+        "vr_platform_specific_chromium_gtests",
+        "win_specific_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_win_dbg_isolated_scripts",
+    basic_suites = [
+        "chromedriver_py_tests_isolated_scripts",
+        "components_perftests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "performance_smoke_test_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_win_gtests",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_win_and_linux_only",
+        "non_android_and_cast_and_chromeos_chromium_gtests",
+        "non_android_chromium_gtests",
+        "vr_platform_specific_chromium_gtests",
+        "win_specific_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_win_rel_isolated_scripts",
+    basic_suites = [
+        "chromedriver_py_tests_isolated_scripts",
+        "components_perftests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "mojo_python_unittests_isolated_scripts",
+        "telemetry_desktop_minidump_unittests_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts",
+        "win_specific_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "chromium_win_rel_isolated_scripts_code_coverage",
+    basic_suites = [
+        "gpu_dawn_webgpu_blink_web_tests",
+    ],
+)
+
+# Like chromium_win_rel_isolated_scripts above, but should only
+# include test suites that aren't affected by things like extra GN args
+# (e.g. is_debug) or OS versions (e.g. Mac-12 vs Mac-13). Note: use
+# chromium_win_rel_isolated_scripts if you're setting up a new builder.
+# This group should only be used across ~3 builders.
+targets.legacy_compound_suite(
+    name = "chromium_win_rel_isolated_scripts_once",
+    basic_suites = [
+        "chromedriver_py_tests_isolated_scripts",
+        "components_perftests_isolated_scripts",
+        "desktop_chromium_isolated_scripts",
+        "desktop_once_isolated_scripts",
+        "mojo_python_unittests_isolated_scripts",
+        "telemetry_desktop_minidump_unittests_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts",
+        "win_specific_isolated_scripts",
+        # TODO(weizhong): Remove wptrunner steps once experimenting completes.
+        "wpt_web_tests_content_shell",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "cronet_dbg_isolated_scripts",
+    basic_suites = [
+        "cronet_sizes",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "cronet_rel_isolated_scripts",
+    basic_suites = [
+        "cronet_resource_sizes",
+        "cronet_sizes",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "devtools_gtests",
+    basic_suites = [
+        "devtools_browser_tests",
+        "blink_unittests",
+    ],
+)
+
+# Runs only the accessibility tests in CI/CQ to reduce accessibility
+# failures that land.
+targets.legacy_compound_suite(
+    name = "fuchsia_accessibility_browsertests",
+    basic_suites = [
+        "fuchsia_accessibility_content_browsertests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "fuchsia_arm64_isolated_scripts",
+    basic_suites = [
+        "fuchsia_sizes_tests",
+        "gpu_angle_fuchsia_unittests_isolated_scripts",
+    ],
+)
+
+# All gtests that can be run on Fuchsia CI/CQ
+targets.legacy_compound_suite(
+    name = "fuchsia_gtests",
+    basic_suites = [
+        "fuchsia_chrome_small_gtests",
+        "fuchsia_common_gtests",
+        "fuchsia_common_gtests_with_graphical_output",
+        "web_engine_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "fuchsia_isolated_scripts",
+    basic_suites = [
+        "chromium_webkit_isolated_scripts",
+        "gpu_angle_fuchsia_unittests_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "fuchsia_web_engine_non_graphical_gtests",
+    basic_suites = [
+        "fuchsia_common_gtests",
+        "web_engine_gtests",
+    ],
+)
+
+# BEGIN composition test suites used by the GPU bots
+
+targets.legacy_compound_suite(
+    name = "gpu_angle_linux_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_webgl2_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_angle_mac_telemetry_tests",
+    basic_suites = [
+        "gpu_info_collection_telemetry_tests",
+        "gpu_webgl2_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl2_conformance_metal_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_metal_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_angle_win_intel_nvidia_telemetry_tests",
+    basic_suites = [
+        "gpu_info_collection_telemetry_tests",
+        "gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d9_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_vulkan_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_chromeos_telemetry_tests",
+    basic_suites = [
+        "gpu_webgl_conformance_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_common_android_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_validating_telemetry_tests",
+        "gpu_webgl_conformance_validating_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_common_gl_passthrough_ganesh_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_gl_passthrough_ganesh_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_common_linux_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_common_metal_passthrough_ganesh_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_metal_passthrough_ganesh_telemetry_tests",
+        "gpu_webgl_conformance_metal_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_common_win_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d11_passthrough_telemetry_tests",
+    ],
+)
+
+# Same as gpu_dawn_isolated_scripts, but with some suites removed:
+# * telemetry_gpu_unittests since those aren't built for Android
+# * SwiftShader-related tests since SwiftShader is not used on Android.
+targets.legacy_compound_suite(
+    name = "gpu_dawn_android_isolated_scripts",
+    basic_suites = [
+        "gpu_dawn_perf_smoke_isolated_scripts",
+        "gpu_dawn_webgpu_blink_web_tests",
+    ],
+)
+
+# Same as gpu_dawn_telemetry_tests, but without SwiftShader tests since
+# SwiftShader is not used on Android.
+targets.legacy_compound_suite(
+    name = "gpu_dawn_android_telemetry_tests",
+    basic_suites = [
+        "gpu_dawn_webgpu_cts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_dawn_asan_isolated_scripts",
+    basic_suites = [
+        "gpu_dawn_common_isolated_scripts",
+        "gpu_dawn_perf_smoke_isolated_scripts",
+        "gpu_dawn_webgpu_blink_web_tests",
+        "gpu_dawn_webgpu_blink_web_tests_force_swiftshader",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_dawn_integration_asan_gtests_passthrough",
+    basic_suites = [
+        "gpu_dawn_gtests",
+        "gpu_dawn_gtests_no_dxc",
+        "gpu_common_gtests_passthrough",
+    ],
+)
+
+# GPU gtests that test Dawn and integration with Chromium
+# These tests are run both on the CI and trybots which test DEPS Dawn.
+targets.legacy_compound_suite(
+    name = "gpu_dawn_integration_gtests_passthrough",
+    basic_suites = [
+        "gpu_dawn_gtests",
+        "gpu_dawn_gtests_with_validation",
+        "gpu_common_gtests_passthrough",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_dawn_integration_gtests_passthrough_win_x64",
+    basic_suites = [
+        "gpu_dawn_gtests",
+        "gpu_dawn_gtests_with_validation",
+        "gpu_dawn_gtests_no_dxc",
+        "gpu_dawn_gtests_no_dxc_with_validation",
+        "gpu_common_gtests_passthrough",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_dawn_isolated_scripts",
+    basic_suites = [
+        "gpu_dawn_common_isolated_scripts",
+        "gpu_dawn_perf_smoke_isolated_scripts",
+        "gpu_dawn_webgpu_blink_web_tests",
+        "gpu_dawn_webgpu_blink_web_tests_force_swiftshader",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_dawn_telemetry_tests",
+    basic_suites = [
+        "gpu_dawn_webgpu_cts",
+        "gpu_dawn_web_platform_webgpu_cts_force_swiftshader",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_dawn_telemetry_win_x64_tests",
+    basic_suites = [
+        "gpu_dawn_webgpu_cts",
+        "gpu_dawn_webgpu_cts_dxc",
+        "gpu_dawn_web_platform_webgpu_cts_force_swiftshader",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_dawn_tsan_gtests",
+    basic_suites = [
+        "gpu_dawn_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_desktop_mac_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_desktop_specific_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_desktop_passthrough_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_desktop_specific_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fuchsia_telemetry_tests",
+    basic_suites = [
+        "gpu_validating_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_android_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_common_gtests_validating",
+        "gpu_fyi_and_optional_non_linux_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_android_shieldtv_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_common_gtests_validating",
+        "gpu_fyi_and_optional_non_linux_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_android_webgl2_and_gold_telemetry_tests",
+    basic_suites = [
+        "gpu_validating_telemetry_tests",
+        "gpu_webgl2_conformance_gles_passthrough_telemetry_tests",
+        "gpu_webgl2_conformance_validating_telemetry_tests",
+    ],
+)
+
+# TODO(crbug.com/1080424): Merge with an existing set of tests such as
+# gpu_fyi_linux_release_gtests once all CrOS tests have been enabled.
+targets.legacy_compound_suite(
+    name = "gpu_fyi_chromeos_release_gtests",
+    basic_suites = [
+        # TODO(crbug.com/1135720): Missing cros wrapper script.
+        # "gpu_angle_unit_gtests",
+        # TODO(crbug.com/1087567, crbug.com/1087590): Enable once there are tests
+        # that actually pass.
+        "gpu_common_gtests_validating",
+        # TODO(crbug.com/1087563): Enable once tab_capture_end2end_tests passes
+        # on CrOS.
+        # "gpu_desktop_specific_gtests",
+    ],
+)
+
+# TODO(crbug.com/1080424): Merge with an existing set of tests such as
+# gpu_fyi_linux_release_telemetry_tests once all CrOS tests
+# have been enabled.
+targets.legacy_compound_suite(
+    name = "gpu_fyi_chromeos_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_mediapipe_validating_telemetry_tests",
+        "gpu_validating_telemetry_tests",
+        "gpu_webcodecs_validating_telemetry_test",
+        "gpu_webgl_conformance_validating_telemetry_tests",
+        # Large amounts of WebGL/WebGL2 tests are failing due to issues that are
+        # possibly related to other CrOS issues that are already reported.
+        # TODO(crbug.com/1080424): Try enabling these again once some of the
+        # existing CrOS WebGL issues are resolved.
+        "gpu_webgl2_conformance_gles_passthrough_telemetry_tests",
+        "gpu_webgl2_conformance_validating_telemetry_tests",
+        # "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+    ],
+)
+
+# The same as gpu_fyi_chromeos_release_telemetry_tests, but using
+# passthrough instead of validating since the Lacros bots are actually
+# Lacros-like Linux bots, and Linux uses the passthrough decoder.
+# Additionally, we use GLES instead of GL since that's what is supported.
+targets.legacy_compound_suite(
+    name = "gpu_fyi_lacros_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webcodecs_telemetry_test",
+        "gpu_webgl2_conformance_gles_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gles_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_linux_debug_gtests",
+    basic_suites = [
+        "gpu_common_gtests_passthrough",
+        "gpu_gles2_conform_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_linux_debug_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_linux_release_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_desktop_specific_gtests",
+        "gpu_gles2_conform_gtests",
+        "gpu_vulkan_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_linux_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webgl2_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+    ],
+)
+
+# TODO(jonross): remove this once Vulkan Swiftshader and Vulkan GL interop
+# paths are merged. This should mirror
+# `gpu_fyi_linux_release_telemetry_tests` but with additional
+# `gpu_skia_renderer_vulkan_passthrough_telemetry_tests`
+targets.legacy_compound_suite(
+    name = "gpu_fyi_linux_release_vulkan_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webgl2_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+        "gpu_skia_renderer_vulkan_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_mac_debug_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_fyi_and_optional_non_linux_gtests",
+        "gpu_fyi_mac_specific_gtests",
+        "gpu_gles2_conform_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_mac_nvidia_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_gl_passthrough_ganesh_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_webcodecs_telemetry_test",
+        "gpu_webgl2_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_mac_pro_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_metal_passthrough_graphite_telemetry_tests",
+        "gpu_webgl2_conformance_metal_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_metal_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_mac_release_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_desktop_specific_gtests",
+        "gpu_fyi_and_optional_non_linux_gtests",
+        "gpu_fyi_mac_specific_gtests",
+        "gpu_gles2_conform_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_mac_release_telemetry_tests",
+    basic_suites = [
+        "gpu_gl_passthrough_ganesh_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_metal_passthrough_graphite_telemetry_tests",
+        "gpu_webcodecs_telemetry_test",
+        "gpu_webgl2_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl2_conformance_metal_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_only_mac_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_gl_passthrough_ganesh_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_metal_passthrough_ganesh_telemetry_tests",
+        "gpu_metal_passthrough_graphite_telemetry_tests",
+        "gpu_webcodecs_telemetry_test",
+        "gpu_webgl2_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl2_conformance_metal_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_metal_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_win_amd_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webcodecs_telemetry_test",
+        "gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d9_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_win_debug_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d9_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_vulkan_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_win_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_default_and_optional_win_media_foundation_specific_gtests",
+        "gpu_default_and_optional_win_specific_gtests",
+        "gpu_desktop_specific_gtests",
+        "gpu_fyi_and_optional_non_linux_gtests",
+        "gpu_fyi_and_optional_win_specific_gtests",
+        "gpu_gles2_conform_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_win_intel_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webcodecs_telemetry_test",
+        "gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d9_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_vulkan_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_win_optional_isolated_scripts",
+    basic_suites = [
+        "gpu_command_buffer_perf_passthrough_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_fyi_win_release_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_webcodecs_telemetry_test",
+        "gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d11_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_d3d9_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_vulkan_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_nexus5x_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_mediapipe_validating_telemetry_tests",
+        "gpu_validating_telemetry_tests",
+        "gpu_webcodecs_validating_telemetry_test",
+        "gpu_webgl_conformance_gles_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_validating_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_nexus5x_telemetry_tests_v8",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_validating_telemetry_tests",
+        "gpu_webgl_conformance_gles_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_validating_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_pixel_4_and_6_telemetry_tests",
+    basic_suites = [
+        "gpu_common_and_optional_telemetry_tests",
+        "gpu_mediapipe_passthrough_telemetry_tests",
+        "gpu_mediapipe_validating_telemetry_tests",
+        "gpu_passthrough_telemetry_tests",
+        "gpu_validating_telemetry_tests",
+        "gpu_webcodecs_validating_telemetry_test",
+        "gpu_webgl_conformance_gles_passthrough_telemetry_tests",
+        "gpu_webgl_conformance_validating_telemetry_tests",
+        "gpu_webgl2_conformance_gles_passthrough_telemetry_tests",
+        "gpu_webgl2_conformance_validating_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_swangle_telemetry_tests",
+    basic_suites = [
+        "gpu_webgl_conformance_swangle_passthrough_telemetry_tests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "gpu_win_gtests",
+    basic_suites = [
+        "gpu_angle_unit_gtests",
+        "gpu_common_gtests_passthrough",
+        "gpu_default_and_optional_win_specific_gtests",
+        "gpu_desktop_specific_gtests",
+    ],
+)
+
+# END composition test suites used by the GPU bots
+
+# This is:
+#   linux_chromium_gtests
+#   - non_android_and_cast_and_chromeos_chromium_gtests
+#   + linux_chromeos_lacros_gtests
+#   + linux_chromeos_specific_gtests
+targets.legacy_compound_suite(
+    name = "linux_chromeos_gtests",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_chromeos_only",
+        "chromium_gtests_for_win_and_linux_only",
+        "linux_chromeos_lacros_gtests",
+        "linux_chromeos_specific_gtests",
+        "linux_flavor_specific_chromium_gtests",
+        "non_android_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "linux_chromeos_gtests_oobe",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_chromeos_only",
+        "chromium_gtests_for_win_and_linux_only",
+        "linux_chromeos_lacros_gtests",
+        "linux_chromeos_oobe_specific_tests",
+        "linux_chromeos_specific_gtests",
+        "linux_flavor_specific_chromium_gtests",
+        "non_android_chromium_gtests",
+    ],
+)
+
+# This is:
+#   linux_chromeos_gtests
+#   + 'linux_chromeos_browser_tests_require_lacros'
+targets.legacy_compound_suite(
+    name = "linux_chromeos_specific_and_lacros_dependent_gtests",
+    basic_suites = [
+        "aura_gtests",
+        "chromium_gtests",
+        "chromium_gtests_for_devices_with_graphical_output",
+        "chromium_gtests_for_linux_and_chromeos_only",
+        "chromium_gtests_for_win_and_linux_only",
+        "linux_chromeos_lacros_gtests",
+        "linux_chromeos_specific_gtests",
+        "linux_chromeos_browser_tests_require_lacros",
+        "linux_flavor_specific_chromium_gtests",
+        "non_android_chromium_gtests",
+        "pixel_experimental_browser_tests_gtests",
+        "ash_pixel_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "linux_viz_gtests",
+    basic_suites = [
+        "gpu_fyi_vulkan_swiftshader_gtests",
+    ],
+)
+
+# TODO(crbug.com/1111436): Re-enable this if/when additional capacity
+# targets.legacy_compound_suite(
+#     name = 'marshmallow_nougat_pie_isolated_scripts_with_proguard',
+#     basic_suites = [
+#         'android_isolated_scripts',
+#         'components_perftests_isolated_scripts',
+#         'telemetry_android_minidump_unittests_isolated_scripts',
+#         'telemetry_perf_unittests_isolated_scripts_android',
+#     ],
+# )
+
+targets.legacy_compound_suite(
+    name = "network_service_extra_gtests",
+    basic_suites = [
+        "network_service_fyi_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "nougat_isolated_scripts",
+    basic_suites = [
+        "android_isolated_scripts",
+        "chromium_junit_tests_scripts",
+        "components_perftests_isolated_scripts",
+        "monochrome_public_apk_checker_isolated_script",
+        "telemetry_android_minidump_unittests_isolated_scripts",
+        "telemetry_perf_unittests_isolated_scripts_android",
+    ],
+)
+
+# Rust tests run on non-cross builds.
+targets.legacy_compound_suite(
+    name = "rust_host_gtests",
+    basic_suites = [
+        "rust_common_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "webrtc_chromium_tests_with_baremetal_tests",
+    basic_suites = [
+        "webrtc_chromium_baremetal_gtests",
+        "webrtc_chromium_gtests",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "webview_bot_all_gtests",
+    basic_suites = [
+        "system_webview_shell_instrumentation_tests",
+        "webview_bot_instrumentation_test_apk_gtest",
+        "webview_bot_instrumentation_test_apk_no_field_trial_gtest",
+        "webview_bot_unittests_gtest",
+        "webview_cts_tests_gtest",
+        "webview_cts_tests_gtest_no_field_trial",
+        "webview_ui_instrumentation_tests",
+        "webview_ui_instrumentation_tests_no_field_trial",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "webview_trichrome_64_cts_gtests",
+    basic_suites = [
+        "webview_trichrome_64_cts_tests",
+        "webview_trichrome_64_cts_tests_no_field_trial",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "win_specific_isolated_scripts_and_sizes",
+    basic_suites = [
+        "chrome_sizes",
+        "win_specific_isolated_scripts",
+    ],
+)
+
+targets.legacy_compound_suite(
+    name = "wpt_web_tests_content_shell_multiple_flags",
+    basic_suites = [
+        "wpt_web_tests_content_shell",
+        "wpt_web_tests_not_site_per_process",
+        "wpt_web_tests_highdpi",
+    ],
+)
diff --git a/infra/config/targets/cros-skylab-variants.json b/infra/config/targets/cros-skylab-variants.json
index 16dfad05..0cce1d13 100644
--- a/infra/config/targets/cros-skylab-variants.json
+++ b/infra/config/targets/cros-skylab-variants.json
@@ -444,7 +444,6 @@
       "cros_model": "voxel",
       "cros_chrome_version": "119.0.6020.0",
       "cros_img": "volteer-public/R119-15623.0.0",
-      "autotest_name": "tast.lacros-from-gcs",
       "bucket": "chromiumos-image-archive",
       "dut_pool": "chromium",
       "public_builder": "cros_test_platform_public",
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json
index 2eff43b3..fb684fee 100644
--- a/infra/config/targets/lacros-version-skew-variants.json
+++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,16 +1,16 @@
 {
   "LACROS_VERSION_SKEW_CANARY": {
     "args": [
-      "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+      "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
     ],
-    "description": "Run with ash-chrome version 119.0.6029.0",
+    "description": "Run with ash-chrome version 119.0.6030.0",
     "identifier": "Lacros version skew testing ash canary",
     "swarming": {
       "cipd_packages": [
         {
           "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-          "location": "lacros_version_skew_tests_v119.0.6029.0",
-          "revision": "version:119.0.6029.0"
+          "location": "lacros_version_skew_tests_v119.0.6030.0",
+          "revision": "version:119.0.6030.0"
         }
       ]
     }
diff --git a/infra/config/targets/matrix_compound_suites.star b/infra/config/targets/matrix_compound_suites.star
new file mode 100644
index 0000000..a016229
--- /dev/null
+++ b/infra/config/targets/matrix_compound_suites.star
@@ -0,0 +1,1454 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file contains suite definitions that can be used in
+# //testing/buildbot/waterfalls.pyl and will also be usable for builders that
+# set their tests in starlark (once that is ready). The legacy_ prefix on the
+# declarations indicates the capability to be used in //testing/buildbot. Once a
+# suite is no longer needed in //testing/buildbot, targets.bundle (which does
+# not yet exist) can be used for grouping tests in a more flexible manner.
+
+load("//lib/targets.star", "targets")
+
+targets.legacy_matrix_compound_suite(
+    name = "android_11_emulator_gtests",
+    basic_suites = {
+        "android_emulator_specific_chrome_public_tests": None,
+        "android_trichrome_smoke_tests": None,
+        "android_smoke_tests": None,
+        "android_specific_chromium_gtests": None,  # Already includes gl_gtests.
+        "chromium_gtests": None,
+        "chromium_gtests_for_devices_with_graphical_output": None,
+        "linux_flavor_specific_chromium_gtests": None,
+        "system_webview_shell_instrumentation_tests": None,  # Not an experimental test
+        "webview_trichrome_cts_tests": targets.legacy_matrix_config(
+            variants = [
+                "WEBVIEW_TRICHROME_FULL_CTS_TESTS",
+                "WEBVIEW_TRICHROME_INSTANT_CTS_TESTS",
+            ],
+        ),
+        "webview_ui_instrumentation_tests": None,
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "android_12_emulator_fyi_gtests",
+    basic_suites = {
+        "oop_network_service_tests": None,
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "android_12_emulator_gtests",
+    basic_suites = {
+        "android_12_fieldtrial_webview_tests": None,
+        "android_emulator_specific_chrome_public_tests": None,
+        "android_trichrome_smoke_tests": None,
+        "android_smoke_tests": None,
+        "android_specific_chromium_gtests": None,  # Already includes gl_gtests.
+        "chrome_profile_generator_tests": None,
+        "chromium_gtests": None,
+        "chromium_gtests_for_devices_with_graphical_output": None,
+        "fieldtrial_android_tests": None,
+        "linux_flavor_specific_chromium_gtests": None,
+        "minidump_uploader_tests": None,
+        "system_webview_shell_instrumentation_tests": None,  # Not an experimental test
+        "webview_trichrome_64_cts_tests": targets.legacy_matrix_config(
+            variants = [
+                "WEBVIEW_TRICHROME_FULL_CTS_TESTS",
+                "WEBVIEW_TRICHROME_INSTANT_CTS_TESTS",
+            ],
+        ),
+        "webview_ui_instrumentation_tests": None,
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "android_12l_emulator_gtests",
+    basic_suites = {
+        "android_emulator_specific_chrome_public_tests": None,
+        "android_trichrome_smoke_tests": None,
+        "android_smoke_tests": None,
+        "android_specific_chromium_gtests": None,  # Already includes gl_gtests.
+        "chromium_gtests": None,
+        "chromium_gtests_for_devices_with_graphical_output": None,
+        "linux_flavor_specific_chromium_gtests": None,
+        "system_webview_shell_instrumentation_tests": None,  # Not an experimental test
+        "webview_ui_instrumentation_tests": None,
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "android_13_emulator_gtests",
+    basic_suites = {
+        "android_emulator_specific_chrome_public_tests": None,
+        "android_trichrome_smoke_tests": None,
+        "android_smoke_tests": None,
+        "android_specific_chromium_gtests": None,  # Already includes gl_gtests.
+        "chromium_gtests": None,
+        "chromium_gtests_for_devices_with_graphical_output": None,
+        "linux_flavor_specific_chromium_gtests": None,
+        "system_webview_shell_instrumentation_tests": None,  # Not an experimental test
+        "webview_trichrome_64_cts_tests": targets.legacy_matrix_config(
+            variants = [
+                "WEBVIEW_TRICHROME_FULL_CTS_TESTS",
+                "WEBVIEW_TRICHROME_INSTANT_CTS_TESTS",
+            ],
+        ),
+        "webview_trichrome_64_cts_tests_no_field_trial": None,
+        "webview_ui_instrumentation_tests": None,
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "android_fieldtrial_rel_webview_tests",
+    basic_suites = {
+        "fieldtrial_android_tests": None,
+        "webview_bot_instrumentation_test_apk_gtest": targets.legacy_matrix_config(
+            variants = [
+                "DISABLE_FIELD_TRIAL_CONFIG",
+                "SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR",
+                "SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR",
+            ],
+        ),
+        "webview_trichrome_64_cts_field_trial_tests": targets.legacy_matrix_config(
+            variants = [
+                "DISABLE_FIELD_TRIAL_CONFIG",
+                "SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR",
+                "SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR",
+            ],
+        ),
+        "webview_ui_instrumentation_tests": targets.legacy_matrix_config(
+            variants = [
+                "DISABLE_FIELD_TRIAL_CONFIG",
+                "SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR",
+                "SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR",
+            ],
+        ),
+        "system_webview_shell_instrumentation_tests": targets.legacy_matrix_config(
+            variants = [
+                "DISABLE_FIELD_TRIAL_CONFIG_WEBVIEW_COMMANDLINE",
+                "SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR_WEBVIEW_COMMANDLINE",
+                "SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR_WEBVIEW_COMMANDLINE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "chromeos_brya_skylab_tests",
+    basic_suites = {
+        "chromeos_chrome_all_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_BRYA_RELEASE_ASH_LKGM",
+            ],
+        ),
+        "chromeos_chrome_criticalstaging_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_BRYA_RELEASE_ASH_LKGM",
+            ],
+        ),
+        "chromeos_chrome_disabled_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_BRYA_RELEASE_ASH_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "chromeos_jacuzzi_skylab_tests",
+    basic_suites = {
+        "chromeos_chrome_all_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM",
+            ],
+        ),
+        "chromeos_chrome_criticalstaging_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM",
+            ],
+        ),
+        "chromeos_chrome_disabled_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "chromeos_octopus_skylab_tests",
+    basic_suites = {
+        "chromeos_chrome_all_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_OCTOPUS_RELEASE_CHROME_FROM_TLS_ASH_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "chromeos_trogdor_skylab_tests",
+    basic_suites = {
+        "chromeos_chrome_all_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_TROGDOR_RELEASE_ASH_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "chromeos_volteer_skylab_tests",
+    basic_suites = {
+        "chromeos_chrome_all_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_VOLTEER_RELEASE_ASH_LKGM",
+            ],
+        ),
+        "chromeos_chrome_criticalstaging_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_VOLTEER_RELEASE_ASH_LKGM",
+            ],
+        ),
+        "chromeos_chrome_disabled_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_VOLTEER_RELEASE_ASH_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "fieldtrial_ios_simulator_tests",
+    basic_suites = {
+        "ios_eg2_cq_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "disable_field_trial_config_for_earl_grey",
+            ],
+            variants = [
+                "SIM_IPAD_AIR_2_15_5",
+                "SIM_IPHONE_13_15_5",
+            ],
+        ),
+        "ios_eg2_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "disable_field_trial_config_for_earl_grey",
+            ],
+            variants = [
+                "SIM_IPAD_AIR_2_15_5",
+                "SIM_IPHONE_13_15_5",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "gpu_angle_ios_gtests",
+    basic_suites = {
+        "gpu_angle_ios_end2end_gtests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+        "gpu_angle_ios_white_box_gtests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "gpu_fyi_chromeos_release_telemetry_tests_skylab",
+    basic_suites = {
+        "gpu_common_and_optional_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_LKGM",
+            ],
+        ),
+        "gpu_mediapipe_validating_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_LKGM",
+            ],
+        ),
+        "gpu_validating_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_LKGM",
+            ],
+        ),
+        "gpu_webcodecs_validating_telemetry_test": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_LKGM",
+            ],
+        ),
+        "gpu_webgl_conformance_validating_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_LKGM",
+            ],
+        ),
+        "gpu_webgl2_conformance_gles_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_LKGM",
+            ],
+        ),
+        "gpu_webgl2_conformance_validating_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "gpu_fyi_lacros_device_release_telemetry_tests",
+    basic_suites = {
+        "gpu_pixel_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_ASH_TOT",
+            ],
+        ),
+        "gpu_webgl_conformance_gles_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_ASH_TOT",
+            ],
+        ),
+        "gpu_webgl2_conformance_gles_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_ASH_TOT",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios16_beta_simulator_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+            ],
+        ),
+        "ios_eg2_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_10TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+            ],
+        ),
+        "ios_eg2_cq_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_10TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_PRO_MAX_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+            ],
+        ),
+        "ios_crash_xcuitests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios16_sdk_simulator_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+            ],
+        ),
+        "ios_crash_xcuitests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+            ],
+        ),
+        "ios_eg2_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+            ],
+        ),
+        "ios_eg2_cq_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_SE_3RD_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios17_beta_simulator_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPHONE_SE_3RD_GEN_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_crash_xcuitests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios17_sdk_simulator_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_tests_parallel": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests_parallel": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPHONE_SE_3RD_GEN_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_asan_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_X_15_5",
+                "SIM_IPAD_AIR_2_15_5",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_X_15_5",
+                "SIM_IPAD_AIR_2_15_5",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_blink_dbg_tests",
+    basic_suites = {
+        "ios_blink_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_clang_tot_device_tests",
+    basic_suites = {
+        "clang_tot_gtests": targets.legacy_matrix_config(
+            variants = [
+                "IPHONE_7_15_4_1",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_clang_tot_sim_tests",
+    basic_suites = {
+        "clang_tot_gtests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_6S_15_5",
+            ],
+        ),
+    },
+)
+
+# This suite is a union of ios_simulator_tests and
+# ios_simulator_full_configs_tests.
+targets.legacy_matrix_compound_suite(
+    name = "ios_code_coverage_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_PLUS_16_4",
+                "SIM_IPHONE_14_PLUS_17_0",
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests_parallel": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_13_15_5",
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+                "SIM_IPAD_PRO_5TH_GEN_15_5",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_tests_parallel": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_13_15_5",
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+                "SIM_IPAD_PRO_5TH_GEN_15_5",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_13_15_5",
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPHONE_SE_3RD_GEN_15_5",
+                "SIM_IPHONE_SE_3RD_GEN_16_4",
+                "SIM_IPHONE_SE_3RD_GEN_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+                "SIM_IPAD_PRO_5TH_GEN_15_5",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_m1_simulator_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+        "ios_eg2_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_10TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_10TH_GEN_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_PRO_MAX_16_4",
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_SE_3RD_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPHONE_14_PRO_MAX_17_0",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPHONE_SE_3RD_GEN_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_simulator_cronet_tests",
+    basic_suites = {
+        "ios_cronet_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_13_15_5",
+            ],
+        ),
+    },
+)
+
+# Please also change ios_code_coverage_tests for any change in this suite.
+targets.legacy_matrix_compound_suite(
+    name = "ios_simulator_full_configs_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_PLUS_16_4",
+                "SIM_IPHONE_14_PLUS_17_0",
+            ],
+        ),
+        "ios_eg2_tests_parallel": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests_parallel": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_simulator_multi_window_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_simulator_noncq_tests",
+    basic_suites = {
+        "ios_eg2_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_13_15_5",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+                "record_failed_tests",
+            ],
+            variants = [
+                "SIM_IPHONE_13_15_5",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_SE_3RD_GEN_15_5",
+                "SIM_IPAD_AIR_5TH_GEN_15_5",
+                "SIM_IPHONE_14_PLUS_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPHONE_SE_3RD_GEN_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPHONE_14_PLUS_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+                "SIM_IPHONE_SE_3RD_GEN_17_0",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+            ],
+        ),
+        "ios_crash_xcuitests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_13_15_5",
+                "SIM_IPHONE_SE_3RD_GEN_16_4",
+                "SIM_IPHONE_SE_3RD_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+# Please also change ios_code_coverage_tests for any change in this suite.
+targets.legacy_matrix_compound_suite(
+    name = "ios_simulator_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests_parallel": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPHONE_14_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_PRO_6TH_GEN_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_PRO_6TH_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_webkit_tot_tests",
+    basic_suites = {
+        "ios_common_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_cq_tests_parallel": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_eg2_tests": targets.legacy_matrix_config(
+            mixins = [
+                "xcode_parallelization",
+            ],
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+        "ios_screen_size_dependent_tests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "ios_webrtc_fyi_tests",
+    basic_suites = {
+        "ios_remoting_fyi_unittests": targets.legacy_matrix_config(
+            variants = [
+                "SIM_IPHONE_14_16_4",
+                "SIM_IPAD_AIR_5TH_GEN_16_4",
+                "SIM_IPHONE_14_17_0",
+                "SIM_IPAD_AIR_5TH_GEN_17_0",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_amd64_generic_rel_skylab_fyi",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_OCTOPUS_PUBLIC_LKGM",
+                "CROS_EVE_PUBLIC_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_arm64_generic_rel_skylab",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_TROGDOR_PUBLIC_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_arm64_generic_rel_skylab_fyi",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_PUBLIC_LKGM",
+                "CROS_JACUZZI_CQ_PUBLIC_LKGM",
+                "CROS_TROGDOR_PUBLIC_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_arm_generic_rel_skylab",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_PUBLIC_LKGM",
+            ],
+        ),
+        "lacros_skylab_tests_with_gtests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_PUBLIC_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_arm_generic_rel_skylab_fyi",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_PUBLIC_LKGM",
+                "CROS_TROGDOR_PUBLIC_LKGM",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_device_or_vm_tests",
+    basic_suites = {
+        "chromeos_integration_tests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_AMD64_GENERIC",
+                "LACROS_EVE",
+            ],
+        ),
+        "lacros_all_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_AMD64_GENERIC",
+                "LACROS_EVE",
+            ],
+        ),
+        "lacros_cq_tast_tests_eve": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_EVE",
+            ],
+        ),
+        "lacros_device_or_vm_gtests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_AMD64_GENERIC",
+                "LACROS_EVE",
+            ],
+        ),
+        "lacros_vm_gtests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_AMD64_GENERIC",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_device_or_vm_tests_fyi",
+    basic_suites = {
+        "lacros_all_tast_tests_informational": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_AMD64_GENERIC",
+                "LACROS_EVE",
+            ],
+        ),
+        "lacros_device_or_vm_gtests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_AMD64_GENERIC",
+                "LACROS_EVE",
+            ],
+        ),
+        "lacros_fyi_tast_tests": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_AMD64_GENERIC",
+                "LACROS_EVE",
+            ],
+        ),
+    },
+)
+
+# Check go/lacros-on-skylab for details of Skylab configurations.
+targets.legacy_matrix_compound_suite(
+    name = "lacros_skylab_arm",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_JACUZZI_RELEASE_LKGM",
+                "CROS_JACUZZI_RELEASE_DEV",
+                "CROS_JACUZZI_RELEASE_BETA",
+                "CROS_JACUZZI_RELEASE_STABLE",
+            ],
+        ),
+    },
+)
+
+# Check go/lacros-on-skylab for details of Skylab configurations.
+targets.legacy_matrix_compound_suite(
+    name = "lacros_skylab_arm64",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_STRONGBAD_RELEASE_LKGM",
+            ],
+        ),
+    },
+)
+
+# Check go/lacros-on-skylab for details of Skylab configurations.
+targets.legacy_matrix_compound_suite(
+    name = "lacros_skylab_arm_fyi",
+    basic_suites = {
+        "lacros_skylab_arm_tests_fyi": targets.legacy_matrix_config(
+            variants = [
+                "CROS_HANA_RELEASE_LKGM",
+                "CROS_HANA_RELEASE_DEV",
+                "CROS_HANA_RELEASE_BETA",
+                "CROS_HANA_RELEASE_STABLE",
+                "CROS_STRONGBAD_RELEASE_LKGM",
+                "CROS_STRONGBAD_RELEASE_DEV",
+                "CROS_STRONGBAD_RELEASE_BETA",
+                "CROS_STRONGBAD_RELEASE_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_skylab_tests_amd64_generic",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_BRYA_RELEASE_LKGM",
+                "CROS_BRYA_RELEASE_DEV",
+                "CROS_BRYA_RELEASE_BETA",
+                "CROS_BRYA_RELEASE_STABLE",
+                "CROS_DEDEDE_RELEASE_LKGM",
+                "CROS_DEDEDE_RELEASE_DEV",
+                "CROS_DEDEDE_RELEASE_BETA",
+                "CROS_DEDEDE_RELEASE_STABLE",
+                "CROS_FIZZ_RELEASE_LKGM",
+                "CROS_FIZZ_RELEASE_DEV",
+                "CROS_FIZZ_RELEASE_BETA",
+                "CROS_FIZZ_RELEASE_STABLE",
+                "CROS_GUYBRUSH_RELEASE_LKGM",
+                "CROS_GUYBRUSH_RELEASE_DEV",
+                "CROS_GUYBRUSH_RELEASE_BETA",
+                "CROS_GUYBRUSH_RELEASE_STABLE",
+                "CROS_PUFF_RELEASE_LKGM",
+                "CROS_PUFF_RELEASE_DEV",
+                "CROS_PUFF_RELEASE_BETA",
+                "CROS_PUFF_RELEASE_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_skylab_tests_amd64_generic_fyi",
+    basic_suites = {
+        "lacros_skylab_amd64_fyi": targets.legacy_matrix_config(
+            variants = [
+                "CROS_OCTOPUS_RELEASE_LKGM",
+                "CROS_OCTOPUS_RELEASE_DEV",
+                "CROS_OCTOPUS_RELEASE_BETA",
+                "CROS_OCTOPUS_RELEASE_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "lacros_skylab_tests_amd64_generic_rel",
+    basic_suites = {
+        "lacros_skylab_tests": targets.legacy_matrix_config(
+            variants = [
+                "CROS_VOLTEER_PUBLIC_LKGM",
+            ],
+        ),
+    },
+)
+
+# This is:
+#   linux_chromeos_gtests
+#   - linux_chromeos_specific_gtests
+#   + linux_chromeos_lacros_gtests
+#   + linux_lacros_chrome_browsertests_version_skew
+#   + linux_lacros_specific_gtests
+targets.legacy_matrix_compound_suite(
+    name = "linux_lacros_gtests",
+    basic_suites = {
+        "aura_gtests": None,
+        "chromium_gtests": None,
+        "chromium_gtests_for_devices_with_graphical_output": None,
+        "chromium_gtests_for_linux_and_chromeos_only": None,
+        "chromium_gtests_for_win_and_linux_only": None,
+        "linux_chromeos_lacros_gtests": None,
+        "linux_flavor_specific_chromium_gtests": None,
+        "linux_lacros_specific_gtests": None,
+        "non_android_chromium_gtests": None,
+        "linux_lacros_chrome_browsertests_non_version_skew": None,
+        "linux_lacros_chrome_browsertests_version_skew": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_VERSION_SKEW_CANARY",
+                "LACROS_VERSION_SKEW_DEV",
+                "LACROS_VERSION_SKEW_BETA",
+                "LACROS_VERSION_SKEW_STABLE",
+            ],
+        ),
+        "linux_lacros_chrome_interactive_ui_tests_version_skew": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_VERSION_SKEW_CANARY",
+            ],
+        ),
+        "linux_lacros_chrome_interactive_ui_tests_version_skew_beta": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_VERSION_SKEW_BETA",
+            ],
+        ),
+        "linux_lacros_chrome_interactive_ui_tests_version_skew_dev": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_VERSION_SKEW_DEV",
+            ],
+        ),
+        "linux_lacros_chrome_interactive_ui_tests_version_skew_stable": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_VERSION_SKEW_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "linux_lacros_version_skew_tests",
+    basic_suites = {
+        "linux_lacros_chrome_interactive_ui_tests_version_skew": targets.legacy_matrix_config(
+            variants = [
+                "LACROS_VERSION_SKEW_CANARY",
+                "LACROS_VERSION_SKEW_DEV",
+                "LACROS_VERSION_SKEW_BETA",
+                "LACROS_VERSION_SKEW_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "linux_optional_gpu_tests_rel_gpu_telemetry_tests",
+    basic_suites = {
+        "gpu_common_and_optional_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "LINUX_INTEL_UHD_630_STABLE",
+                "LINUX_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_mediapipe_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "LINUX_INTEL_UHD_630_STABLE",
+                "LINUX_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_webcodecs_telemetry_test": targets.legacy_matrix_config(
+            variants = [
+                "LINUX_INTEL_UHD_630_STABLE",
+                "LINUX_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_webgl2_conformance_gl_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "LINUX_INTEL_UHD_630_STABLE",
+                "LINUX_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "LINUX_INTEL_UHD_630_STABLE",
+                "LINUX_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "linux_optional_gpu_tests_rel_gtests",
+    basic_suites = {
+        "gpu_gles2_conform_gtests": targets.legacy_matrix_config(
+            variants = [
+                "LINUX_INTEL_UHD_630_STABLE",
+                "LINUX_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "mac_optional_gpu_tests_rel_gpu_telemetry_tests",
+    basic_suites = {
+        "gpu_common_and_optional_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+                "MAC_RETINA_NVIDIA_GPU_STABLE",
+            ],
+        ),
+        "gpu_mediapipe_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+                "MAC_RETINA_NVIDIA_GPU_STABLE",
+            ],
+        ),
+        "gpu_gl_passthrough_ganesh_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+            ],
+        ),
+        "gpu_metal_passthrough_graphite_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+            ],
+        ),
+        "gpu_webcodecs_telemetry_test": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+                "MAC_RETINA_NVIDIA_GPU_STABLE",
+            ],
+        ),
+        "gpu_webgl2_conformance_metal_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+            ],
+        ),
+        "gpu_webgl_conformance_gl_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+            ],
+        ),
+        "gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "mac_optional_gpu_tests_rel_gtests",
+    basic_suites = {
+        "gpu_fyi_and_optional_non_linux_gtests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+                "MAC_RETINA_NVIDIA_GPU_STABLE",
+            ],
+        ),
+        "gpu_fyi_mac_specific_gtests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+                "MAC_RETINA_NVIDIA_GPU_STABLE",
+            ],
+        ),
+        "gpu_gles2_conform_gtests": targets.legacy_matrix_config(
+            variants = [
+                "MAC_MINI_INTEL_GPU_STABLE",
+                "MAC_RETINA_AMD_GPU_STABLE",
+                "MAC_RETINA_NVIDIA_GPU_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "model_validation_tests_full",
+    basic_suites = {
+        "model_validation_tests": targets.legacy_matrix_config(
+            variants = [
+                "MODEL_VALIDATION_BASE",
+                "MODEL_VALIDATION_TRUNK",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "model_validation_tests_trunk",
+    basic_suites = {
+        "model_validation_tests": targets.legacy_matrix_config(
+            variants = [
+                "MODEL_VALIDATION_TRUNK",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "webview_trichrome_10_cts_tests_gtest",
+    basic_suites = {
+        "webview_trichrome_cts_tests": targets.legacy_matrix_config(
+            variants = [
+                "WEBVIEW_TRICHROME_FULL_CTS_TESTS",
+                "WEBVIEW_TRICHROME_INSTANT_CTS_TESTS",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "win_optional_gpu_tests_rel_gpu_telemetry_tests",
+    basic_suites = {
+        "gpu_common_and_optional_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_mediapipe_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_webcodecs_telemetry_test": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_webgl_conformance_d3d11_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_webgl_conformance_d3d9_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_webgl_conformance_vulkan_passthrough_telemetry_tests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "win_optional_gpu_tests_rel_gtests",
+    basic_suites = {
+        "gpu_default_and_optional_win_media_foundation_specific_gtests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+            ],
+        ),
+        "gpu_default_and_optional_win_specific_gtests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_fyi_and_optional_non_linux_gtests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_fyi_and_optional_win_specific_gtests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+        "gpu_gles2_conform_gtests": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_INTEL_UHD_630_STABLE",
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+    },
+)
+
+targets.legacy_matrix_compound_suite(
+    name = "win_optional_gpu_tests_rel_isolated_scripts",
+    basic_suites = {
+        "gpu_command_buffer_perf_passthrough_isolated_scripts": targets.legacy_matrix_config(
+            variants = [
+                "WIN10_NVIDIA_GTX_1660_STABLE",
+            ],
+        ),
+    },
+)
diff --git a/infra/config/targets/variants.star b/infra/config/targets/variants.star
index 39b1f82..7ec4e276 100644
--- a/infra/config/targets/variants.star
+++ b/infra/config/targets/variants.star
@@ -141,57 +141,57 @@
 targets.variant(
     name = "SIM_IPAD_AIR_2_15_5",
     identifier = "iPad Air 2 15.5",
+    mixins = [
+        "ios_runtime_cache_15_5",
+    ],
     args = [
         "--platform",
         "iPad Air 2",
         "--version",
         "15.5",
     ],
-    mixins = [
-        "ios_runtime_cache_15_5",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPAD_AIR_5TH_GEN_15_5",
     identifier = "iPad Air (5th generation) 15.5",
+    mixins = [
+        "ios_runtime_cache_15_5",
+    ],
     args = [
         "--platform",
         "iPad Air (5th generation)",
         "--version",
         "15.5",
     ],
-    mixins = [
-        "ios_runtime_cache_15_5",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPAD_AIR_5TH_GEN_16_4",
     identifier = "iPad Air (5th generation) 16.4",
+    mixins = [
+        "ios_runtime_cache_16_4",
+    ],
     args = [
         "--platform",
         "iPad Air (5th generation)",
         "--version",
         "16.4",
     ],
-    mixins = [
-        "ios_runtime_cache_16_4",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPAD_AIR_5TH_GEN_17_0",
     identifier = "iPad Air (5th generation) 17.0",
+    mixins = [
+        "ios_runtime_cache_17_0",
+    ],
     args = [
         "--platform",
         "iPad Air (5th generation)",
         "--version",
         "17.0",
     ],
-    mixins = [
-        "ios_runtime_cache_17_0",
-    ],
 )
 
 # In Xcode 12, "iPad Pro (12.9-inch)" requires a generation suffix in
@@ -199,239 +199,239 @@
 targets.variant(
     name = "SIM_IPAD_PRO_5TH_GEN_15_5",
     identifier = "iPad Pro (12.9-inch) (5th generation) 15.5",
+    mixins = [
+        "ios_runtime_cache_15_5",
+    ],
     args = [
         "--platform",
         "iPad Pro (12.9-inch) (5th generation)",
         "--version",
         "15.5",
     ],
-    mixins = [
-        "ios_runtime_cache_15_5",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPAD_PRO_6TH_GEN_16_4",
     identifier = "iPad Pro (12.9-inch) (6th generation) 16.4",
+    mixins = [
+        "ios_runtime_cache_16_4",
+    ],
     args = [
         "--platform",
         "iPad Pro (12.9-inch) (6th generation)",
         "--version",
         "16.4",
     ],
-    mixins = [
-        "ios_runtime_cache_16_4",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPAD_PRO_6TH_GEN_17_0",
     identifier = "iPad Pro (12.9-inch) (6th generation) 17.0",
+    mixins = [
+        "ios_runtime_cache_17_0",
+    ],
     args = [
         "--platform",
         "iPad Pro (12.9-inch) (6th generation)",
         "--version",
         "17.0",
     ],
-    mixins = [
-        "ios_runtime_cache_17_0",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPAD_10TH_GEN_16_4",
     identifier = "iPad (10th generation) 16.4",
+    mixins = [
+        "ios_runtime_cache_16_4",
+    ],
     args = [
         "--platform",
         "iPad (10th generation)",
         "--version",
         "16.4",
     ],
-    mixins = [
-        "ios_runtime_cache_16_4",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPAD_10TH_GEN_17_0",
     identifier = "iPad (10th generation) 17.0",
+    mixins = [
+        "ios_runtime_cache_17_0",
+    ],
     args = [
         "--platform",
         "iPad (10th generation)",
         "--version",
         "17.0",
     ],
-    mixins = [
-        "ios_runtime_cache_17_0",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_6S_15_5",
     identifier = "iPhone 6s 15.5",
+    mixins = [
+        "ios_runtime_cache_15_5",
+    ],
     args = [
         "--platform",
         "iPhone 6s",
         "--version",
         "15.5",
     ],
-    mixins = [
-        "ios_runtime_cache_15_5",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_13_15_5",
     identifier = "iPhone 13 15.5",
+    mixins = [
+        "ios_runtime_cache_15_5",
+    ],
     args = [
         "--platform",
         "iPhone 13",
         "--version",
         "15.5",
     ],
-    mixins = [
-        "ios_runtime_cache_15_5",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_14_16_4",
     identifier = "iPhone 14 16.4",
+    mixins = [
+        "ios_runtime_cache_16_4",
+    ],
     args = [
         "--platform",
         "iPhone 14",
         "--version",
         "16.4",
     ],
-    mixins = [
-        "ios_runtime_cache_16_4",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_14_17_0",
     identifier = "iPhone 14 17.0",
+    mixins = [
+        "ios_runtime_cache_17_0",
+    ],
     args = [
         "--platform",
         "iPhone 14",
         "--version",
         "17.0",
     ],
-    mixins = [
-        "ios_runtime_cache_17_0",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_14_PLUS_16_4",
     identifier = "iPhone 14 Plus 16.4",
+    mixins = [
+        "ios_runtime_cache_16_4",
+    ],
     args = [
         "--platform",
         "iPhone 14 Plus",
         "--version",
         "16.4",
     ],
-    mixins = [
-        "ios_runtime_cache_16_4",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_14_PLUS_17_0",
     identifier = "iPhone 14 Plus 17.0",
+    mixins = [
+        "ios_runtime_cache_17_0",
+    ],
     args = [
         "--platform",
         "iPhone 14 Plus",
         "--version",
         "17.0",
     ],
-    mixins = [
-        "ios_runtime_cache_17_0",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_14_PRO_MAX_16_4",
     identifier = "iPhone 14 Pro Max 16.4",
+    mixins = [
+        "ios_runtime_cache_16_4",
+    ],
     args = [
         "--platform",
         "iPhone 14 Pro Max",
         "--version",
         "16.4",
     ],
-    mixins = [
-        "ios_runtime_cache_16_4",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_14_PRO_MAX_17_0",
     identifier = "iPhone 14 Pro Max 17.0",
+    mixins = [
+        "ios_runtime_cache_17_0",
+    ],
     args = [
         "--platform",
         "iPhone 14 Pro Max",
         "--version",
         "17.0",
     ],
-    mixins = [
-        "ios_runtime_cache_17_0",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_SE_3RD_GEN_15_5",
     identifier = "iPhone SE (3rd generation) 15.5",
+    mixins = [
+        "ios_runtime_cache_15_5",
+    ],
     args = [
         "--platform",
         "iPhone SE (3rd generation)",
         "--version",
         "15.5",
     ],
-    mixins = [
-        "ios_runtime_cache_15_5",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_SE_3RD_GEN_16_4",
     identifier = "iPhone SE (3rd generation) 16.4",
+    mixins = [
+        "ios_runtime_cache_16_4",
+    ],
     args = [
         "--platform",
         "iPhone SE (3rd generation)",
         "--version",
         "16.4",
     ],
-    mixins = [
-        "ios_runtime_cache_16_4",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_SE_3RD_GEN_17_0",
     identifier = "iPhone SE (3rd generation) 17.0",
+    mixins = [
+        "ios_runtime_cache_17_0",
+    ],
     args = [
         "--platform",
         "iPhone SE (3rd generation)",
         "--version",
         "17.0",
     ],
-    mixins = [
-        "ios_runtime_cache_17_0",
-    ],
 )
 
 targets.variant(
     name = "SIM_IPHONE_X_15_5",
     identifier = "iPhone X 15.5",
+    mixins = [
+        "ios_runtime_cache_15_5",
+    ],
     args = [
         "--platform",
         "iPhone X",
         "--version",
         "15.5",
     ],
-    mixins = [
-        "ios_runtime_cache_15_5",
-    ],
 )
 
 targets.variant(
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index f0895ae..6955a1c 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1667,6 +1667,11 @@
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(
          feature_engagement::kIPHiOSPromoPasswordManagerWidgetFeature)},
+    {"autofill-enable-virtual-cards",
+     flag_descriptions::kAutofillEnableVirtualCardsName,
+     flag_descriptions::kAutofillEnableVirtualCardsDescription,
+     flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableVirtualCards)},
 };
 
 bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index e095b59..c709d67e 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -113,6 +113,12 @@
     "When enabled, card product name (instead of issuer network) will be shown "
     "in Payments UI.";
 
+const char kAutofillEnableVirtualCardsName[] =
+    "Enable virtual card enrollment and retrieval";
+const char kAutofillEnableVirtualCardsDescription[] =
+    "When enabled, virtual card enrollment and retrieval will be available on "
+    "Bling.";
+
 const char kAutofillIOSDelayBetweenFieldsName[] = "Autofill delay";
 const char kAutofillIOSDelayBetweenFieldsDescription[] =
     "Delay between the different fields of a form being autofilled. In "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 35147d46..27cee34 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -96,6 +96,11 @@
 extern const char kAutofillEnableCardProductNameName[];
 extern const char kAutofillEnableCardProductNameDescription[];
 
+// Title and description for flag to enable virtual card enrollment and
+// retrieval.
+extern const char kAutofillEnableVirtualCardsName[];
+extern const char kAutofillEnableVirtualCardsDescription[];
+
 // Title and description for the flag to control the autofill delay.
 extern const char kAutofillIOSDelayBetweenFieldsName[];
 extern const char kAutofillIOSDelayBetweenFieldsDescription[];
diff --git a/ios/chrome/browser/ui/autofill/autofill_profile_edit_table_view_controller.mm b/ios/chrome/browser/ui/autofill/autofill_profile_edit_table_view_controller.mm
index faa13e15..ef4b1f1f 100644
--- a/ios/chrome/browser/ui/autofill/autofill_profile_edit_table_view_controller.mm
+++ b/ios/chrome/browser/ui/autofill/autofill_profile_edit_table_view_controller.mm
@@ -258,7 +258,8 @@
       [self.delegate willSelectCountryWithCurrentlySelectedCountry:
                          self.homeAddressCountry];
     } else if (itemType != AutofillProfileDetailsItemTypeFooter &&
-               itemType != AutofillProfileDetailsItemTypeError) {
+               itemType != AutofillProfileDetailsItemTypeError &&
+               [self isItemTypeTextEditCell:itemType]) {
       UITableViewCell* cell =
           [self.controller.tableView cellForRowAtIndexPath:indexPath];
       TableViewTextEditCell* textFieldCell =
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
index 3d99638..5f103be 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
@@ -70,8 +70,6 @@
   [notification_observer_ disconnect];
   [broadcaster_ removeObserver:bridge_
                    forSelector:@selector(broadcastScrollViewContentSize:)];
-  [broadcaster_ removeObserver:bridge_
-                   forSelector:@selector(broadcastContentScrollOffset:)];
   if (base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) {
     [broadcaster_ removeObserver:bridge_
                      forSelector:@selector(broadcastScrollViewSize:)];
diff --git a/ios_internal b/ios_internal
index b4ee1c0..8cb00a5 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit b4ee1c0e0af715ddf8c0bf37925f6271c4b9a288
+Subproject commit 8cb00a50524709f4aed93935c0abc0d09980bbb1
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index a22acf2..8e83362 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -953,6 +953,18 @@
              "LiveCaptionLogFlickerRate",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Use a greedy text stabilizer to reduce flickering when translating partial
+// speech recognition results.
+BASE_FEATURE(kLiveCaptionUseGreedyTextStabilizer,
+             "LiveCaptionUseGreedyTextStabilizer",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+// Use a wait-k approach to reduce flickering when translating partial speech
+// recognition results.
+BASE_FEATURE(kLiveCaptionUseWaitK,
+             "LiveCaptionUseWaitK",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Live Caption can be used in multiple languages, as opposed to just English.
 BASE_FEATURE(kLiveCaptionMultiLanguage,
              "LiveCaptionMultiLanguage",
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 2d95d0c..5071116 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -250,6 +250,8 @@
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionRightClick);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionLogFlickerRate);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionMultiLanguage);
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionUseGreedyTextStabilizer);
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionUseWaitK);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionWebAudio);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionSystemWideOnChromeOS);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveTranslate);
diff --git a/media/mojo/clients/win/media_foundation_renderer_client.cc b/media/mojo/clients/win/media_foundation_renderer_client.cc
index aa5f22f..ec05097e 100644
--- a/media/mojo/clients/win/media_foundation_renderer_client.cc
+++ b/media/mojo/clients/win/media_foundation_renderer_client.cc
@@ -100,6 +100,8 @@
   // Frame Server mode. This behavior must match the logic in
   // MediaFoundationRenderer::Initialize.
   rendering_strategy_ = kMediaFoundationClearRenderingStrategyParam.Get();
+  LogRenderingStrategy();
+
   rendering_mode_ =
       rendering_strategy_ ==
               MediaFoundationClearRenderingStrategy::kDirectComposition
@@ -688,4 +690,25 @@
   renderer_extension_->NotifyFrameReleased(token);
 }
 
+void MediaFoundationRendererClient::LogRenderingStrategy() {
+  std::string strategy;
+  switch (rendering_strategy_) {
+    case MediaFoundationClearRenderingStrategy::kDirectComposition:
+      strategy = "Direct Composition";
+      break;
+    case MediaFoundationClearRenderingStrategy::kFrameServer:
+      strategy = "Frame Server";
+      break;
+    case MediaFoundationClearRenderingStrategy::kDynamic:
+      strategy = "Dynamic";
+      break;
+    default:
+      strategy = "Unknown";
+      break;
+  }
+
+  MEDIA_LOG(INFO, media_log_)
+      << "MediaFoundationRenderingStrategy: " << strategy;
+}
+
 }  // namespace media
diff --git a/media/mojo/clients/win/media_foundation_renderer_client.h b/media/mojo/clients/win/media_foundation_renderer_client.h
index d32db7bc..93809cbe 100644
--- a/media/mojo/clients/win/media_foundation_renderer_client.h
+++ b/media/mojo/clients/win/media_foundation_renderer_client.h
@@ -146,6 +146,7 @@
   void OnOverlayStateChanged(const gpu::Mailbox& mailbox, bool promoted);
   void UpdateRenderMode();
   void OnPaintComplete(const base::UnguessableToken& token);
+  void LogRenderingStrategy();
 
   // This class is constructed on the main thread. Hence we store
   // PendingRemotes so we can bind the Remotes on the media task
diff --git a/media/video/h265_parser.cc b/media/video/h265_parser.cc
index 4ce39cd4..7871795 100644
--- a/media/video/h265_parser.cc
+++ b/media/video/h265_parser.cc
@@ -367,6 +367,7 @@
         int cpb_cnt_minus1_j = 0;
         if (!low_delay_hrd_flag_j) {
           READ_UE_OR_RETURN(&cpb_cnt_minus1_j);
+          IN_RANGE_OR_RETURN(cpb_cnt_minus1_j, 0, 31);
         }
         if (nal_hrd_parameters_present_flag) {
           // E.2.3 sub_layer_hrd_parameters()
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc
index dd8539ef..5d4bed8 100644
--- a/net/cert/cert_verify_proc_builtin.cc
+++ b/net/cert/cert_verify_proc_builtin.cc
@@ -56,8 +56,6 @@
 
 DEFINE_CERT_ERROR_ID(kPathLacksEVPolicy, "Path does not have an EV policy");
 
-const void* const kResultDebugDataKey = &kResultDebugDataKey;
-
 base::Value::Dict NetLogCertParams(const CRYPTO_BUFFER* cert_handle,
                                    const CertErrors& errors) {
   base::Value::Dict results;
@@ -636,9 +634,6 @@
                        bool checked_revocation_for_some_path,
                        CertVerifyProcTrustStore* trust_store,
                        CertVerifyResult* verify_result) {
-  // Clone debug data from the CertPathBuilder::Result into CertVerifyResult.
-  verify_result->CloneDataFrom(result);
-
   const CertPathBuilderResultPath* best_path_possibly_invalid =
       result.GetBestPathPossiblyInvalid();
 
@@ -743,7 +738,6 @@
     verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
     return ERR_CERT_AUTHORITY_INVALID;
   }
-  absl::optional<int64_t> chrome_root_store_version_opt = absl::nullopt;
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
   int64_t chrome_root_store_version =
       system_trust_store_->chrome_root_store_version();
@@ -752,14 +746,9 @@
         NetLogEventType::CERT_VERIFY_PROC_CHROME_ROOT_STORE_VERSION, [&] {
           return NetLogChromeRootStoreVersion(chrome_root_store_version);
         });
-    chrome_root_store_version_opt = chrome_root_store_version;
   }
 #endif
 
-  CertVerifyProcBuiltinResultDebugData::Create(verify_result, verification_time,
-                                               der_verification_time,
-                                               chrome_root_store_version_opt);
-
   // Parse the target certificate.
   std::shared_ptr<const ParsedCertificate> target;
   {
@@ -907,39 +896,6 @@
 
 }  // namespace
 
-CertVerifyProcBuiltinResultDebugData::CertVerifyProcBuiltinResultDebugData(
-    base::Time verification_time,
-    const der::GeneralizedTime& der_verification_time,
-    absl::optional<int64_t> chrome_root_store_version)
-    : verification_time_(verification_time),
-      der_verification_time_(der_verification_time),
-      chrome_root_store_version_(chrome_root_store_version) {}
-
-// static
-const CertVerifyProcBuiltinResultDebugData*
-CertVerifyProcBuiltinResultDebugData::Get(
-    const base::SupportsUserData* debug_data) {
-  return static_cast<CertVerifyProcBuiltinResultDebugData*>(
-      debug_data->GetUserData(kResultDebugDataKey));
-}
-
-// static
-void CertVerifyProcBuiltinResultDebugData::Create(
-    base::SupportsUserData* debug_data,
-    base::Time verification_time,
-    const der::GeneralizedTime& der_verification_time,
-    absl::optional<int64_t> chrome_root_store_version) {
-  debug_data->SetUserData(
-      kResultDebugDataKey,
-      std::make_unique<CertVerifyProcBuiltinResultDebugData>(
-          verification_time, der_verification_time, chrome_root_store_version));
-}
-
-std::unique_ptr<base::SupportsUserData::Data>
-CertVerifyProcBuiltinResultDebugData::Clone() {
-  return std::make_unique<CertVerifyProcBuiltinResultDebugData>(*this);
-}
-
 scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin(
     scoped_refptr<CertNetFetcher> net_fetcher,
     scoped_refptr<CRLSet> crl_set,
diff --git a/net/cert/cert_verify_proc_builtin.h b/net/cert/cert_verify_proc_builtin.h
index 208f560..34fd9a1 100644
--- a/net/cert/cert_verify_proc_builtin.h
+++ b/net/cert/cert_verify_proc_builtin.h
@@ -8,11 +8,8 @@
 #include <memory>
 
 #include "base/memory/scoped_refptr.h"
-#include "base/supports_user_data.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
-#include "net/der/parse_values.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace net {
 
@@ -21,38 +18,6 @@
 class CRLSet;
 class SystemTrustStore;
 
-class NET_EXPORT CertVerifyProcBuiltinResultDebugData
-    : public base::SupportsUserData::Data {
- public:
-  CertVerifyProcBuiltinResultDebugData(
-      base::Time verification_time,
-      const der::GeneralizedTime& der_verification_time,
-      absl::optional<int64_t> chrome_root_store_version);
-
-  static const CertVerifyProcBuiltinResultDebugData* Get(
-      const base::SupportsUserData* debug_data);
-  static void Create(base::SupportsUserData* debug_data,
-                     base::Time verification_time,
-                     const der::GeneralizedTime& der_verification_time,
-                     absl::optional<int64_t> chrome_root_store_version);
-
-  // base::SupportsUserData::Data implementation:
-  std::unique_ptr<Data> Clone() override;
-
-  base::Time verification_time() const { return verification_time_; }
-  const der::GeneralizedTime& der_verification_time() const {
-    return der_verification_time_;
-  }
-  absl::optional<int64_t> chrome_root_store_version() const {
-    return chrome_root_store_version_;
-  }
-
- private:
-  base::Time verification_time_;
-  der::GeneralizedTime der_verification_time_;
-  absl::optional<int64_t> chrome_root_store_version_;
-};
-
 // TODO(crbug.com/649017): This is not how other cert_verify_proc_*.h are
 // implemented -- they expose the type in the header. Use a consistent style
 // here too.
diff --git a/net/cert/cert_verify_proc_builtin_unittest.cc b/net/cert/cert_verify_proc_builtin_unittest.cc
index 336fa81b..884c324b1 100644
--- a/net/cert/cert_verify_proc_builtin_unittest.cc
+++ b/net/cert/cert_verify_proc_builtin_unittest.cc
@@ -107,7 +107,6 @@
                           /*ocsp_response=*/std::string(),
                           /*sct_list=*/std::string(), flags,
                           additional_trust_anchors, verify_result, net_log);
-  verify_result->DetachFromSequence();
   *out_source = net_log.source();
   return error;
 }
@@ -139,9 +138,8 @@
 
 class BlockingTrustStore : public TrustStore {
  public:
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override {
-    return backing_trust_store_.GetTrust(cert, debug_data);
+  CertificateTrust GetTrust(const ParsedCertificate* cert) override {
+    return backing_trust_store_.GetTrust(cert);
   }
 
   void SyncGetIssuersOf(const ParsedCertificate* cert,
@@ -185,7 +183,6 @@
               CertVerifyResult* verify_result,
               NetLogSource* out_source,
               CompletionOnceCallback callback) {
-    verify_result->DetachFromSequence();
     base::ThreadPool::PostTaskAndReplyWithResult(
         FROM_HERE,
         {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
@@ -580,39 +577,6 @@
             verify_result.verified_cert->intermediate_buffers()[0].get());
 }
 
-TEST_F(CertVerifyProcBuiltinTest, DebugData) {
-  auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
-
-  scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
-  ASSERT_TRUE(chain.get());
-
-  base::Time time = base::Time::Now();
-
-  CertVerifyResult verify_result;
-  NetLogSource verify_net_log_source;
-  TestCompletionCallback callback;
-  Verify(chain.get(), "www.example.com", /*flags=*/0,
-         /*additional_trust_anchors=*/{root->GetX509Certificate()},
-         &verify_result, &verify_net_log_source, callback.callback());
-
-  int error = callback.WaitForResult();
-  EXPECT_THAT(error, IsOk());
-
-  auto* debug_data = CertVerifyProcBuiltinResultDebugData::Get(&verify_result);
-  ASSERT_TRUE(debug_data);
-  // No delayed tasks involved, so the mock time should not have advanced.
-  EXPECT_EQ(time, debug_data->verification_time());
-
-  base::Time der_verification_time_converted_back_to_base_time;
-  EXPECT_TRUE(net::GeneralizedTimeToTime(
-      debug_data->der_verification_time(),
-      &der_verification_time_converted_back_to_base_time));
-  // GeneralizedTime only has seconds precision.
-  EXPECT_EQ(
-      0,
-      (time - der_verification_time_converted_back_to_base_time).InSeconds());
-}
-
 namespace {
 
 // Returns a TLV to use as an unknown signature algorithm when building a cert.
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 52afd421..0de216e 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -35,7 +35,6 @@
 #include "net/cert/cert_verify_result.h"
 #include "net/cert/crl_set.h"
 #include "net/cert/ev_root_ca_metadata.h"
-#include "net/cert/internal/cert_issuer_source_aia.h"
 #include "net/cert/internal/system_trust_store.h"
 #include "net/cert/ocsp_revocation_status.h"
 #include "net/cert/pem.h"
@@ -77,7 +76,6 @@
 #include "net/cert/cert_verify_proc_ios.h"
 #elif BUILDFLAG(IS_MAC)
 #include "base/mac/mac_util.h"
-#include "net/cert/internal/trust_store_mac.h"
 #endif
 
 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
@@ -1495,17 +1493,6 @@
       << "that date, please disable and file a bug "
       << "against mattm. Current time: " << base::Time::Now();
   EXPECT_TRUE(verify_result.is_issued_by_known_root);
-#if BUILDFLAG(IS_MAC)
-  if (verify_proc_type() == CERT_VERIFY_PROC_BUILTIN) {
-    auto* mac_trust_debug_info =
-        net::TrustStoreMac::ResultDebugData::Get(&verify_result);
-    ASSERT_TRUE(mac_trust_debug_info);
-    // Since this test queries the real trust store, can't know exactly
-    // what bits should be set in the trust debug info, but it should at
-    // least have something set.
-    EXPECT_NE(0, mac_trust_debug_info->combined_trust_debug_info());
-  }
-#endif
 }
 
 // This tests that on successful certificate verification,
@@ -3003,13 +2990,6 @@
   EXPECT_NE(OK, error);
 
   EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
-  if (VerifyProcTypeIsBuiltin()) {
-    const net::CertIssuerSourceAia::AiaDebugData* aia_debug_data =
-        net::CertIssuerSourceAia::AiaDebugData::Get(&verify_result);
-    ASSERT_TRUE(aia_debug_data);
-    EXPECT_EQ(0, aia_debug_data->aia_fetch_success());
-    EXPECT_EQ(1, aia_debug_data->aia_fetch_fail());
-  }
 }
 #undef MAYBE_IntermediateFromAia404
 
@@ -3065,13 +3045,6 @@
     int error = Verify(leaf.get(), kHostname, /*flags=*/0, CertificateList(),
                        &verify_result);
     EXPECT_THAT(error, IsOk());
-    if (VerifyProcTypeIsBuiltin()) {
-      const net::CertIssuerSourceAia::AiaDebugData* aia_debug_data =
-          net::CertIssuerSourceAia::AiaDebugData::Get(&verify_result);
-      ASSERT_TRUE(aia_debug_data);
-      EXPECT_EQ(1, aia_debug_data->aia_fetch_success());
-      EXPECT_EQ(0, aia_debug_data->aia_fetch_fail());
-    }
   }
 }
 
@@ -3129,13 +3102,6 @@
     EXPECT_THAT(error, IsOk());
   }
 
-  if (VerifyProcTypeIsBuiltin()) {
-    const net::CertIssuerSourceAia::AiaDebugData* aia_debug_data =
-        net::CertIssuerSourceAia::AiaDebugData::Get(&verify_result);
-    ASSERT_TRUE(aia_debug_data);
-    EXPECT_EQ(1, aia_debug_data->aia_fetch_success());
-    EXPECT_EQ(0, aia_debug_data->aia_fetch_fail());
-  }
 }
 
 // This test is the same as IntermediateFromAia200Pem, but with a different
@@ -3189,13 +3155,6 @@
   } else {
     EXPECT_THAT(error, IsOk());
   }
-  if (VerifyProcTypeIsBuiltin()) {
-    const net::CertIssuerSourceAia::AiaDebugData* aia_debug_data =
-        net::CertIssuerSourceAia::AiaDebugData::Get(&verify_result);
-    ASSERT_TRUE(aia_debug_data);
-    EXPECT_EQ(1, aia_debug_data->aia_fetch_success());
-    EXPECT_EQ(0, aia_debug_data->aia_fetch_fail());
-  }
 }
 
 // Tries verifying a certificate chain that uses a SHA1 intermediate,
@@ -3262,11 +3221,6 @@
 
     EXPECT_FALSE(verify_result.has_sha1);
     EXPECT_THAT(error, IsOk());
-    const net::CertIssuerSourceAia::AiaDebugData* aia_debug_data =
-        net::CertIssuerSourceAia::AiaDebugData::Get(&verify_result);
-    ASSERT_TRUE(aia_debug_data);
-    EXPECT_EQ(1, aia_debug_data->aia_fetch_success());
-    EXPECT_EQ(0, aia_debug_data->aia_fetch_fail());
   } else {
     EXPECT_NE(OK, error);
     if (verify_proc_type() == CERT_VERIFY_PROC_ANDROID &&
diff --git a/net/cert/cert_verify_result.cc b/net/cert/cert_verify_result.cc
index 49d205c..c45b61a0 100644
--- a/net/cert/cert_verify_result.cc
+++ b/net/cert/cert_verify_result.cc
@@ -25,26 +25,6 @@
 
 CertVerifyResult::~CertVerifyResult() = default;
 
-CertVerifyResult& CertVerifyResult::operator=(const CertVerifyResult& other) {
-  verified_cert = other.verified_cert;
-  cert_status = other.cert_status;
-  has_sha1 = other.has_sha1;
-  is_issued_by_known_root = other.is_issued_by_known_root;
-  is_issued_by_additional_trust_anchor =
-      other.is_issued_by_additional_trust_anchor;
-
-  public_key_hashes = other.public_key_hashes;
-  ocsp_result = other.ocsp_result;
-
-  scts = other.scts;
-  policy_compliance = other.policy_compliance;
-
-  ClearAllUserData();
-  CloneDataFrom(other);
-
-  return *this;
-}
-
 void CertVerifyResult::Reset() {
   verified_cert = nullptr;
   cert_status = 0;
@@ -58,8 +38,6 @@
   scts.clear();
   policy_compliance =
       ct::CTPolicyCompliance::CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE;
-
-  ClearAllUserData();
 }
 
 base::Value::Dict CertVerifyResult::NetLogParams(int net_error) const {
diff --git a/net/cert/cert_verify_result.h b/net/cert/cert_verify_result.h
index 7cdcb77f..7e743c33 100644
--- a/net/cert/cert_verify_result.h
+++ b/net/cert/cert_verify_result.h
@@ -6,7 +6,6 @@
 #define NET_CERT_CERT_VERIFY_RESULT_H_
 
 #include "base/memory/scoped_refptr.h"
-#include "base/supports_user_data.h"
 #include "base/values.h"
 #include "net/base/hash_value.h"
 #include "net/base/net_export.h"
@@ -24,20 +23,11 @@
 class X509Certificate;
 
 // The result of certificate verification.
-//
-// Additional debugging or purely informational data may be added through
-// SupportsUserData, but such data must not be used for anything that changes
-// how the results are interpreted or acted upon: any data that changes the
-// meaning of the result must be added as a member in this class, not through
-// SupportsUserData.
-// Any Data added through SupportsUserData must implement Clone().
-class NET_EXPORT CertVerifyResult : public base::SupportsUserData {
+class NET_EXPORT CertVerifyResult {
  public:
   CertVerifyResult();
   CertVerifyResult(const CertVerifyResult& other);
-  ~CertVerifyResult() override;
-
-  CertVerifyResult& operator=(const CertVerifyResult& other);
+  ~CertVerifyResult();
 
   void Reset();
 
diff --git a/net/cert/internal/cert_issuer_source_aia.cc b/net/cert/internal/cert_issuer_source_aia.cc
index 2b8b1fa..ceefa71 100644
--- a/net/cert/internal/cert_issuer_source_aia.cc
+++ b/net/cert/internal/cert_issuer_source_aia.cc
@@ -17,8 +17,6 @@
 
 namespace {
 
-const void* const kAiaDebugDataKey = &kAiaDebugDataKey;
-
 // TODO(mattm): These are arbitrary choices. Re-evaluate.
 const int kTimeoutMilliseconds = 10000;
 const int kMaxResponseBytes = 65536;
@@ -92,8 +90,7 @@
   ~AiaRequest() override;
 
   // CertIssuerSource::Request implementation.
-  void GetNext(ParsedCertificateList* issuers,
-               base::SupportsUserData* debug_data) override;
+  void GetNext(ParsedCertificateList* issuers) override;
 
   void AddCertFetcherRequest(
       std::unique_ptr<CertNetFetcher::Request> cert_fetcher_request);
@@ -109,11 +106,7 @@
 
 AiaRequest::~AiaRequest() = default;
 
-void AiaRequest::GetNext(ParsedCertificateList* out_certs,
-                         base::SupportsUserData* debug_data) {
-  CertIssuerSourceAia::AiaDebugData* aia_debug_data =
-      debug_data ? CertIssuerSourceAia::AiaDebugData::GetOrCreate(debug_data)
-                 : nullptr;
+void AiaRequest::GetNext(ParsedCertificateList* out_certs) {
   // TODO(eroman): Rather than blocking in FIFO order, select the one that
   // completes first.
   while (current_request_ < cert_fetcher_requests_.size()) {
@@ -123,14 +116,7 @@
     req->WaitForResult(&error, &bytes);
 
     if (AddCompletedFetchToResults(error, std::move(bytes), out_certs)) {
-      if (aia_debug_data) {
-        aia_debug_data->IncrementAiaFetchSuccess();
-      }
       return;
-    } else {
-      if (aia_debug_data) {
-        aia_debug_data->IncrementAiaFetchFail();
-      }
     }
   }
 }
@@ -165,31 +151,6 @@
 
 }  // namespace
 
-// static
-const CertIssuerSourceAia::AiaDebugData* CertIssuerSourceAia::AiaDebugData::Get(
-    const base::SupportsUserData* debug_data) {
-  return static_cast<AiaDebugData*>(debug_data->GetUserData(kAiaDebugDataKey));
-}
-
-// static
-CertIssuerSourceAia::AiaDebugData*
-CertIssuerSourceAia::AiaDebugData::GetOrCreate(
-    base::SupportsUserData* debug_data) {
-  AiaDebugData* data =
-      static_cast<AiaDebugData*>(debug_data->GetUserData(kAiaDebugDataKey));
-  if (!data) {
-    std::unique_ptr<AiaDebugData> new_data = std::make_unique<AiaDebugData>();
-    data = new_data.get();
-    debug_data->SetUserData(kAiaDebugDataKey, std::move(new_data));
-  }
-  return data;
-}
-
-std::unique_ptr<base::SupportsUserData::Data>
-CertIssuerSourceAia::AiaDebugData::Clone() {
-  return std::make_unique<AiaDebugData>(*this);
-}
-
 CertIssuerSourceAia::CertIssuerSourceAia(
     scoped_refptr<CertNetFetcher> cert_fetcher)
     : cert_fetcher_(std::move(cert_fetcher)) {}
diff --git a/net/cert/internal/cert_issuer_source_aia.h b/net/cert/internal/cert_issuer_source_aia.h
index 33466c6..d605007 100644
--- a/net/cert/internal/cert_issuer_source_aia.h
+++ b/net/cert/internal/cert_issuer_source_aia.h
@@ -7,7 +7,6 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/string_piece.h"
-#include "base/supports_user_data.h"
 #include "net/base/net_export.h"
 #include "net/cert/pki/cert_issuer_source.h"
 
@@ -17,25 +16,6 @@
 
 class NET_EXPORT CertIssuerSourceAia : public CertIssuerSource {
  public:
-  class NET_EXPORT AiaDebugData : public base::SupportsUserData::Data {
-   public:
-    static const AiaDebugData* Get(const base::SupportsUserData* debug_data);
-    static AiaDebugData* GetOrCreate(base::SupportsUserData* debug_data);
-
-    // base::SupportsUserData::Data implementation:
-    std::unique_ptr<Data> Clone() override;
-
-    void IncrementAiaFetchSuccess() { aia_fetch_success_++; }
-    void IncrementAiaFetchFail() { aia_fetch_fail_++; }
-
-    int aia_fetch_fail() const { return aia_fetch_fail_; }
-    int aia_fetch_success() const { return aia_fetch_success_; }
-
-   private:
-    int aia_fetch_success_ = 0;
-    int aia_fetch_fail_ = 0;
-  };
-
   // Creates CertIssuerSource that will use |cert_fetcher| to retrieve issuers
   // using AuthorityInfoAccess URIs. CertIssuerSourceAia must be created and
   // used only on a single thread, which is the thread |cert_fetcher| will be
diff --git a/net/cert/internal/cert_issuer_source_aia_unittest.cc b/net/cert/internal/cert_issuer_source_aia_unittest.cc
index 7c8dc88..21e8043ac 100644
--- a/net/cert/internal/cert_issuer_source_aia_unittest.cc
+++ b/net/cert/internal/cert_issuer_source_aia_unittest.cc
@@ -106,7 +106,7 @@
 
   // No results.
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   EXPECT_TRUE(result_certs.empty());
 }
 
@@ -143,12 +143,12 @@
   ASSERT_NE(nullptr, cert_source_request);
 
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(1u, result_certs.size());
   ASSERT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
 
   result_certs.clear();
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   EXPECT_TRUE(result_certs.empty());
 }
 
@@ -179,11 +179,11 @@
   ASSERT_NE(nullptr, cert_source_request);
 
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(1u, result_certs.size());
   ASSERT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
 
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   EXPECT_EQ(1u, result_certs.size());
 }
 
@@ -207,13 +207,13 @@
   ASSERT_NE(nullptr, cert_source_request);
 
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(1u, result_certs.size());
   EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
 
   // No more results.
   result_certs.clear();
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   EXPECT_EQ(0u, result_certs.size());
 }
 
@@ -248,18 +248,18 @@
   // GetNext() should return intermediate_cert followed by intermediate_cert2.
   // They are returned in two separate batches.
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(1u, result_certs.size());
   EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
 
   result_certs.clear();
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(1u, result_certs.size());
   EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert2->der_cert());
 
   // No more results.
   result_certs.clear();
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   EXPECT_EQ(0u, result_certs.size());
 }
 
@@ -283,7 +283,7 @@
 
   // No results.
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(0u, result_certs.size());
 }
 
@@ -308,7 +308,7 @@
 
   // No results.
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(0u, result_certs.size());
 }
 
@@ -341,13 +341,13 @@
 
   // GetNext() should return intermediate_cert2.
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(1u, result_certs.size());
   EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert2->der_cert());
 
   // No more results.
   result_certs.clear();
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   EXPECT_EQ(0u, result_certs.size());
 }
 
@@ -380,13 +380,13 @@
 
   // GetNext() should return intermediate_cert.
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(1u, result_certs.size());
   EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
 
   // No more results.
   result_certs.clear();
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   EXPECT_EQ(0u, result_certs.size());
 }
 
@@ -430,7 +430,7 @@
   // GetNext() will not get any certificates (since the first 5 fail to be
   // parsed, and the sixth URL is not attempted).
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(0u, result_certs.size());
 }
 
@@ -458,7 +458,7 @@
   ASSERT_NE(nullptr, cert_source_request);
 
   ParsedCertificateList result_certs;
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   ASSERT_EQ(2u, result_certs.size());
 
   // The fingerprint of the Google certificate used in the parsing tests.
@@ -476,7 +476,7 @@
   EXPECT_EQ(thawte_parse_fingerprint, X509Certificate::CalculateFingerprint256(
                                           result_certs[1]->cert_buffer()));
   result_certs.clear();
-  cert_source_request->GetNext(&result_certs, /*debug_data=*/nullptr);
+  cert_source_request->GetNext(&result_certs);
   EXPECT_TRUE(result_certs.empty());
 }
 
diff --git a/net/cert/internal/path_builder_trust_store_win_unittest.cc b/net/cert/internal/path_builder_trust_store_win_unittest.cc
index bee1160..acc0b868 100644
--- a/net/cert/internal/path_builder_trust_store_win_unittest.cc
+++ b/net/cert/internal/path_builder_trust_store_win_unittest.cc
@@ -77,8 +77,7 @@
 
     ~StaticAsyncRequest() override = default;
 
-    void GetNext(ParsedCertificateList* out_certs,
-                 base::SupportsUserData* debug_data) override {
+    void GetNext(ParsedCertificateList* out_certs) override {
       if (issuers_iter_ != issuers_.end())
         out_certs->push_back(std::move(*issuers_iter_++));
     }
@@ -149,26 +148,6 @@
   return ::testing::AssertionSuccess();
 }
 
-const void* kKey = &kKey;
-class TrustStoreThatStoresUserData : public TrustStore {
- public:
-  class Data : public base::SupportsUserData::Data {
-   public:
-    explicit Data(int value) : value(value) {}
-
-    int value = 0;
-  };
-
-  // TrustStore implementation:
-  void SyncGetIssuersOf(const ParsedCertificate* cert,
-                        ParsedCertificateList* issuers) override {}
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override {
-    debug_data->SetUserData(kKey, std::make_unique<Data>(1234));
-    return CertificateTrust::ForUnspecified();
-  }
-};
-
 class PathBuilderMultiRootWindowsTest : public ::testing::Test {
  public:
   PathBuilderMultiRootWindowsTest()
diff --git a/net/cert/internal/system_trust_store_nss_unittest.cc b/net/cert/internal/system_trust_store_nss_unittest.cc
index 96ae434..62a448b2 100644
--- a/net/cert/internal/system_trust_store_nss_unittest.cc
+++ b/net/cert/internal/system_trust_store_nss_unittest.cc
@@ -110,8 +110,7 @@
   ASSERT_NO_FATAL_FAILURE(ImportRootCertAsTrusted(test_nssdb_.slot()));
 
   CertificateTrust trust =
-      system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get(),
-                                                    /*debug_data=*/nullptr);
+      system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get());
   EXPECT_EQ(CertificateTrust::ForTrustAnchor()
                 .WithEnforceAnchorConstraints()
                 .WithEnforceAnchorExpiry()
@@ -130,8 +129,7 @@
   ASSERT_NO_FATAL_FAILURE(ImportRootCertAsTrusted(test_nssdb_.slot()));
 
   CertificateTrust trust =
-      system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get(),
-                                                    /*debug_data=*/nullptr);
+      system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get());
   EXPECT_EQ(CertificateTrust::ForTrustAnchor().ToDebugString(),
             trust.ToDebugString());
 }
@@ -147,8 +145,7 @@
   ASSERT_NO_FATAL_FAILURE(ImportRootCertAsTrusted(other_test_nssdb_.slot()));
 
   CertificateTrust trust =
-      system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get(),
-                                                    /*debug_data=*/nullptr);
+      system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get());
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
             trust.ToDebugString());
 }
@@ -162,8 +159,7 @@
   ASSERT_NO_FATAL_FAILURE(ImportRootCertAsTrusted(test_nssdb_.slot()));
 
   CertificateTrust trust =
-      system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get(),
-                                                    /*debug_data=*/nullptr);
+      system_trust_store->GetTrustStore()->GetTrust(parsed_root_cert_.get());
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
             trust.ToDebugString());
 }
diff --git a/net/cert/internal/system_trust_store_unittest.cc b/net/cert/internal/system_trust_store_unittest.cc
index 3a979ca..c9639a7 100644
--- a/net/cert/internal/system_trust_store_unittest.cc
+++ b/net/cert/internal/system_trust_store_unittest.cc
@@ -49,14 +49,14 @@
   // With no trust settings in the fake system trust store, the cert is trusted
   // by the test chrome root store.
   EXPECT_TRUE(system_trust_store_chrome->GetTrustStore()
-                  ->GetTrust(root.get(), /*debug_data=*/nullptr)
+                  ->GetTrust(root.get())
                   .IsTrustAnchor());
 
   // Adding a distrust entry in the fake system trust store should override the
   // trust in the chrome root store.
   test_system_trust_store_ptr->AddDistrustedCertificateForTest(root);
   EXPECT_TRUE(system_trust_store_chrome->GetTrustStore()
-                  ->GetTrust(root.get(), /*debug_data=*/nullptr)
+                  ->GetTrust(root.get())
                   .IsDistrusted());
 }
 
@@ -87,7 +87,7 @@
   // With no trust settings in the fake system trust store, the cert is trusted
   // by the test chrome root store.
   EXPECT_TRUE(system_trust_store_chrome->GetTrustStore()
-                  ->GetTrust(root.get(), /*debug_data=*/nullptr)
+                  ->GetTrust(root.get())
                   .IsTrustAnchor());
 
   // Adding the certificate to the fake system store as a trusted leaf doesn't
@@ -95,10 +95,10 @@
   test_system_trust_store_ptr->AddCertificate(
       root, CertificateTrust::ForTrustedLeaf());
   EXPECT_TRUE(system_trust_store_chrome->GetTrustStore()
-                  ->GetTrust(root.get(), /*debug_data=*/nullptr)
+                  ->GetTrust(root.get())
                   .IsTrustAnchor());
   EXPECT_FALSE(system_trust_store_chrome->GetTrustStore()
-                   ->GetTrust(root.get(), /*debug_data=*/nullptr)
+                   ->GetTrust(root.get())
                    .IsTrustLeaf());
 }
 #endif  // CHROME_ROOT_STORE_SUPPORTED
diff --git a/net/cert/internal/trust_store_android.cc b/net/cert/internal/trust_store_android.cc
index 3e0ed64..82b47b3 100644
--- a/net/cert/internal/trust_store_android.cc
+++ b/net/cert/internal/trust_store_android.cc
@@ -46,9 +46,8 @@
   }
 
   // TODO(hchao): see if we can get GetTrust marked const again
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) {
-    return trust_store_.GetTrust(cert, debug_data);
+  CertificateTrust GetTrust(const ParsedCertificate* cert) {
+    return trust_store_.GetTrust(cert);
   }
 
   int generation() { return generation_; }
@@ -115,10 +114,8 @@
   MaybeInitializeAndGetImpl()->SyncGetIssuersOf(cert, issuers);
 }
 
-CertificateTrust TrustStoreAndroid::GetTrust(
-    const ParsedCertificate* cert,
-    base::SupportsUserData* debug_data) {
-  return MaybeInitializeAndGetImpl()->GetTrust(cert, debug_data);
+CertificateTrust TrustStoreAndroid::GetTrust(const ParsedCertificate* cert) {
+  return MaybeInitializeAndGetImpl()->GetTrust(cert);
 }
 
 }  // namespace net
diff --git a/net/cert/internal/trust_store_android.h b/net/cert/internal/trust_store_android.h
index cab48a81..de922c5b 100644
--- a/net/cert/internal/trust_store_android.h
+++ b/net/cert/internal/trust_store_android.h
@@ -34,8 +34,7 @@
   // TrustStore:
   void SyncGetIssuersOf(const ParsedCertificate* cert,
                         ParsedCertificateList* issuers) override;
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override;
+  CertificateTrust GetTrust(const ParsedCertificate* cert) override;
 
   // CertDatabase::Observer:
   void OnTrustStoreChanged() override;
diff --git a/net/cert/internal/trust_store_chrome.cc b/net/cert/internal/trust_store_chrome.cc
index 4890118..a5780c23 100644
--- a/net/cert/internal/trust_store_chrome.cc
+++ b/net/cert/internal/trust_store_chrome.cc
@@ -109,10 +109,8 @@
   trust_store_.SyncGetIssuersOf(cert, issuers);
 }
 
-CertificateTrust TrustStoreChrome::GetTrust(
-    const ParsedCertificate* cert,
-    base::SupportsUserData* debug_data) {
-  return trust_store_.GetTrust(cert, debug_data);
+CertificateTrust TrustStoreChrome::GetTrust(const ParsedCertificate* cert) {
+  return trust_store_.GetTrust(cert);
 }
 
 bool TrustStoreChrome::Contains(const ParsedCertificate* cert) const {
diff --git a/net/cert/internal/trust_store_chrome.h b/net/cert/internal/trust_store_chrome.h
index ebd0deb..8f651064 100644
--- a/net/cert/internal/trust_store_chrome.h
+++ b/net/cert/internal/trust_store_chrome.h
@@ -68,8 +68,7 @@
   // TrustStore implementation:
   void SyncGetIssuersOf(const ParsedCertificate* cert,
                         ParsedCertificateList* issuers) override;
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override;
+  CertificateTrust GetTrust(const ParsedCertificate* cert) override;
 
   // Returns true if the trust store contains the given ParsedCertificate
   // (matches by DER).
diff --git a/net/cert/internal/trust_store_chrome_unittest.cc b/net/cert/internal/trust_store_chrome_unittest.cc
index c8845cd..7eebc8e 100644
--- a/net/cert/internal/trust_store_chrome_unittest.cc
+++ b/net/cert/internal/trust_store_chrome_unittest.cc
@@ -44,8 +44,7 @@
     std::shared_ptr<const ParsedCertificate> parsed =
         ToParsedCertificate(*cert);
     ASSERT_TRUE(trust_store_chrome->Contains(parsed.get()));
-    CertificateTrust trust =
-        trust_store_chrome->GetTrust(parsed.get(), /*debug_data=*/nullptr);
+    CertificateTrust trust = trust_store_chrome->GetTrust(parsed.get());
     EXPECT_EQ(CertificateTrust::ForTrustAnchor().ToDebugString(),
               trust.ToDebugString());
   }
@@ -59,8 +58,7 @@
   std::shared_ptr<const ParsedCertificate> other_parsed =
       ToParsedCertificate(*other_cert);
   ASSERT_FALSE(trust_store_chrome->Contains(other_parsed.get()));
-  CertificateTrust trust = trust_store_chrome->GetTrust(other_parsed.get(),
-                                                        /*debug_data=*/nullptr);
+  CertificateTrust trust = trust_store_chrome->GetTrust(other_parsed.get());
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
             trust.ToDebugString());
 }
diff --git a/net/cert/internal/trust_store_mac.cc b/net/cert/internal/trust_store_mac.cc
index 79d83ce..bf099d3 100644
--- a/net/cert/internal/trust_store_mac.cc
+++ b/net/cert/internal/trust_store_mac.cc
@@ -56,51 +56,17 @@
   DISTRUSTED
 };
 
-const void* kResultDebugDataKey = &kResultDebugDataKey;
-
 // Returns trust status of usage constraints dictionary |trust_dict| for a
 // certificate that |is_self_issued|.
 TrustStatus IsTrustDictionaryTrustedForPolicy(
     CFDictionaryRef trust_dict,
     bool is_self_issued,
-    const CFStringRef target_policy_oid,
-    int* debug_info) {
+    const CFStringRef target_policy_oid) {
   crypto::GetMacSecurityServicesLock().AssertAcquired();
 
   // An empty trust dict should be interpreted as
   // kSecTrustSettingsResultTrustRoot. This is handled by falling through all
   // the conditions below with the default value of |trust_settings_result|.
-  CFIndex dict_size = CFDictionaryGetCount(trust_dict);
-  if (dict_size == 0)
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_EMPTY;
-
-  CFIndex known_elements = 0;
-  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsPolicy)) {
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_CONTAINS_POLICY;
-    known_elements++;
-  }
-  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsApplication)) {
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_CONTAINS_APPLICATION;
-    known_elements++;
-  }
-  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsPolicyString)) {
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_CONTAINS_POLICY_STRING;
-    known_elements++;
-  }
-  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsKeyUsage)) {
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_CONTAINS_KEY_USAGE;
-    known_elements++;
-  }
-  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsResult)) {
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_CONTAINS_RESULT;
-    known_elements++;
-  }
-  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsAllowedError)) {
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_CONTAINS_ALLOWED_ERROR;
-    known_elements++;
-  }
-  if (known_elements != dict_size)
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_UNKNOWN_KEY;
 
   // Trust settings may be scoped to a single application, by checking that the
   // code signing identity of the current application matches the serialized
@@ -129,7 +95,6 @@
     SecPolicyRef policy_ref = base::apple::GetValueFromDictionary<SecPolicyRef>(
         trust_dict, kSecTrustSettingsPolicy);
     if (!policy_ref) {
-      *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_INVALID_POLICY_TYPE;
       return TrustStatus::UNSPECIFIED;
     }
     base::apple::ScopedCFTypeRef<CFDictionaryRef> policy_dict(
@@ -153,7 +118,6 @@
     if (!trust_settings_result_ref ||
         !CFNumberGetValue(trust_settings_result_ref, kCFNumberIntType,
                           &trust_settings_result)) {
-      *debug_info |= TrustStoreMac::TRUST_SETTINGS_DICT_INVALID_RESULT_TYPE;
       return TrustStatus::UNSPECIFIED;
     }
   }
@@ -188,14 +152,12 @@
 // that |is_self_issued| should be treated as a trust anchor.
 TrustStatus IsTrustSettingsTrustedForPolicy(CFArrayRef trust_settings,
                                             bool is_self_issued,
-                                            const CFStringRef policy_oid,
-                                            int* debug_info) {
+                                            const CFStringRef policy_oid) {
   // An empty trust settings array (that is, the trust_settings parameter
   // returns a valid but empty CFArray) means "always trust this certificate"
   // with an overall trust setting for the certificate of
   // kSecTrustSettingsResultTrustRoot.
   if (CFArrayGetCount(trust_settings) == 0) {
-    *debug_info |= TrustStoreMac::TRUST_SETTINGS_ARRAY_EMPTY;
     return is_self_issued ? TrustStatus::TRUSTED : TrustStatus::UNSPECIFIED;
   }
 
@@ -204,7 +166,7 @@
     CFDictionaryRef trust_dict = reinterpret_cast<CFDictionaryRef>(
         const_cast<void*>(CFArrayGetValueAtIndex(trust_settings, i)));
     TrustStatus trust = IsTrustDictionaryTrustedForPolicy(
-        trust_dict, is_self_issued, policy_oid, debug_info);
+        trust_dict, is_self_issued, policy_oid);
     if (trust != TrustStatus::UNSPECIFIED)
       return trust;
   }
@@ -217,8 +179,7 @@
     SecCertificateRef cert_handle,
     const bool is_self_issued,
     const CFStringRef policy_oid,
-    SecTrustSettingsDomain trust_domain,
-    int* debug_info) {
+    SecTrustSettingsDomain trust_domain) {
   crypto::GetMacSecurityServicesLock().AssertAcquired();
 
   base::apple::ScopedCFTypeRef<CFArrayRef> trust_settings;
@@ -231,19 +192,17 @@
   }
   if (err) {
     OSSTATUS_LOG(ERROR, err) << "SecTrustSettingsCopyTrustSettings error";
-    *debug_info |= TrustStoreMac::COPY_TRUST_SETTINGS_ERROR;
     return TrustStatus::UNSPECIFIED;
   }
   TrustStatus trust = IsTrustSettingsTrustedForPolicy(
-      trust_settings, is_self_issued, policy_oid, debug_info);
+      trust_settings, is_self_issued, policy_oid);
   return trust;
 }
 
 TrustStatus IsCertificateTrustedForPolicyInDomain(
     const ParsedCertificate* cert,
     const CFStringRef policy_oid,
-    SecTrustSettingsDomain trust_domain,
-    int* debug_info) {
+    SecTrustSettingsDomain trust_domain) {
   // TODO(eroman): Inefficient -- path building will convert between
   // SecCertificateRef and ParsedCertificate representations multiple times
   // (when getting the issuers, and again here).
@@ -263,14 +222,13 @@
   const bool is_self_issued =
       cert->normalized_subject() == cert->normalized_issuer();
 
-  return IsSecCertificateTrustedForPolicyInDomain(
-      cert_handle, is_self_issued, policy_oid, trust_domain, debug_info);
+  return IsSecCertificateTrustedForPolicyInDomain(cert_handle, is_self_issued,
+                                                  policy_oid, trust_domain);
 }
 
 TrustStatus IsCertificateTrustedForPolicy(const ParsedCertificate* cert,
                                           SecCertificateRef cert_handle,
-                                          const CFStringRef policy_oid,
-                                          int* debug_info) {
+                                          const CFStringRef policy_oid) {
   crypto::GetMacSecurityServicesLock().AssertAcquired();
 
   const bool is_self_issued =
@@ -290,11 +248,10 @@
         continue;
       }
       OSSTATUS_LOG(ERROR, err) << "SecTrustSettingsCopyTrustSettings error";
-      *debug_info |= TrustStoreMac::COPY_TRUST_SETTINGS_ERROR;
       continue;
     }
     TrustStatus trust = IsTrustSettingsTrustedForPolicy(
-        trust_settings, is_self_issued, policy_oid, debug_info);
+        trust_settings, is_self_issued, policy_oid);
     if (trust != TrustStatus::UNSPECIFIED)
       return trust;
   }
@@ -305,8 +262,7 @@
 }
 
 TrustStatus IsCertificateTrustedForPolicy(const ParsedCertificate* cert,
-                                          const CFStringRef policy_oid,
-                                          int* debug_info) {
+                                          const CFStringRef policy_oid) {
   base::apple::ScopedCFTypeRef<SecCertificateRef> cert_handle =
       x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(),
                                                cert->der_cert().Length());
@@ -314,18 +270,7 @@
   if (!cert_handle)
     return TrustStatus::UNSPECIFIED;
 
-  return IsCertificateTrustedForPolicy(cert, cert_handle, policy_oid,
-                                       debug_info);
-}
-
-void UpdateUserData(int debug_info,
-                    base::SupportsUserData* user_data,
-                    TrustStoreMac::TrustImplType impl_type) {
-  if (!user_data)
-    return;
-  TrustStoreMac::ResultDebugData* result_debug_data =
-      TrustStoreMac::ResultDebugData::GetOrCreate(user_data);
-  result_debug_data->UpdateTrustDebugInfo(debug_info, impl_type);
+  return IsCertificateTrustedForPolicy(cert, cert_handle, policy_oid);
 }
 
 // Returns true if |cert| would never be a valid intermediate. (A return
@@ -359,7 +304,6 @@
  public:
   struct TrustStatusDetails {
     TrustStatus trust_status = TrustStatus::UNKNOWN;
-    int debug_info = 0;
   };
 
   TrustDomainCacheFullCerts(SecTrustSettingsDomain domain,
@@ -425,21 +369,16 @@
 
   // Returns the trust status for |cert| in |domain_|.
   TrustStatus IsCertTrusted(const ParsedCertificate* cert,
-                            const SHA256HashValue& cert_hash,
-                            base::SupportsUserData* debug_data) {
+                            const SHA256HashValue& cert_hash) {
     auto cache_iter = trust_status_cache_.find(cert_hash);
     if (cache_iter == trust_status_cache_.end()) {
       // Cert does not have trust settings in this domain, return UNSPECIFIED.
-      UpdateUserData(0, debug_data,
-                     TrustStoreMac::TrustImplType::kDomainCacheFullCerts);
       return TrustStatus::UNSPECIFIED;
     }
 
     if (cache_iter->second.trust_status != TrustStatus::UNKNOWN) {
       // Cert has trust settings and trust has already been calculated, return
       // the cached value.
-      UpdateUserData(cache_iter->second.debug_info, debug_data,
-                     TrustStoreMac::TrustImplType::kDomainCacheFullCerts);
       return cache_iter->second.trust_status;
     }
 
@@ -447,11 +386,9 @@
 
     // Cert has trust settings but trust has not been calculated yet.
     // Calculate it now, insert into cache, and return.
-    TrustStatus cert_trust = IsCertificateTrustedForPolicyInDomain(
-        cert, policy_oid_, domain_, &cache_iter->second.debug_info);
+    TrustStatus cert_trust =
+        IsCertificateTrustedForPolicyInDomain(cert, policy_oid_, domain_);
     cache_iter->second.trust_status = cert_trust;
-    UpdateUserData(cache_iter->second.debug_info, debug_data,
-                   TrustStoreMac::TrustImplType::kDomainCacheFullCerts);
     return cert_trust;
   }
 
@@ -619,38 +556,6 @@
 
 }  // namespace
 
-// static
-const TrustStoreMac::ResultDebugData* TrustStoreMac::ResultDebugData::Get(
-    const base::SupportsUserData* debug_data) {
-  return static_cast<ResultDebugData*>(
-      debug_data->GetUserData(kResultDebugDataKey));
-}
-
-// static
-TrustStoreMac::ResultDebugData* TrustStoreMac::ResultDebugData::GetOrCreate(
-    base::SupportsUserData* debug_data) {
-  ResultDebugData* data = static_cast<ResultDebugData*>(
-      debug_data->GetUserData(kResultDebugDataKey));
-  if (!data) {
-    std::unique_ptr<ResultDebugData> new_data =
-        std::make_unique<ResultDebugData>();
-    data = new_data.get();
-    debug_data->SetUserData(kResultDebugDataKey, std::move(new_data));
-  }
-  return data;
-}
-
-void TrustStoreMac::ResultDebugData::UpdateTrustDebugInfo(
-    int trust_debug_info,
-    TrustImplType impl_type) {
-  combined_trust_debug_info_ |= trust_debug_info;
-  trust_impl_ = impl_type;
-}
-
-std::unique_ptr<base::SupportsUserData::Data>
-TrustStoreMac::ResultDebugData::Clone() {
-  return std::make_unique<ResultDebugData>(*this);
-}
 
 // Interface for different implementations of getting trust settings from the
 // Mac APIs. This abstraction can be removed once a single implementation has
@@ -659,8 +564,7 @@
  public:
   virtual ~TrustImpl() = default;
 
-  virtual TrustStatus IsCertTrusted(const ParsedCertificate* cert,
-                                    base::SupportsUserData* debug_data) = 0;
+  virtual TrustStatus IsCertTrusted(const ParsedCertificate* cert) = 0;
   virtual bool ImplementsSyncGetIssuersOf() const { return false; }
   virtual void SyncGetIssuersOf(const ParsedCertificate* cert,
                                 ParsedCertificateList* issuers) {}
@@ -693,8 +597,7 @@
       const TrustImplDomainCacheFullCerts&) = delete;
 
   // Returns the trust status for |cert|.
-  TrustStatus IsCertTrusted(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override {
+  TrustStatus IsCertTrusted(const ParsedCertificate* cert) override {
     SHA256HashValue cert_hash = CalculateFingerprint256(cert->der_cert());
 
     base::AutoLock lock(cache_lock_);
@@ -704,8 +607,7 @@
     // admin (and both override the system domain, but we don't check that).
     for (TrustDomainCacheFullCerts* trust_domain_cache :
          {&user_domain_cache_, &admin_domain_cache_}) {
-      TrustStatus ts =
-          trust_domain_cache->IsCertTrusted(cert, cert_hash, debug_data);
+      TrustStatus ts = trust_domain_cache->IsCertTrusted(cert, cert_hash);
       if (ts != TrustStatus::UNSPECIFIED)
         return ts;
     }
@@ -907,16 +809,9 @@
   TrustImplKeychainCacheFullCerts& operator=(
       const TrustImplKeychainCacheFullCerts&) = delete;
 
-  TrustStatus IsCertTrusted(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override {
+  TrustStatus IsCertTrusted(const ParsedCertificate* cert) override {
     SHA256HashValue cert_hash = CalculateFingerprint256(cert->der_cert());
 
-    // This impl doesn't bother to set the debug_info field since we're not
-    // using that anymore, but the related code hasn't been cleaned up yet.
-    // TODO(https://crbug.com/1379461): delete the debug user data code.
-    UpdateUserData(0, debug_data,
-                   TrustStoreMac::TrustImplType::kKeychainCacheFullCerts);
-
     base::AutoLock lock(cache_lock_);
     MaybeInitializeCache();
 
@@ -1021,9 +916,8 @@
         continue;
       }
 
-      int debug_info = 0;
       TrustStatus trust_status = IsCertificateTrustedForPolicy(
-          parsed_cert.get(), sec_cert, policy_oid_, &debug_info);
+          parsed_cert.get(), sec_cert, policy_oid_);
 
       if (trust_status == TrustStatus::TRUSTED ||
           trust_status == TrustStatus::DISTRUSTED) {
@@ -1084,14 +978,9 @@
   ~TrustImplNoCache() override = default;
 
   // Returns the trust status for |cert|.
-  TrustStatus IsCertTrusted(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override {
-    int debug_info = 0;
+  TrustStatus IsCertTrusted(const ParsedCertificate* cert) override {
     base::AutoLock lock(crypto::GetMacSecurityServicesLock());
-    TrustStatus result =
-        IsCertificateTrustedForPolicy(cert, policy_oid_, &debug_info);
-    UpdateUserData(debug_info, debug_data,
-                   TrustStoreMac::TrustImplType::kSimple);
+    TrustStatus result = IsCertificateTrustedForPolicy(cert, policy_oid_);
     return result;
   }
 
@@ -1161,9 +1050,8 @@
   }
 }
 
-CertificateTrust TrustStoreMac::GetTrust(const ParsedCertificate* cert,
-                                         base::SupportsUserData* debug_data) {
-  TrustStatus trust_status = trust_cache_->IsCertTrusted(cert, debug_data);
+CertificateTrust TrustStoreMac::GetTrust(const ParsedCertificate* cert) {
+  TrustStatus trust_status = trust_cache_->IsCertTrusted(cert);
   switch (trust_status) {
     case TrustStatus::TRUSTED: {
       CertificateTrust trust;
diff --git a/net/cert/internal/trust_store_mac.h b/net/cert/internal/trust_store_mac.h
index ac2b299..a72c324a 100644
--- a/net/cert/internal/trust_store_mac.h
+++ b/net/cert/internal/trust_store_mac.h
@@ -23,56 +23,6 @@
 // TrustStoreMac object outlives any threads accessing it.
 class NET_EXPORT TrustStoreMac : public TrustStore {
  public:
-  // Bits representing different conditions encountered while evaluating
-  // the trustSettings returned by SecTrustSettingsCopyTrustSettings.
-  enum TrustDebugInfo {
-    // The trustSettings array was empty.
-    TRUST_SETTINGS_ARRAY_EMPTY = 1 << 0,
-
-    // One of the trustSettings dictionaries was empty.
-    TRUST_SETTINGS_DICT_EMPTY = 1 << 1,
-
-    // One of the trustSettings dictionaries contained an unknown key.
-    TRUST_SETTINGS_DICT_UNKNOWN_KEY = 1 << 2,
-
-    // One of the trustSettings dictionaries contained a
-    // kSecTrustSettingsPolicy key.
-    TRUST_SETTINGS_DICT_CONTAINS_POLICY = 1 << 3,
-
-    // One of the trustSettings dictionaries contained a
-    // kSecTrustSettingsPolicy key with a value that was not a SecPolicyRef.
-    TRUST_SETTINGS_DICT_INVALID_POLICY_TYPE = 1 << 4,
-
-    // One of the trustSettings dictionaries contained a
-    // kSecTrustSettingsApplication key.
-    TRUST_SETTINGS_DICT_CONTAINS_APPLICATION = 1 << 5,
-
-    // One of the trustSettings dictionaries contained a
-    // kSecTrustSettingsPolicyString key.
-    TRUST_SETTINGS_DICT_CONTAINS_POLICY_STRING = 1 << 6,
-
-    // One of the trustSettings dictionaries contained a
-    // kSecTrustSettingsKeyUsage key.
-    TRUST_SETTINGS_DICT_CONTAINS_KEY_USAGE = 1 << 7,
-
-    // One of the trustSettings dictionaries contained a
-    // kSecTrustSettingsResult key.
-    TRUST_SETTINGS_DICT_CONTAINS_RESULT = 1 << 8,
-
-    // One of the trustSettings dictionaries contained a
-    // kSecTrustSettingsResult key with a value that was not a CFNumber or
-    // could not be represented by a signed int.
-    TRUST_SETTINGS_DICT_INVALID_RESULT_TYPE = 1 << 9,
-
-    // One of the trustSettings dictionaries contained a
-    // kSecTrustSettingsAllowedError key.
-    TRUST_SETTINGS_DICT_CONTAINS_ALLOWED_ERROR = 1 << 10,
-
-    // SecTrustSettingsCopyTrustSettings returned a value other than
-    // errSecSuccess or errSecItemNotFound.
-    COPY_TRUST_SETTINGS_ERROR = 1 << 11,
-  };
-
   // NOTE: When updating this enum, also update ParamToTrustImplType in
   // system_trust_store.cc
   enum class TrustImplType {
@@ -84,30 +34,6 @@
     kKeychainCacheFullCerts = 5,
   };
 
-  class ResultDebugData : public base::SupportsUserData::Data {
-   public:
-    static const ResultDebugData* Get(const base::SupportsUserData* debug_data);
-    static ResultDebugData* GetOrCreate(base::SupportsUserData* debug_data);
-
-    void UpdateTrustDebugInfo(int trust_debug_info, TrustImplType impl_type);
-
-    // base::SupportsUserData::Data implementation:
-    std::unique_ptr<Data> Clone() override;
-
-    // Returns a bitfield of TrustDebugInfo flags. If multiple GetTrust calls
-    // were done with the same SupportsUserData object, this will return the
-    // union of all the TrustDebugInfo flags.
-    int combined_trust_debug_info() const { return combined_trust_debug_info_; }
-
-    // Returns an enum representing which trust implementation was used.
-    TrustImplType trust_impl() const { return trust_impl_; }
-
-   private:
-    int combined_trust_debug_info_ = 0;
-
-    TrustImplType trust_impl_ = TrustImplType::kUnknown;
-  };
-
   // Creates a TrustStoreMac which will find anchors that are trusted for
   // |policy_oid|. For list of possible policy values, see:
   // https://developer.apple.com/reference/security/1667150-certificate_key_and_trust_servic/1670151-standard_policies_for_specific_c?language=objc
@@ -126,8 +52,7 @@
   // TrustStore implementation:
   void SyncGetIssuersOf(const ParsedCertificate* cert,
                         ParsedCertificateList* issuers) override;
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override;
+  CertificateTrust GetTrust(const ParsedCertificate* cert) override;
 
  private:
   class TrustImpl;
diff --git a/net/cert/internal/trust_store_mac_unittest.cc b/net/cert/internal/trust_store_mac_unittest.cc
index 09fad31..4917fb171 100644
--- a/net/cert/internal/trust_store_mac_unittest.cc
+++ b/net/cert/internal/trust_store_mac_unittest.cc
@@ -101,11 +101,6 @@
   return certs;
 }
 
-class DebugData : public base::SupportsUserData {
- public:
-  ~DebugData() override = default;
-};
-
 const char* TrustImplTypeToString(TrustStoreMac::TrustImplType t) {
   switch (t) {
     case TrustStoreMac::TrustImplType::kSimple:
@@ -261,17 +256,9 @@
   // added and trusted the test certs on the machine the test is being run on).
   for (const auto& cert :
        {a_by_b, b_by_c, b_by_f, c_by_d, c_by_e, f_by_e, d_by_d, e_by_e}) {
-    DebugData debug_data;
-    CertificateTrust trust = trust_store.GetTrust(cert.get(), &debug_data);
+    CertificateTrust trust = trust_store.GetTrust(cert.get());
     EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
               trust.ToDebugString());
-    // The combined_trust_debug_info should be 0 since no trust records
-    // should exist for these test certs.
-    const TrustStoreMac::ResultDebugData* trust_debug_data =
-        TrustStoreMac::ResultDebugData::Get(&debug_data);
-    ASSERT_TRUE(trust_debug_data);
-    EXPECT_EQ(0, trust_debug_data->combined_trust_debug_info());
-    EXPECT_EQ(trust_impl, trust_debug_data->trust_impl());
   }
 }
 
@@ -349,8 +336,7 @@
     }
 
     // Check if this cert is considered a trust anchor by TrustStoreMac.
-    DebugData debug_data;
-    CertificateTrust cert_trust = trust_store.GetTrust(cert.get(), &debug_data);
+    CertificateTrust cert_trust = trust_store.GetTrust(cert.get());
     bool is_trusted = cert_trust.IsTrustAnchor() || cert_trust.IsTrustLeaf();
     if (is_trusted) {
       EXPECT_EQ(ExpectedTrustForAnchor().ToDebugString(),
@@ -385,32 +371,12 @@
             trusted && (SecTrustGetCertificateCount(trust) == 1);
         EXPECT_EQ(expected_trust_anchor, is_trusted);
       }
-      auto* trust_debug_data = TrustStoreMac::ResultDebugData::Get(&debug_data);
-      ASSERT_TRUE(trust_debug_data);
-      if (is_trusted &&
-          trust_impl != TrustStoreMac::TrustImplType::kKeychainCacheFullCerts) {
-        // Since this test queries the real trust store, can't know exactly
-        // what bits should be set in the trust debug info, but if it's trusted
-        // it should at least have something set.
-        EXPECT_NE(0, trust_debug_data->combined_trust_debug_info());
-      }
-      // The impl that was used should be specified in the debug data.
-      EXPECT_EQ(trust_impl, trust_debug_data->trust_impl());
     }
 
     // Call GetTrust again on the same cert. This should exercise the code
     // that checks the trust value for a cert which has already been cached.
-    DebugData debug_data2;
-    CertificateTrust cert_trust2 =
-        trust_store.GetTrust(cert.get(), &debug_data2);
+    CertificateTrust cert_trust2 = trust_store.GetTrust(cert.get());
     EXPECT_EQ(cert_trust.ToDebugString(), cert_trust2.ToDebugString());
-    auto* trust_debug_data = TrustStoreMac::ResultDebugData::Get(&debug_data);
-    ASSERT_TRUE(trust_debug_data);
-    auto* trust_debug_data2 = TrustStoreMac::ResultDebugData::Get(&debug_data2);
-    ASSERT_TRUE(trust_debug_data2);
-    EXPECT_EQ(trust_debug_data->combined_trust_debug_info(),
-              trust_debug_data2->combined_trust_debug_info());
-    EXPECT_EQ(trust_debug_data->trust_impl(), trust_debug_data2->trust_impl());
   }
 
   // Since this is testing the actual platform certs and trust settings, we
diff --git a/net/cert/internal/trust_store_nss.cc b/net/cert/internal/trust_store_nss.cc
index 4d51901a..1cce5292 100644
--- a/net/cert/internal/trust_store_nss.cc
+++ b/net/cert/internal/trust_store_nss.cc
@@ -37,21 +37,6 @@
 
 namespace {
 
-const void* kResultDebugDataKey = &kResultDebugDataKey;
-
-TrustStoreNSS::ResultDebugData::SlotFilterType GetSlotFilterType(
-    const TrustStoreNSS::UserSlotTrustSetting& user_slot_trust_setting) {
-  if (absl::holds_alternative<TrustStoreNSS::UseTrustFromAllUserSlots>(
-          user_slot_trust_setting)) {
-    return TrustStoreNSS::ResultDebugData::SlotFilterType::kDontFilter;
-  }
-  if (absl::get<crypto::ScopedPK11Slot>(user_slot_trust_setting) == nullptr) {
-    return TrustStoreNSS::ResultDebugData::SlotFilterType::kDoNotAllowUserSlots;
-  }
-  return TrustStoreNSS::ResultDebugData::SlotFilterType::
-      kAllowSpecifiedUserSlot;
-}
-
 struct FreePK11GenericObjects {
   void operator()(PK11GenericObject* x) const {
     if (x) {
@@ -124,34 +109,6 @@
 
 }  // namespace
 
-TrustStoreNSS::ResultDebugData::ResultDebugData(
-    bool ignore_system_trust_settings,
-    SlotFilterType slot_filter_type)
-    : ignore_system_trust_settings_(ignore_system_trust_settings),
-      slot_filter_type_(slot_filter_type) {}
-
-// static
-const TrustStoreNSS::ResultDebugData* TrustStoreNSS::ResultDebugData::Get(
-    const base::SupportsUserData* debug_data) {
-  return static_cast<ResultDebugData*>(
-      debug_data->GetUserData(kResultDebugDataKey));
-}
-
-// static
-void TrustStoreNSS::ResultDebugData::Create(
-    bool ignore_system_trust_settings,
-    SlotFilterType slot_filter_type,
-    base::SupportsUserData* debug_data) {
-  debug_data->SetUserData(kResultDebugDataKey,
-                          std::make_unique<ResultDebugData>(
-                              ignore_system_trust_settings, slot_filter_type));
-}
-
-std::unique_ptr<base::SupportsUserData::Data>
-TrustStoreNSS::ResultDebugData::Clone() {
-  return std::make_unique<ResultDebugData>(*this);
-}
-
 TrustStoreNSS::ListCertsResult::ListCertsResult(ScopedCERTCertificate cert,
                                                 CertificateTrust trust)
     : cert(std::move(cert)), trust(trust) {}
@@ -209,14 +166,8 @@
   }
 }
 
-CertificateTrust TrustStoreNSS::GetTrust(const ParsedCertificate* cert,
-                                         base::SupportsUserData* debug_data) {
+CertificateTrust TrustStoreNSS::GetTrust(const ParsedCertificate* cert) {
   crypto::EnsureNSSInit();
-  if (debug_data) {
-    ResultDebugData::Create(ignore_system_trust_settings_,
-                            GetSlotFilterType(user_slot_trust_setting_),
-                            debug_data);
-  }
   // In theory we could also do better multi-profile slot filtering using a
   // similar approach as GetTrustIgnoringSystemTrust, however it makes the
   // logic more complicated and isn't really worth doing since we'll be
@@ -224,9 +175,9 @@
   // better for ensuring that the temporary fallback policy actually falls back
   // to the same old behavior.
   if (ignore_system_trust_settings_) {
-    return GetTrustIgnoringSystemTrust(cert, debug_data);
+    return GetTrustIgnoringSystemTrust(cert);
   } else {
-    return GetTrustWithSystemTrust(cert, debug_data);
+    return GetTrustWithSystemTrust(cert);
   }
 }
 
@@ -264,7 +215,7 @@
       continue;
     }
     results.emplace_back(x509_util::DupCERTCertificate(node->cert),
-                         GetTrustIgnoringSystemTrust(node->cert, nullptr));
+                         GetTrustIgnoringSystemTrust(node->cert));
   }
 
   return results;
@@ -279,8 +230,7 @@
 // https://searchfox.org/nss/source/lib/pk11wrap/pk11cert.c#357)
 
 CertificateTrust TrustStoreNSS::GetTrustIgnoringSystemTrust(
-    const ParsedCertificate* cert,
-    base::SupportsUserData* debug_data) const {
+    const ParsedCertificate* cert) const {
   // If trust settings are only being used from a specified slot, and that slot
   // is nullptr, there's nothing to do. This corresponds to the case where we
   // wanted to get the builtin roots from NSS still but not user-added roots.
@@ -320,12 +270,11 @@
     return CertificateTrust::ForUnspecified();
   }
 
-  return GetTrustIgnoringSystemTrust(nss_cert.get(), debug_data);
+  return GetTrustIgnoringSystemTrust(nss_cert.get());
 }
 
 CertificateTrust TrustStoreNSS::GetTrustIgnoringSystemTrust(
-    CERTCertificate* nss_cert,
-    base::SupportsUserData* debug_data) const {
+    CERTCertificate* nss_cert) const {
   // See if NSS has any trust settings for the certificate at all. If not,
   // there is no point in doing further work.
   CERTCertTrust nss_cert_trust;
@@ -515,8 +464,7 @@
 }
 
 CertificateTrust TrustStoreNSS::GetTrustWithSystemTrust(
-    const ParsedCertificate* cert,
-    base::SupportsUserData* debug_data) const {
+    const ParsedCertificate* cert) const {
   // TODO(eroman): Inefficient -- path building will convert between
   // CERTCertificate and ParsedCertificate representations multiple times
   // (when getting the issuers, and again here).
diff --git a/net/cert/internal/trust_store_nss.h b/net/cert/internal/trust_store_nss.h
index 0582d8a..5e7c57f 100644
--- a/net/cert/internal/trust_store_nss.h
+++ b/net/cert/internal/trust_store_nss.h
@@ -29,36 +29,6 @@
   using UserSlotTrustSetting =
       absl::variant<UseTrustFromAllUserSlots, crypto::ScopedPK11Slot>;
 
-  class ResultDebugData : public base::SupportsUserData::Data {
-   public:
-    enum class SlotFilterType {
-      kDontFilter,
-      kDoNotAllowUserSlots,
-      kAllowSpecifiedUserSlot
-    };
-
-    explicit ResultDebugData(bool ignore_system_trust_settings,
-                             SlotFilterType slot_filter_type);
-
-    static const ResultDebugData* Get(const base::SupportsUserData* debug_data);
-    static void Create(bool ignore_system_trust_settings,
-                       SlotFilterType slot_filter_type,
-                       base::SupportsUserData* debug_data);
-
-    // base::SupportsUserData::Data implementation:
-    std::unique_ptr<Data> Clone() override;
-
-    bool ignore_system_trust_settings() const {
-      return ignore_system_trust_settings_;
-    }
-
-    SlotFilterType slot_filter_type() const { return slot_filter_type_; }
-
-   private:
-    const bool ignore_system_trust_settings_;
-    const SlotFilterType slot_filter_type_;
-  };
-
   // Creates a TrustStoreNSS which will find anchors that are trusted for
   // SSL server auth.
   //
@@ -83,8 +53,7 @@
                         ParsedCertificateList* issuers) override;
 
   // TrustStore implementation:
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override;
+  CertificateTrust GetTrust(const ParsedCertificate* cert) override;
 
   struct ListCertsResult {
     ListCertsResult(ScopedCERTCertificate cert, CertificateTrust trust);
@@ -102,16 +71,11 @@
   CertificateTrust GetTrustForNSSTrust(const CERTCertTrust& trust) const;
 
   CertificateTrust GetTrustIgnoringSystemTrust(
-      const ParsedCertificate* cert,
-      base::SupportsUserData* debug_data) const;
+      const ParsedCertificate* cert) const;
 
-  CertificateTrust GetTrustIgnoringSystemTrust(
-      CERTCertificate* nss_cert,
-      base::SupportsUserData* debug_data) const;
+  CertificateTrust GetTrustIgnoringSystemTrust(CERTCertificate* nss_cert) const;
 
-  CertificateTrust GetTrustWithSystemTrust(
-      const ParsedCertificate* cert,
-      base::SupportsUserData* debug_data) const;
+  CertificateTrust GetTrustWithSystemTrust(const ParsedCertificate* cert) const;
 
   // |ignore_system_certs_trust_settings_| specifies if the system trust
   // settings should be considered when determining a cert's trustworthiness.
diff --git a/net/cert/internal/trust_store_nss_unittest.cc b/net/cert/internal/trust_store_nss_unittest.cc
index c4b192e..78fe4b9 100644
--- a/net/cert/internal/trust_store_nss_unittest.cc
+++ b/net/cert/internal/trust_store_nss_unittest.cc
@@ -13,7 +13,6 @@
 
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/supports_user_data.h"
 #include "base/test/scoped_feature_list.h"
 #include "crypto/scoped_test_nss_db.h"
 #include "net/base/features.h"
@@ -363,8 +362,7 @@
                 CertificateTrust expected_trust) {
     bool success = true;
     for (const std::shared_ptr<const ParsedCertificate>& cert : certs) {
-      CertificateTrust trust =
-          trust_store_nss_->GetTrust(cert.get(), /*debug_data=*/nullptr);
+      CertificateTrust trust = trust_store_nss_->GetTrust(cert.get());
       std::string trust_string = trust.ToDebugString();
       std::string expected_trust_string = expected_trust.ToDebugString();
       if (trust_string != expected_trust_string) {
@@ -398,11 +396,11 @@
 
 // Specifies which kind of per-slot filtering the TrustStoreNSS is supposed to
 // perform in the parametrized TrustStoreNSSTestWithSlotFilterType.
-// TODO(https://crbug.com/1412591): The SlotFilterType enum is shared with
-// TrustStoreNSS::ResultDebugData::SlotFilterType for convenience. Once the old
-// code path and trial code is cleaned up, the type definition can be moved
-// back to here.
-using SlotFilterType = TrustStoreNSS::ResultDebugData::SlotFilterType;
+enum class SlotFilterType {
+  kDontFilter,
+  kDoNotAllowUserSlots,
+  kAllowSpecifiedUserSlot
+};
 
 std::string SlotFilterTypeToString(SlotFilterType slot_filter_type) {
   switch (slot_filter_type) {
@@ -448,23 +446,6 @@
   }
 };
 
-class DebugData : public base::SupportsUserData {
- public:
-  ~DebugData() override = default;
-};
-
-TEST_P(TrustStoreNSSTestWithSlotFilterType, DebugData) {
-  DebugData debug_data;
-  trust_store_nss_->GetTrust(target_.get(), &debug_data);
-  const TrustStoreNSS::ResultDebugData* trust_debug_data =
-      TrustStoreNSS::ResultDebugData::Get(&debug_data);
-  ASSERT_TRUE(trust_debug_data);
-  EXPECT_EQ(system_trust_setting() ==
-                TrustStoreNSS::SystemTrustSetting::kIgnoreSystemTrust,
-            trust_debug_data->ignore_system_trust_settings());
-  EXPECT_EQ(slot_filter_type(), trust_debug_data->slot_filter_type());
-}
-
 // Without adding any certs to the NSS DB, should get no anchor results for
 // any of the test certs.
 TEST_P(TrustStoreNSSTestWithSlotFilterType, CertsNotPresent) {
diff --git a/net/cert/internal/trust_store_win.cc b/net/cert/internal/trust_store_win.cc
index ab059b7..3bdfc1b0 100644
--- a/net/cert/internal/trust_store_win.cc
+++ b/net/cert/internal/trust_store_win.cc
@@ -284,8 +284,7 @@
     }
   }
 
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) {
+  CertificateTrust GetTrust(const ParsedCertificate* cert) {
     if (!root_cert_store_.get() || !intermediate_cert_store_.get() ||
         !trusted_people_cert_store_.get() || !all_certs_store_.get() ||
         !disallowed_cert_store_.get()) {
@@ -455,9 +454,8 @@
 // If a certificate is found multiple times in the ROOT store, it is trusted
 // for TLS server auth if any instance of the certificate found
 // is usable for TLS server auth.
-CertificateTrust TrustStoreWin::GetTrust(const ParsedCertificate* cert,
-                                         base::SupportsUserData* debug_data) {
-  return MaybeInitializeAndGetImpl()->GetTrust(cert, debug_data);
+CertificateTrust TrustStoreWin::GetTrust(const ParsedCertificate* cert) {
+  return MaybeInitializeAndGetImpl()->GetTrust(cert);
 }
 
 }  // namespace net
diff --git a/net/cert/internal/trust_store_win.h b/net/cert/internal/trust_store_win.h
index 9e4adce..6f85c2c 100644
--- a/net/cert/internal/trust_store_win.h
+++ b/net/cert/internal/trust_store_win.h
@@ -76,8 +76,7 @@
   void SyncGetIssuersOf(const ParsedCertificate* cert,
                         ParsedCertificateList* issuers) override;
 
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override;
+  CertificateTrust GetTrust(const ParsedCertificate* cert) override;
 
  private:
   // Inner Impl class for use in initializing stores.
diff --git a/net/cert/internal/trust_store_win_unittest.cc b/net/cert/internal/trust_store_win_unittest.cc
index 284cfcd..f592a574 100644
--- a/net/cert/internal/trust_store_win_unittest.cc
+++ b/net/cert/internal/trust_store_win_unittest.cc
@@ -168,7 +168,7 @@
       TrustStoreWin::CreateForTesting(
           TrustStoreWin::CertStores::CreateNullStoresForTesting());
   ASSERT_TRUE(trust_store_win);
-  CertificateTrust trust = trust_store_win->GetTrust(d_by_d_.get(), nullptr);
+  CertificateTrust trust = trust_store_win->GetTrust(d_by_d_.get());
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
             trust.ToDebugString());
 }
@@ -183,23 +183,23 @@
 
   // Explicitly trusted root should be trusted.
   EXPECT_EQ(ExpectedTrustForAnchor().ToDebugString(),
-            trust_store_win->GetTrust(d_by_d_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(d_by_d_.get()).ToDebugString());
 
   // Explicitly trusted peer should be trusted.
   // (Although it wouldn't actually verify since it's not self-signed but has
   // require_leaf_selfsigned set. That doesn't matter for the purposes of these
   // tests.)
   EXPECT_EQ(ExpectedTrustForPeer().ToDebugString(),
-            trust_store_win->GetTrust(a_by_b_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(a_by_b_.get()).ToDebugString());
 
   // Intermediate for path building should not be trusted.
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
-            trust_store_win->GetTrust(c_by_d_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(c_by_d_.get()).ToDebugString());
 
   // Unknown roots should not be trusted (e.g. just because they're
   // self-signed doesn't make them a root)
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
-            trust_store_win->GetTrust(e_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(e_by_e_.get()).ToDebugString());
 }
 
 // This test has a special TrustStoreWin setup with restricted EKU usages.
@@ -226,25 +226,25 @@
   // Root cert with EKU szOID_PKIX_KP_SERVER_AUTH usage set should be
   // trusted.
   EXPECT_EQ(ExpectedTrustForAnchor().ToDebugString(),
-            trust_store_win->GetTrust(d_by_d_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(d_by_d_.get()).ToDebugString());
 
   // Root cert with EKU szOID_ANY_ENHANCED_KEY_USAGE usage set should be
   // trusted.
   EXPECT_EQ(ExpectedTrustForAnchor().ToDebugString(),
-            trust_store_win->GetTrust(c_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(c_by_e_.get()).ToDebugString());
 
   // Root cert with EKU szOID_PKIX_KP_CLIENT_AUTH does not allow usage of
   // cert for server auth, return UNSPECIFIED.
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
-            trust_store_win->GetTrust(e_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(e_by_e_.get()).ToDebugString());
 
   // Root cert with no EKU usages, return UNSPECIFIED.
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
-            trust_store_win->GetTrust(c_by_d_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(c_by_d_.get()).ToDebugString());
 
   // Unknown cert has unspecified trust.
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
-            trust_store_win->GetTrust(f_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(f_by_e_.get()).ToDebugString());
 }
 
 // Same as GetTrustRestrictedEKU but for the Trusted People store.
@@ -264,25 +264,25 @@
   // TrustedPeople cert with EKU szOID_PKIX_KP_SERVER_AUTH usage set should be
   // trusted.
   EXPECT_EQ(ExpectedTrustForPeer().ToDebugString(),
-            trust_store_win->GetTrust(d_by_d_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(d_by_d_.get()).ToDebugString());
 
   // TrustedPeople cert with EKU szOID_ANY_ENHANCED_KEY_USAGE usage set should
   // be trusted.
   EXPECT_EQ(ExpectedTrustForPeer().ToDebugString(),
-            trust_store_win->GetTrust(c_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(c_by_e_.get()).ToDebugString());
 
   // TrustedPeople cert with EKU szOID_PKIX_KP_CLIENT_AUTH does not allow usage
   // of cert for server auth, return UNSPECIFIED.
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
-            trust_store_win->GetTrust(e_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(e_by_e_.get()).ToDebugString());
 
   // TrustedPeople cert with no EKU usages, return UNSPECIFIED.
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
-            trust_store_win->GetTrust(c_by_d_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(c_by_d_.get()).ToDebugString());
 
   // Unknown cert has unspecified trust.
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
-            trust_store_win->GetTrust(f_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(f_by_e_.get()).ToDebugString());
 }
 
 // If duplicate certs are added to the root store with different EKU usages,
@@ -305,7 +305,7 @@
 
   // One copy of the Root cert is trusted for TLS Server Auth.
   EXPECT_EQ(ExpectedTrustForAnchor().ToDebugString(),
-            trust_store_win->GetTrust(d_by_d_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(d_by_d_.get()).ToDebugString());
 }
 
 // Test that disallowed certs will be distrusted regardless of EKU settings.
@@ -324,18 +324,18 @@
 
   // E-by-E is in both root and distrusted store. Distrust takes precedence.
   EXPECT_EQ(CertificateTrust::ForDistrusted().ToDebugString(),
-            trust_store_win->GetTrust(e_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(e_by_e_.get()).ToDebugString());
 
   // F-by-E is in both trusted people and distrusted store. Distrust takes
   // precedence.
   EXPECT_EQ(CertificateTrust::ForDistrusted().ToDebugString(),
-            trust_store_win->GetTrust(f_by_e_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(f_by_e_.get()).ToDebugString());
 
   // D-by-D is in root and in distrusted but without szOID_PKIX_KP_SERVER_AUTH
   // set. It should still be distrusted since the EKU settings aren't checked
   // on distrust.
   EXPECT_EQ(CertificateTrust::ForDistrusted().ToDebugString(),
-            trust_store_win->GetTrust(d_by_d_.get(), nullptr).ToDebugString());
+            trust_store_win->GetTrust(d_by_d_.get()).ToDebugString());
 }
 
 MATCHER_P(ParsedCertEq, expected_cert, "") {
diff --git a/net/cert/multi_threaded_cert_verifier.cc b/net/cert/multi_threaded_cert_verifier.cc
index 2cae6f1..056fc35c 100644
--- a/net/cert/multi_threaded_cert_verifier.cc
+++ b/net/cert/multi_threaded_cert_verifier.cc
@@ -81,10 +81,6 @@
   verify_result->error = verify_proc->Verify(
       cert.get(), hostname, ocsp_response, sct_list, flags,
       additional_trust_anchors, &verify_result->result, net_log);
-  // The CertVerifyResult is created and populated on the worker thread and
-  // then returned to the network thread. Detach now before returning the
-  // result, since any further access will be on the network thread.
-  verify_result->result.DetachFromSequence();
   return verify_result;
 }
 
diff --git a/net/cert/pki/DEPS b/net/cert/pki/DEPS
index 1149878c..cac7a02e 100644
--- a/net/cert/pki/DEPS
+++ b/net/cert/pki/DEPS
@@ -7,5 +7,4 @@
   "+base/files/file_util.h",
   "+base/numerics/clamped_math.h",
   "+base/path_service.h",
-  "+base/supports_user_data.h",
 ]
diff --git a/net/cert/pki/cert_issuer_source.h b/net/cert/pki/cert_issuer_source.h
index b40bd7c..875aeb5a6e 100644
--- a/net/cert/pki/cert_issuer_source.h
+++ b/net/cert/pki/cert_issuer_source.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/supports_user_data.h"
 #include "net/base/net_export.h"
 #include "net/cert/pki/parsed_certificate.h"
 
@@ -40,8 +39,7 @@
     // If no issuers are left then |issuers| will not be modified. This
     // indicates that the issuers have been exhausted and GetNext() should
     // not be called again.
-    virtual void GetNext(ParsedCertificateList* issuers,
-                         base::SupportsUserData* debug_data) = 0;
+    virtual void GetNext(ParsedCertificateList* issuers) = 0;
   };
 
   virtual ~CertIssuerSource() = default;
diff --git a/net/cert/pki/path_builder.cc b/net/cert/pki/path_builder.cc
index 2f0ef8b37..72166dba 100644
--- a/net/cert/pki/path_builder.cc
+++ b/net/cert/pki/path_builder.cc
@@ -164,12 +164,11 @@
 // which may be issuers of |cert|.
 class CertIssuersIter {
  public:
-  // Constructs the CertIssuersIter. |*cert_issuer_sources|, |*trust_store|,
-  // and |*debug_data| must be valid for the lifetime of the CertIssuersIter.
+  // Constructs the CertIssuersIter. |*cert_issuer_sources|, and
+  // |*trust_store| must be valid for the lifetime of the CertIssuersIter.
   CertIssuersIter(std::shared_ptr<const ParsedCertificate> cert,
                   CertIssuerSources* cert_issuer_sources,
-                  TrustStore* trust_store,
-                  base::SupportsUserData* debug_data);
+                  TrustStore* trust_store);
 
   CertIssuersIter(const CertIssuersIter&) = delete;
   CertIssuersIter& operator=(const CertIssuersIter&) = delete;
@@ -237,19 +236,15 @@
   // cancelled if CertIssuersIter is destroyed.
   std::vector<std::unique_ptr<CertIssuerSource::Request>>
       pending_async_requests_;
-
-  base::SupportsUserData* debug_data_;
 };
 
 CertIssuersIter::CertIssuersIter(
     std::shared_ptr<const ParsedCertificate> in_cert,
     CertIssuerSources* cert_issuer_sources,
-    TrustStore* trust_store,
-    base::SupportsUserData* debug_data)
+    TrustStore* trust_store)
     : cert_(std::move(in_cert)),
       cert_issuer_sources_(cert_issuer_sources),
-      trust_store_(trust_store),
-      debug_data_(debug_data) {
+      trust_store_(trust_store) {
   DVLOG(2) << "CertIssuersIter created for " << CertDebugString(cert());
 }
 
@@ -275,8 +270,7 @@
     while (!HasCurrentIssuer() &&
            cur_async_request_ < pending_async_requests_.size()) {
       ParsedCertificateList new_issuers;
-      pending_async_requests_[cur_async_request_]->GetNext(&new_issuers,
-                                                           debug_data_);
+      pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
       if (new_issuers.empty()) {
         // Request is exhausted, no more results pending from that
         // CertIssuerSource.
@@ -315,7 +309,7 @@
     // Look up the trust for this issuer.
     IssuerEntry entry;
     entry.cert = std::move(issuer);
-    entry.trust = trust_store_->GetTrust(entry.cert.get(), debug_data_);
+    entry.trust = trust_store_->GetTrust(entry.cert.get());
     entry.trust_and_key_id_match_ordering = TrustAndKeyIdentifierMatchToOrder(
         cert(), entry.cert.get(), entry.trust);
 
@@ -470,8 +464,7 @@
 class CertPathIter {
  public:
   CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
-               TrustStore* trust_store,
-               base::SupportsUserData* debug_data);
+               TrustStore* trust_store);
 
   CertPathIter(const CertPathIter&) = delete;
   CertPathIter& operator=(const CertPathIter&) = delete;
@@ -510,18 +503,14 @@
   CertIssuerSources cert_issuer_sources_;
   // The TrustStore for checking if a path ends in a trust anchor.
   TrustStore* trust_store_;
-
-  base::SupportsUserData* debug_data_;
 };
 
 CertPathIter::CertPathIter(std::shared_ptr<const ParsedCertificate> cert,
-                           TrustStore* trust_store,
-                           base::SupportsUserData* debug_data)
-    : trust_store_(trust_store), debug_data_(debug_data) {
+                           TrustStore* trust_store)
+    : trust_store_(trust_store) {
   // Initialize |next_issuer_| to the target certificate.
   next_issuer_.cert = std::move(cert);
-  next_issuer_.trust =
-      trust_store_->GetTrust(next_issuer_.cert.get(), debug_data_);
+  next_issuer_.trust = trust_store_->GetTrust(next_issuer_.cert.get());
 }
 
 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) {
@@ -682,8 +671,7 @@
         }
 
         cur_path_.Append(std::make_unique<CertIssuersIter>(
-            std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_,
-            debug_data_));
+            std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_));
         next_issuer_ = IssuerEntry();
         DVLOG(1) << "CertPathIter cur_path_ =\n" << cur_path_.PathDebugString();
         // Continue descending the tree.
@@ -750,9 +738,7 @@
     InitialPolicyMappingInhibit initial_policy_mapping_inhibit,
     InitialAnyPolicyInhibit initial_any_policy_inhibit)
     : cert_path_iter_(
-          std::make_unique<CertPathIter>(std::move(cert),
-                                         trust_store,
-                                         /*debug_data=*/&out_result_)),
+          std::make_unique<CertPathIter>(std::move(cert), trust_store)),
       delegate_(delegate),
       time_(time),
       key_purpose_(key_purpose),
diff --git a/net/cert/pki/path_builder.h b/net/cert/pki/path_builder.h
index cd9b583..f281baf 100644
--- a/net/cert/pki/path_builder.h
+++ b/net/cert/pki/path_builder.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/supports_user_data.h"
 #include "net/base/net_export.h"
 #include "net/cert/pki/cert_errors.h"
 #include "net/cert/pki/parsed_certificate.h"
@@ -111,14 +110,14 @@
  public:
   // Provides the overall result of path building. This includes the paths that
   // were attempted.
-  struct NET_EXPORT Result : public base::SupportsUserData {
+  struct NET_EXPORT Result {
     Result();
     Result(Result&&);
 
     Result(const Result&) = delete;
     Result& operator=(const Result&) = delete;
 
-    ~Result() override;
+    ~Result();
     Result& operator=(Result&&);
 
     // Returns true if there was a valid path.
diff --git a/net/cert/pki/path_builder_unittest.cc b/net/cert/pki/path_builder_unittest.cc
index 2ee48ce3..401f6b8 100644
--- a/net/cert/pki/path_builder_unittest.cc
+++ b/net/cert/pki/path_builder_unittest.cc
@@ -85,8 +85,7 @@
 
     ~StaticAsyncRequest() override = default;
 
-    void GetNext(ParsedCertificateList* out_certs,
-                 base::SupportsUserData* debug_data) override {
+    void GetNext(ParsedCertificateList* out_certs) override {
       if (issuers_iter_ != issuers_.end())
         out_certs->push_back(std::move(*issuers_iter_++));
     }
@@ -158,49 +157,6 @@
   return ::testing::AssertionSuccess();
 }
 
-const void* kKey = &kKey;
-class TrustStoreThatStoresUserData : public TrustStore {
- public:
-  class Data : public base::SupportsUserData::Data {
-   public:
-    explicit Data(int value) : value(value) {}
-
-    int value = 0;
-  };
-
-  // TrustStore implementation:
-  void SyncGetIssuersOf(const ParsedCertificate* cert,
-                        ParsedCertificateList* issuers) override {}
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override {
-    debug_data->SetUserData(kKey, std::make_unique<Data>(1234));
-    return CertificateTrust::ForUnspecified();
-  }
-};
-
-TEST(PathBuilderResultUserDataTest, ModifyUserDataInConstructor) {
-  std::shared_ptr<const ParsedCertificate> a_by_b;
-  ASSERT_TRUE(ReadTestCert("multi-root-A-by-B.pem", &a_by_b));
-  SimplePathBuilderDelegate delegate(
-      1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
-  der::GeneralizedTime verify_time = {2017, 3, 1, 0, 0, 0};
-  TrustStoreThatStoresUserData trust_store;
-
-  // |trust_store| will unconditionally store user data in the
-  // CertPathBuilder::Result. This ensures that the Result object has been
-  // initialized before the first GetTrust call occurs (otherwise the test will
-  // crash or fail on ASAN bots).
-  CertPathBuilder path_builder(
-      a_by_b, &trust_store, &delegate, verify_time, KeyPurpose::ANY_EKU,
-      InitialExplicitPolicy::kFalse, {der::Input(kAnyPolicyOid)},
-      InitialPolicyMappingInhibit::kFalse, InitialAnyPolicyInhibit::kFalse);
-  CertPathBuilder::Result result = path_builder.Run();
-  auto* data = static_cast<TrustStoreThatStoresUserData::Data*>(
-      result.GetUserData(kKey));
-  ASSERT_TRUE(data);
-  EXPECT_EQ(1234, data->value);
-}
-
 class PathBuilderMultiRootTest : public ::testing::Test {
  public:
   PathBuilderMultiRootTest()
@@ -1566,7 +1522,7 @@
 
 class MockCertIssuerSourceRequest : public CertIssuerSource::Request {
  public:
-  MOCK_METHOD2(GetNext, void(ParsedCertificateList*, base::SupportsUserData*));
+  MOCK_METHOD1(GetNext, void(ParsedCertificateList*));
 };
 
 class MockCertIssuerSource : public CertIssuerSource {
@@ -1602,10 +1558,7 @@
       const std::shared_ptr<const ParsedCertificate>& cert)
       : cert_(cert) {}
 
-  void operator()(ParsedCertificateList* out,
-                  base::SupportsUserData* debug_data) {
-    out->push_back(cert_);
-  }
+  void operator()(ParsedCertificateList* out) { out->push_back(cert_); }
 
  private:
   std::shared_ptr<const ParsedCertificate> cert_;
@@ -1643,7 +1596,7 @@
         .WillOnce(Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt));
   }
 
-  EXPECT_CALL(*target_issuers_req, GetNext(_, _))
+  EXPECT_CALL(*target_issuers_req, GetNext(_))
       // First async batch: return oldintermediate_.
       .WillOnce(Invoke(AppendCertToList(oldintermediate_)))
       // Second async batch: return newintermediate_.
@@ -1730,7 +1683,7 @@
               oldintermediate_->der_cert().Length(), nullptr)),
           {}, nullptr));
 
-  EXPECT_CALL(*target_issuers_req, GetNext(_, _))
+  EXPECT_CALL(*target_issuers_req, GetNext(_))
       // First async batch: return oldintermediate_.
       .WillOnce(Invoke(AppendCertToList(oldintermediate_)))
       // Second async batch: return a different copy of oldintermediate_ again.
diff --git a/net/cert/pki/trust_store.h b/net/cert/pki/trust_store.h
index 91bcb4d..4c9536d 100644
--- a/net/cert/pki/trust_store.h
+++ b/net/cert/pki/trust_store.h
@@ -5,7 +5,6 @@
 #ifndef NET_CERT_PKI_TRUST_STORE_H_
 #define NET_CERT_PKI_TRUST_STORE_H_
 
-#include "base/supports_user_data.h"
 #include "net/base/net_export.h"
 #include "net/cert/pki/cert_issuer_source.h"
 #include "net/cert/pki/parsed_certificate.h"
@@ -131,17 +130,9 @@
   TrustStore& operator=(const TrustStore&) = delete;
 
   // Returns the trusted of |cert|, which must be non-null.
-  //
-  // Optionally, if |debug_data| is non-null, debug information may be added
-  // (any added Data must implement the Clone method.) The same |debug_data|
-  // object may be passed to multiple GetTrust calls for a single verification,
-  // so implementations should check whether they already added data with a
-  // certain key and update it instead of overwriting it.
-  virtual CertificateTrust GetTrust(const ParsedCertificate* cert,
-                                    base::SupportsUserData* debug_data) = 0;
+  virtual CertificateTrust GetTrust(const ParsedCertificate* cert) = 0;
 
   // Disable async issuers for TrustStore, as it isn't needed.
-  // TODO(mattm): Pass debug_data here too.
   void AsyncGetIssuersOf(const ParsedCertificate* cert,
                          std::unique_ptr<Request>* out_req) final;
 };
diff --git a/net/cert/pki/trust_store_collection.cc b/net/cert/pki/trust_store_collection.cc
index 7ee83ac4..1732fe5 100644
--- a/net/cert/pki/trust_store_collection.cc
+++ b/net/cert/pki/trust_store_collection.cc
@@ -23,14 +23,12 @@
   }
 }
 
-CertificateTrust TrustStoreCollection::GetTrust(
-    const ParsedCertificate* cert,
-    base::SupportsUserData* debug_data) {
+CertificateTrust TrustStoreCollection::GetTrust(const ParsedCertificate* cert) {
   // The current aggregate result.
   CertificateTrust result = CertificateTrust::ForUnspecified();
 
   for (auto* store : stores_) {
-    CertificateTrust cur_trust = store->GetTrust(cert, debug_data);
+    CertificateTrust cur_trust = store->GetTrust(cert);
 
     // * If any stores distrust the certificate, consider it untrusted.
     // * If multiple stores consider it trusted, use the trust result from the
diff --git a/net/cert/pki/trust_store_collection.h b/net/cert/pki/trust_store_collection.h
index 4e9fe6b..21bcb20 100644
--- a/net/cert/pki/trust_store_collection.h
+++ b/net/cert/pki/trust_store_collection.h
@@ -31,8 +31,7 @@
   // TrustStore implementation:
   void SyncGetIssuersOf(const ParsedCertificate* cert,
                         ParsedCertificateList* issuers) override;
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override;
+  CertificateTrust GetTrust(const ParsedCertificate* cert) override;
 
  private:
   std::vector<TrustStore*> stores_;
diff --git a/net/cert/pki/trust_store_collection_unittest.cc b/net/cert/pki/trust_store_collection_unittest.cc
index 47951ff..07914ec1 100644
--- a/net/cert/pki/trust_store_collection_unittest.cc
+++ b/net/cert/pki/trust_store_collection_unittest.cc
@@ -76,13 +76,12 @@
   EXPECT_EQ(newroot_.get(), issuers[0].get());
 
   // newroot_ is trusted.
-  CertificateTrust trust =
-      collection.GetTrust(newroot_.get(), /*debug_data=*/nullptr);
+  CertificateTrust trust = collection.GetTrust(newroot_.get());
   EXPECT_EQ(CertificateTrust::ForTrustAnchor().ToDebugString(),
             trust.ToDebugString());
 
   // oldroot_ is not.
-  trust = collection.GetTrust(oldroot_.get(), /*debug_data=*/nullptr);
+  trust = collection.GetTrust(oldroot_.get());
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
             trust.ToDebugString());
 }
@@ -105,13 +104,12 @@
   EXPECT_EQ(newroot_.get(), issuers[3].get());
 
   // newroot_ is trusted.
-  CertificateTrust trust =
-      collection.GetTrust(newroot_.get(), /*debug_data=*/nullptr);
+  CertificateTrust trust = collection.GetTrust(newroot_.get());
   EXPECT_EQ(CertificateTrust::ForTrustAnchor().ToDebugString(),
             trust.ToDebugString());
 
   // newrootrollover_ is not.
-  trust = collection.GetTrust(newrootrollover_.get(), /*debug_data=*/nullptr);
+  trust = collection.GetTrust(newrootrollover_.get());
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
             trust.ToDebugString());
 }
@@ -134,18 +132,17 @@
   EXPECT_EQ(oldroot_.get(), issuers[1].get());
 
   // newroot_ is trusted.
-  CertificateTrust trust =
-      collection.GetTrust(newroot_.get(), /*debug_data=*/nullptr);
+  CertificateTrust trust = collection.GetTrust(newroot_.get());
   EXPECT_EQ(CertificateTrust::ForTrustAnchor().ToDebugString(),
             trust.ToDebugString());
 
   // oldroot_ is trusted.
-  trust = collection.GetTrust(oldroot_.get(), /*debug_data=*/nullptr);
+  trust = collection.GetTrust(oldroot_.get());
   EXPECT_EQ(CertificateTrust::ForTrustAnchor().ToDebugString(),
             trust.ToDebugString());
 
   // newrootrollover_ is not.
-  trust = collection.GetTrust(newrootrollover_.get(), /*debug_data=*/nullptr);
+  trust = collection.GetTrust(newrootrollover_.get());
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
             trust.ToDebugString());
 }
@@ -171,18 +168,17 @@
   collection.AddTrustStore(&in_memory2);
 
   // newroot_ is distrusted..
-  CertificateTrust trust =
-      collection.GetTrust(newroot_.get(), /*debug_data=*/nullptr);
+  CertificateTrust trust = collection.GetTrust(newroot_.get());
   EXPECT_EQ(CertificateTrust::ForDistrusted().ToDebugString(),
             trust.ToDebugString());
 
   // oldintermediate_ is distrusted.
-  trust = collection.GetTrust(oldintermediate_.get(), /*debug_data=*/nullptr);
+  trust = collection.GetTrust(oldintermediate_.get());
   EXPECT_EQ(CertificateTrust::ForDistrusted().ToDebugString(),
             trust.ToDebugString());
 
   // newrootrollover_ is unspecified.
-  trust = collection.GetTrust(newrootrollover_.get(), /*debug_data=*/nullptr);
+  trust = collection.GetTrust(newrootrollover_.get());
   EXPECT_EQ(CertificateTrust::ForUnspecified().ToDebugString(),
             trust.ToDebugString());
 }
diff --git a/net/cert/pki/trust_store_in_memory.cc b/net/cert/pki/trust_store_in_memory.cc
index f6ccced..ac09e24 100644
--- a/net/cert/pki/trust_store_in_memory.cc
+++ b/net/cert/pki/trust_store_in_memory.cc
@@ -52,9 +52,7 @@
     issuers->push_back(it->second.cert);
 }
 
-CertificateTrust TrustStoreInMemory::GetTrust(
-    const ParsedCertificate* cert,
-    base::SupportsUserData* debug_data) {
+CertificateTrust TrustStoreInMemory::GetTrust(const ParsedCertificate* cert) {
   const Entry* entry = GetEntry(cert);
   return entry ? entry->trust : CertificateTrust::ForUnspecified();
 }
diff --git a/net/cert/pki/trust_store_in_memory.h b/net/cert/pki/trust_store_in_memory.h
index 5441ea5..0bc0e53 100644
--- a/net/cert/pki/trust_store_in_memory.h
+++ b/net/cert/pki/trust_store_in_memory.h
@@ -61,8 +61,7 @@
   // TrustStore implementation:
   void SyncGetIssuersOf(const ParsedCertificate* cert,
                         ParsedCertificateList* issuers) override;
-  CertificateTrust GetTrust(const ParsedCertificate* cert,
-                            base::SupportsUserData* debug_data) override;
+  CertificateTrust GetTrust(const ParsedCertificate* cert) override;
 
   // Returns true if the trust store contains the given ParsedCertificate
   // (matches by DER).
diff --git a/net/cert/test_root_certs.h b/net/cert/test_root_certs.h
index fa3066694..538a9b5f 100644
--- a/net/cert/test_root_certs.h
+++ b/net/cert/test_root_certs.h
@@ -5,8 +5,11 @@
 #ifndef NET_CERT_TEST_ROOT_CERTS_H_
 #define NET_CERT_TEST_ROOT_CERTS_H_
 
+#include <set>
+
 #include "base/containers/span.h"
 #include "base/lazy_instance.h"
+#include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
 #include "net/base/net_export.h"
 #include "net/cert/pki/trust_store.h"
diff --git a/net/tools/cert_verify_tool/cert_verify_tool_util.cc b/net/tools/cert_verify_tool/cert_verify_tool_util.cc
index 484a5d0..bb6ad02 100644
--- a/net/tools/cert_verify_tool/cert_verify_tool_util.cc
+++ b/net/tools/cert_verify_tool/cert_verify_tool_util.cc
@@ -15,10 +15,6 @@
 #include "net/cert/x509_certificate.h"
 #include "net/cert/x509_util.h"
 
-#if BUILDFLAG(IS_MAC)
-#include "net/cert/internal/trust_store_mac.h"
-#endif
-
 namespace {
 
 // The PEM block header used for PEM-encoded DER certificates.
@@ -123,18 +119,6 @@
   std::cerr << "\n";
 }
 
-void PrintDebugData(const base::SupportsUserData* debug_data) {
-#if BUILDFLAG(IS_MAC)
-  auto* mac_trust_debug_info =
-      net::TrustStoreMac::ResultDebugData::Get(debug_data);
-  if (mac_trust_debug_info) {
-    std::cout << base::StringPrintf(
-        "TrustStoreMac::ResultDebugData::combined_trust_debug_info: 0x%x\n",
-        mac_trust_debug_info->combined_trust_debug_info());
-  }
-#endif
-}
-
 std::string FingerPrintCryptoBuffer(const CRYPTO_BUFFER* cert_handle) {
   net::SHA256HashValue hash =
       net::X509Certificate::CalculateFingerprint256(cert_handle);
diff --git a/net/tools/cert_verify_tool/cert_verify_tool_util.h b/net/tools/cert_verify_tool/cert_verify_tool_util.h
index 61ffee7..125d74a 100644
--- a/net/tools/cert_verify_tool/cert_verify_tool_util.h
+++ b/net/tools/cert_verify_tool/cert_verify_tool_util.h
@@ -12,10 +12,6 @@
 #include "base/files/file_path.h"
 #include "net/cert/pki/trust_store.h"
 
-namespace base {
-class SupportsUserData;
-}
-
 namespace net {
 class X509Certificate;
 }  // namespace net
@@ -66,9 +62,6 @@
 // was read from, as well as which block in the file if it was a PEM file.
 void PrintCertError(const std::string& error, const CertInput& cert);
 
-// Prints any known debug information from |debug_data|.
-void PrintDebugData(const base::SupportsUserData* debug_data);
-
 // Returns a hex-encoded sha256 of the DER-encoding of |cert_handle|.
 std::string FingerPrintCryptoBuffer(const CRYPTO_BUFFER* cert_handle);
 
diff --git a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
index ad7cf89..d95183f 100644
--- a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
+++ b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
@@ -59,7 +59,6 @@
 }  // namespace
 
 void PrintCertVerifyResult(const net::CertVerifyResult& result) {
-  PrintDebugData(&result);
   PrintCertStatus(result.cert_status);
   if (result.has_sha1)
     std::cout << "has_sha1\n";
diff --git a/net/tools/cert_verify_tool/verify_using_path_builder.cc b/net/tools/cert_verify_tool/verify_using_path_builder.cc
index 3a788b0..41b241c 100644
--- a/net/tools/cert_verify_tool/verify_using_path_builder.cc
+++ b/net/tools/cert_verify_tool/verify_using_path_builder.cc
@@ -206,8 +206,6 @@
   std::cout << "CertPathBuilder result: "
             << (result.HasValidPath() ? "SUCCESS" : "FAILURE") << "\n";
 
-  PrintDebugData(&result);
-
   for (size_t i = 0; i < result.paths.size(); ++i) {
     PrintResultPath(result.paths[i].get(), i, i == result.best_result_index);
   }
diff --git a/services/data_decoder/xml_parser_unittest.cc b/services/data_decoder/xml_parser_unittest.cc
index a2baaec..83162991 100644
--- a/services/data_decoder/xml_parser_unittest.cc
+++ b/services/data_decoder/xml_parser_unittest.cc
@@ -66,11 +66,11 @@
     const char* input;
     const char* expected_error;
   } test_cases[] = {
-      {"", "Extra content at the end of the document"},
-      {"  ", "Extra content at the end of the document"},
-      {"Awesome possum", "Document is empty"},
-      {R"( ["json", "or", "xml?"] )", "Document is empty"},
-      {"<unbalanced>", "Extra content at the end of the document"},
+      {"", "Document is empty"},
+      {"  ", "Start tag expected"},
+      {"Awesome possum", "Start tag expected"},
+      {R"( ["json", "or", "xml?"] )", "Start tag expected"},
+      {"<unbalanced>", "Premature end of data in tag"},
       {"<hello>bad tag</goodbye>",
        "Opening and ending tag mismatch: hello line 1 and goodbye"},
   };
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc
index db6ff07..2b781f2 100644
--- a/storage/browser/blob/blob_storage_context.cc
+++ b/storage/browser/blob/blob_storage_context.cc
@@ -743,4 +743,9 @@
           std::move(callback)));
 }
 
+void BlobStorageContext::Clone(
+    mojo::PendingReceiver<mojom::BlobStorageContext> receiver) {
+  Bind(std::move(receiver));
+}
+
 }  // namespace storage
diff --git a/storage/browser/blob/blob_storage_context.h b/storage/browser/blob/blob_storage_context.h
index 400356a..ae1d156 100644
--- a/storage/browser/blob/blob_storage_context.h
+++ b/storage/browser/blob/blob_storage_context.h
@@ -256,6 +256,7 @@
                        bool flush_on_write,
                        absl::optional<base::Time> last_modified,
                        WriteBlobToFileCallback callback) override;
+  void Clone(mojo::PendingReceiver<mojom::BlobStorageContext> cloned) override;
 
   base::FilePath profile_directory_;
   BlobStorageRegistry registry_;
diff --git a/testing/buildbot/README.md b/testing/buildbot/README.md
index fb094c07..aac666e 100644
--- a/testing/buildbot/README.md
+++ b/testing/buildbot/README.md
@@ -36,7 +36,8 @@
 (by name) to test suites that are defined in test_suites.pyl.
 * [test_suites.pyl](./test_suites.pyl) -- describes the test suites that are
 referred to by waterfalls.pyl. A test suite describes groups of tests that are
-run on one or more bots.
+run on one or more bots. This file is actually generated from starlark
+definitions (see [below](#starlark-inputs)).
 * [mixins.pyl](./mixins.pyl) -- describes reusable bits of configuration that
 can be used to modify the expansion of tests from waterfalls.pyl into the
 generated test specs. This file is actually generated from starlark definitions
@@ -71,6 +72,16 @@
 [sync-pyl-files.py](../../infra/config/scripts/sync-pyl-files.py) to update the
 pyl files in this directory.
 
+* [basic_suites.star](../../infra/config/targets/basic_suites.star) -- Contains
+the basic suite definitions that produce the basic_suites entries in
+test_suites.pyl.
+* [compound_suites.star](../../infra/config/targets/compound_suites.star) --
+Contains the compound suite definitions that produce the compound_suites entries
+in test_suites.pyl.
+* [matrix_compound_suites.star](
+  ../../infra/config/targets/matrix_compound_suites.star) -- Contains the matrix
+  compound suite definitions that produce the matrix_compound_suites entries in
+  test_suites.pyl.
 * [mixins.star](../../infra/config/targets/mixins.star) -- contains the test
   suite mixins that produce mixins.pyl.
 * [variants.star](../../infra/config/targets/variants.star) -- contains the
diff --git a/testing/buildbot/autoshard_exceptions.json b/testing/buildbot/autoshard_exceptions.json
index 15e8100..fc65736a 100644
--- a/testing/buildbot/autoshard_exceptions.json
+++ b/testing/buildbot/autoshard_exceptions.json
@@ -47,31 +47,31 @@
         "android-nougat-x86-rel": {
             "content_shell_test_apk": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "72.0",
-                    "estimated_bot_hour_delta": "2.65",
-                    "prev_avg_pending_time_sec": "13.7",
+                    "avg_num_builds_per_peak_hour": "87.0",
+                    "estimated_bot_hour_delta": "-3.23",
+                    "prev_avg_pending_time_sec": "12.7",
                     "prev_p50_pending_time_sec": "0.0",
-                    "prev_p90_pending_time_sec": "42.0",
-                    "prev_percentile_duration_minutes": "16.88",
-                    "prev_shard_count": "5",
-                    "simulated_max_shard_duration": "14.07",
+                    "prev_p90_pending_time_sec": "38.0",
+                    "prev_percentile_duration_minutes": "12.65",
+                    "prev_shard_count": "6",
+                    "simulated_max_shard_duration": "15.18",
                     "try_builder": "android-nougat-x86-rel"
                 },
-                "shards": "6"
+                "shards": "5"
             },
             "webview_instrumentation_test_apk": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "72.0",
-                    "estimated_bot_hour_delta": "2.74",
-                    "prev_avg_pending_time_sec": "29.5",
-                    "prev_p50_pending_time_sec": "5.0",
-                    "prev_p90_pending_time_sec": "100.0",
-                    "prev_percentile_duration_minutes": "15.07",
-                    "prev_shard_count": "20",
-                    "simulated_max_shard_duration": "14.35",
+                    "avg_num_builds_per_peak_hour": "87.0",
+                    "estimated_bot_hour_delta": "3.34",
+                    "prev_avg_pending_time_sec": "27.0",
+                    "prev_p50_pending_time_sec": "4.0",
+                    "prev_p90_pending_time_sec": "96.0",
+                    "prev_percentile_duration_minutes": "15.42",
+                    "prev_shard_count": "21",
+                    "simulated_max_shard_duration": "14.72",
                     "try_builder": "android-nougat-x86-rel"
                 },
-                "shards": "21"
+                "shards": "22"
             }
         }
     },
@@ -79,17 +79,17 @@
         "chromeos-amd64-generic-rel": {
             "chrome_all_tast_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "75.0",
-                    "estimated_bot_hour_delta": "-3.15",
-                    "prev_avg_pending_time_sec": "64.1",
-                    "prev_p50_pending_time_sec": "17.0",
-                    "prev_p90_pending_time_sec": "179.0",
-                    "prev_percentile_duration_minutes": "13.41",
-                    "prev_shard_count": "16",
-                    "simulated_max_shard_duration": "14.3",
+                    "avg_num_builds_per_peak_hour": "86.0",
+                    "estimated_bot_hour_delta": "6.94",
+                    "prev_avg_pending_time_sec": "41.5",
+                    "prev_p50_pending_time_sec": "9.0",
+                    "prev_p90_pending_time_sec": "115.0",
+                    "prev_percentile_duration_minutes": "16.1",
+                    "prev_shard_count": "15",
+                    "simulated_max_shard_duration": "14.21",
                     "try_builder": "chromeos-amd64-generic-rel"
                 },
-                "shards": "15"
+                "shards": "17"
             }
         },
         "linux-chromeos-rel": {
@@ -109,33 +109,61 @@
             },
             "browser_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "69.0",
-                    "estimated_bot_hour_delta": "6.06",
-                    "prev_avg_pending_time_sec": "61.6",
-                    "prev_p50_pending_time_sec": "7.0",
-                    "prev_p90_pending_time_sec": "196.0",
-                    "prev_percentile_duration_minutes": "15.48",
-                    "prev_shard_count": "75",
-                    "simulated_max_shard_duration": "14.88",
+                    "avg_num_builds_per_peak_hour": "81.0",
+                    "estimated_bot_hour_delta": "11.96",
+                    "prev_avg_pending_time_sec": "38.5",
+                    "prev_p50_pending_time_sec": "6.0",
+                    "prev_p90_pending_time_sec": "119.0",
+                    "prev_percentile_duration_minutes": "15.73",
+                    "prev_shard_count": "78",
+                    "simulated_max_shard_duration": "14.78",
                     "try_builder": "linux-chromeos-rel"
                 },
-                "shards": "78"
+                "shards": "83"
+            },
+            "browser_tests_require_lacros": {
+                "debug": {
+                    "avg_num_builds_per_peak_hour": "81.0",
+                    "estimated_bot_hour_delta": "2.15",
+                    "prev_avg_pending_time_sec": "204.8",
+                    "prev_p50_pending_time_sec": "12.0",
+                    "prev_p90_pending_time_sec": "639.0",
+                    "prev_percentile_duration_minutes": "15.52",
+                    "prev_shard_count": "8",
+                    "simulated_max_shard_duration": "13.8",
+                    "try_builder": "linux-chromeos-rel"
+                },
+                "shards": "9"
+            },
+            "content_browsertests": {
+                "debug": {
+                    "avg_num_builds_per_peak_hour": "81.0",
+                    "estimated_bot_hour_delta": "1.89",
+                    "prev_avg_pending_time_sec": "199.4",
+                    "prev_p50_pending_time_sec": "11.0",
+                    "prev_p90_pending_time_sec": "604.0",
+                    "prev_percentile_duration_minutes": "15.09",
+                    "prev_shard_count": "6",
+                    "simulated_max_shard_duration": "12.93",
+                    "try_builder": "linux-chromeos-rel"
+                },
+                "shards": "7"
             }
         },
         "linux-lacros-tester-rel": {
             "browser_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "72.0",
-                    "estimated_bot_hour_delta": "1.93",
-                    "prev_avg_pending_time_sec": "315.9",
-                    "prev_p50_pending_time_sec": "30.0",
-                    "prev_p90_pending_time_sec": "1273.0",
-                    "prev_percentile_duration_minutes": "15.05",
-                    "prev_shard_count": "25",
-                    "simulated_max_shard_duration": "14.47",
+                    "avg_num_builds_per_peak_hour": "85.0",
+                    "estimated_bot_hour_delta": "2.3",
+                    "prev_avg_pending_time_sec": "173.8",
+                    "prev_p50_pending_time_sec": "17.0",
+                    "prev_p90_pending_time_sec": "577.0",
+                    "prev_percentile_duration_minutes": "15.37",
+                    "prev_shard_count": "26",
+                    "simulated_max_shard_duration": "14.8",
                     "try_builder": "linux-lacros-rel"
                 },
-                "shards": "26"
+                "shards": "27"
             },
             "interactive_ui_tests": {
                 "debug": {
@@ -329,17 +357,17 @@
             },
             "browser_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "71.0",
-                    "estimated_bot_hour_delta": "1.89",
-                    "prev_avg_pending_time_sec": "328.5",
-                    "prev_p50_pending_time_sec": "34.0",
-                    "prev_p90_pending_time_sec": "1276.0",
-                    "prev_percentile_duration_minutes": "15.28",
-                    "prev_shard_count": "25",
-                    "simulated_max_shard_duration": "14.69",
+                    "avg_num_builds_per_peak_hour": "82.0",
+                    "estimated_bot_hour_delta": "2.19",
+                    "prev_avg_pending_time_sec": "170.4",
+                    "prev_p50_pending_time_sec": "13.0",
+                    "prev_p90_pending_time_sec": "571.0",
+                    "prev_percentile_duration_minutes": "15.4",
+                    "prev_shard_count": "26",
+                    "simulated_max_shard_duration": "14.83",
                     "try_builder": "linux-rel"
                 },
-                "shards": "26"
+                "shards": "27"
             },
             "interactive_ui_tests": {
                 "debug": {
@@ -359,17 +387,17 @@
         "Linux Tests (Wayland)": {
             "browser_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "71.0",
-                    "estimated_bot_hour_delta": "1.88",
-                    "prev_avg_pending_time_sec": "288.2",
-                    "prev_p50_pending_time_sec": "13.0",
-                    "prev_p90_pending_time_sec": "1201.0",
-                    "prev_percentile_duration_minutes": "15.02",
-                    "prev_shard_count": "24",
-                    "simulated_max_shard_duration": "14.42",
+                    "avg_num_builds_per_peak_hour": "84.0",
+                    "estimated_bot_hour_delta": "2.24",
+                    "prev_avg_pending_time_sec": "156.3",
+                    "prev_p50_pending_time_sec": "5.0",
+                    "prev_p90_pending_time_sec": "560.0",
+                    "prev_percentile_duration_minutes": "15.5",
+                    "prev_shard_count": "25",
+                    "simulated_max_shard_duration": "14.9",
                     "try_builder": "linux-wayland-rel"
                 },
-                "shards": "25"
+                "shards": "26"
             },
             "interactive_ui_tests": {
                 "debug": {
@@ -463,17 +491,17 @@
             },
             "interactive_ui_tests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "76.0",
-                    "estimated_bot_hour_delta": "-2.59",
-                    "prev_avg_pending_time_sec": "533.4",
-                    "prev_p50_pending_time_sec": "147.0",
-                    "prev_p90_pending_time_sec": "1871.0",
-                    "prev_percentile_duration_minutes": "14.55",
-                    "prev_shard_count": "40",
-                    "simulated_max_shard_duration": "14.92",
+                    "avg_num_builds_per_peak_hour": "86.0",
+                    "estimated_bot_hour_delta": "2.9",
+                    "prev_avg_pending_time_sec": "183.3",
+                    "prev_p50_pending_time_sec": "10.0",
+                    "prev_p90_pending_time_sec": "579.0",
+                    "prev_percentile_duration_minutes": "15.03",
+                    "prev_shard_count": "39",
+                    "simulated_max_shard_duration": "14.65",
                     "try_builder": "linux_chromium_tsan_rel_ng"
                 },
-                "shards": "39"
+                "shards": "40"
             },
             "sync_integration_tests": {
                 "debug": {
@@ -523,17 +551,17 @@
         "Win10 Tests x64": {
             "content_browsertests": {
                 "debug": {
-                    "avg_num_builds_per_peak_hour": "69.0",
-                    "estimated_bot_hour_delta": "2.35",
-                    "prev_avg_pending_time_sec": "190.7",
-                    "prev_p50_pending_time_sec": "77.0",
-                    "prev_p90_pending_time_sec": "558.0",
-                    "prev_percentile_duration_minutes": "15.1",
-                    "prev_shard_count": "9",
-                    "simulated_max_shard_duration": "13.59",
+                    "avg_num_builds_per_peak_hour": "76.0",
+                    "estimated_bot_hour_delta": "5.29",
+                    "prev_avg_pending_time_sec": "404.5",
+                    "prev_p50_pending_time_sec": "214.0",
+                    "prev_p90_pending_time_sec": "1199.0",
+                    "prev_percentile_duration_minutes": "16.47",
+                    "prev_shard_count": "10",
+                    "simulated_max_shard_duration": "13.72",
                     "try_builder": "win-rel"
                 },
-                "shards": "10"
+                "shards": "12"
             },
             "updater_tests_system": {
                 "debug": {
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 2c8843b1..9b95786 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -26619,7 +26619,7 @@
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 6
+          "shards": 5
         },
         "test": "content_shell_test_apk",
         "test_id_prefix": "ninja://content/shell/android:content_shell_test_apk/"
@@ -29092,7 +29092,7 @@
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 21
+          "shards": 22
         },
         "test": "webview_instrumentation_test_apk",
         "test_id_prefix": "ninja://android_webview/test:webview_instrumentation_test_apk/"
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 9e22c6d..a8b8e57 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -188,7 +188,7 @@
             }
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 15
+          "shards": 17
         },
         "test": "chrome_all_tast_tests",
         "test_id_prefix": "ninja://chromeos:chrome_all_tast_tests/"
@@ -1409,7 +1409,6 @@
     ],
     "skylab_tests": [
       {
-        "autotest_name": "tast.lacros-from-gcs",
         "bucket": "chromiumos-image-archive",
         "cros_board": "volteer",
         "cros_img": "volteer-public/R119-15623.0.0",
@@ -3147,7 +3146,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 78
+          "shards": 83
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
@@ -3167,7 +3166,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 8
+          "shards": 9
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
@@ -3337,7 +3336,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 6
+          "shards": 7
         },
         "test": "content_browsertests",
         "test_id_prefix": "ninja://content/test:content_browsertests/"
@@ -4568,7 +4567,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 26
+          "shards": 27
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
@@ -5039,9 +5038,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5051,8 +5050,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -5187,9 +5186,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5199,8 +5198,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -5319,9 +5318,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5331,8 +5330,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 629609d..61dce2f 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -25384,9 +25384,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25396,8 +25396,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -25532,9 +25532,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25544,8 +25544,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -25664,9 +25664,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25676,8 +25676,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index fe2bf761..d5c95f67 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -43455,9 +43455,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43466,8 +43466,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -43603,9 +43603,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43614,8 +43614,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -43735,9 +43735,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43746,8 +43746,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -45059,9 +45059,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45070,8 +45070,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -45207,9 +45207,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45218,8 +45218,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -45339,9 +45339,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45350,8 +45350,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -46049,9 +46049,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -46060,8 +46060,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 84679885..61d2c7b7 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -1830,7 +1830,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 26
+          "shards": 27
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
@@ -3881,7 +3881,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 25
+          "shards": 26
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 3bfd44d..a45baa9 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -8415,7 +8415,7 @@
             "os": "Ubuntu-22.04"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 39
+          "shards": 40
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
@@ -16364,12 +16364,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16379,8 +16379,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -16532,12 +16532,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16547,8 +16547,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
@@ -16679,12 +16679,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 119.0.6029.0",
+        "description": "Run with ash-chrome version 119.0.6030.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16694,8 +16694,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v119.0.6029.0",
-              "revision": "version:119.0.6029.0"
+              "location": "lacros_version_skew_tests_v119.0.6030.0",
+              "revision": "version:119.0.6030.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 74eaf00..1f57834 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -531,7 +531,7 @@
             "os": "Windows-10-19045"
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
+          "shards": 12
         },
         "test": "content_browsertests",
         "test_id_prefix": "ninja://content/test:content_browsertests/"
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index ccf1088..8d4d250a 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -1,28 +1,15 @@
-# Copyright 2017 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This is a .pyl, or "Python Literal", file. You can treat it just like a
-# .json file, with the following exceptions:
-# * all keys must be quoted (use single quotes, please);
-# * comments are allowed, using '#' syntax; and
-# * trailing commas are allowed.
-
-# The test suites understood by the waterfalls. Two kinds of entries
-# are supported here:
-#  1. Dictionaries that directly define test suites.
-#  2. Compositions, in the form of lists which refer to other test
-#     suites.
-#
-# This file must be sorted by key. Run ./generate_buildbot_json.py -c to check
-# your ordering; it will print out incorrectly sorted keys if there are any.
+# THIS IS A GENERATED FILE DO NOT EDIT!!!
+# Instead:
+# 1. Modify //infra/config/targets/basic_suites.star, //infra/config/targets/compound_suites.star and/or //infra/config/targets/matrix_compound_suites.star
+# 2. Run //infra/config/main.star
+# 3. Run //infra/config/scripts/sync-pyl-files.py
 
 {
-  # Test suites.
   'basic_suites': {
 
     'android_12_fieldtrial_webview_tests': {
       'webview_trichrome_64_cts_tests_no_field_trial': {
+        'test': 'webview_trichrome_64_cts_tests',
         'args': [
           '--disable-field-trial-config',
         ],
@@ -31,142 +18,128 @@
           'shards': 2,
           'cipd_packages': [
             {
-              "cipd_package": 'chromium/android_webview/tools/cts_archive',
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
               'location': 'android_webview/tools/cts_archive',
               'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
-            }
-          ]
+            },
+          ],
         },
-        'test': 'webview_trichrome_64_cts_tests',
       },
       'webview_ui_test_app_test_apk_no_field_trial': {
+        'test': 'webview_ui_test_app_test_apk',
         'args': [
           '--disable-field-trial-config',
         ],
         'ci_only': True,
-        'test': 'webview_ui_test_app_test_apk',
       },
     },
 
     'android_ar_gtests': {
       'monochrome_public_test_ar_apk': {},
-      # Name is vr_*, but actually has AR tests.
       'vr_android_unittests': {},
     },
 
     'android_ddready_vr_gtests': {
       'chrome_public_test_vr_apk-ddready-cardboard': {
-        'args': [
-          '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json',
-        ],
+        'test': 'chrome_public_test_vr_apk',
         'mixins': [
           'vr_instrumentation_test',
         ],
+        'args': [
+          '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json',
+        ],
         'swarming': {
           'shards': 2,
         },
-        'test': 'chrome_public_test_vr_apk',
       },
       'chrome_public_test_vr_apk-ddready-ddview': {
-        'args': [
-          '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json',
-          '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk',
-        ],
+        'test': 'chrome_public_test_vr_apk',
         'mixins': [
           'skia_gold_test',
           'vr_instrumentation_test',
         ],
+        'args': [
+          '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json',
+          '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk',
+        ],
         'swarming': {
           'shards': 4,
         },
-        'test': 'chrome_public_test_vr_apk',
       },
       'chrome_public_test_vr_apk-ddready-don-enabled': {
+        'test': 'chrome_public_test_vr_apk',
+        'mixins': [
+          'vr_instrumentation_test',
+        ],
         'args': [
           '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_don_setupcomplete.json',
           '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk',
           '--annotation=Restriction=VR_DON_Enabled',
           '--vr-don-enabled',
         ],
-        'mixins': [
-          'vr_instrumentation_test',
-        ],
-        'test': 'chrome_public_test_vr_apk',
       },
     },
 
     'android_emulator_specific_chrome_public_tests': {
       'chrome_public_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+          'emulator-8-cores',
+        ],
         'args': [
-            # These tests launch external intent thus require playstore to be
-            # present. See crbug.com/1056330 for more details.
-            # Exclude them here since this test suite will run on emulator
-            # on images that do not have playstore.
-            # They will be ran in chrome_public_test_apk_with_playstore below.
-            '--gtest_filter=-'
-            'org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:'
-            'org.chromium.shape_detection.*'
+          '--gtest_filter=-org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*',
         ],
         'swarming': {
           'shards': 20,
         },
-        'mixins': [
-          'skia_gold_test',
-          'emulator-8-cores',  # Use 8-core to shorten test runtime.
-        ],
       },
       'chrome_public_test_apk_with_playstore': {
-        'args': [
-            # These tests launch external intent thus require playstore to be
-            # present. See crbug.com/1056330 for more details.
-            # They should be ran in emulator on images that have playstore.
-            '--gtest_filter='
-            'org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:'
-            'org.chromium.shape_detection.*'
-        ],
+        'test': 'chrome_public_test_apk',
         'mixins': [
           'skia_gold_test',
         ],
-        'test': 'chrome_public_test_apk',
+        'args': [
+          '--gtest_filter=org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*',
+        ],
       },
       'chrome_public_unit_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+        ],
         'swarming': {
           'shards': 4,
         },
-        'mixins': [
-          'skia_gold_test',
-        ],
       },
     },
 
     'android_finch_smoke_tests': {
       'chrome_finch_smoke_tests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
         'args': [
           '--finch-seed-path',
           '../../variations_seed',
         ],
-        'mixins': [
-          'skia_gold_test',
-        ],
       },
       'monochrome_finch_smoke_tests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
         'args': [
           '--finch-seed-path',
           '../../variations_seed',
         ],
-        'mixins': [
-          'skia_gold_test',
-        ],
       },
       'variations_smoke_tests': {
         'test': 'variations_desktop_smoke_tests',
-        'args': [
-          '--target-platform=android',
-        ],
         'mixins': [
           'skia_gold_test',
           'has_native_resultdb_integration',
         ],
+        'args': [
+          '--target-platform=android',
+        ],
       },
     },
 
@@ -177,7 +150,7 @@
         ],
         'resultdb': {
           'enable': True,
-          'result_format': 'single'
+          'result_format': 'single',
         },
       },
     },
@@ -189,12 +162,12 @@
 
     'android_oreo_standard_gtests': {
       'chrome_public_test_apk': {
-        'swarming': {
-          'shards': 5,
-        },
         'mixins': [
           'skia_gold_test',
         ],
+        'swarming': {
+          'shards': 5,
+        },
       },
       'chrome_public_unit_test_apk': {
         'mixins': [
@@ -203,14 +176,12 @@
       },
       'webview_instrumentation_test_apk': {
         'swarming': {
-          'expiration': 10800,
           'shards': 5,
+          'expiration': 10800,
         },
       },
     },
 
-    # TODO(crbug.com/1111436): Deprecate this group in favor of
-    # android_pie_rel_gtests if/when android Pie capacity is fully restored.
     'android_pie_rel_reduced_capacity_gtests': {
       'android_browsertests': {},
       'blink_platform_unittests': {},
@@ -239,12 +210,12 @@
         },
       },
       'android_sync_integration_tests': {
-        'swarming': {
-          'shards': 1,
-        },
         'args': [
           '--test-launcher-batch-limit=1',
         ],
+        'swarming': {
+          'shards': 1,
+        },
       },
       'android_webview_unittests': {},
       'content_shell_test_apk': {
@@ -254,20 +225,11 @@
       },
       'gl_tests_validating': {
         'test': 'gl_tests',
-        # TODO(kbr): these are actually run on many of the GPU bots, which have
-        # physical hardware for several of the desktop OSs. Once the GPU JSON
-        # generation script is merged with this one, this should be promoted from
-        # the Android-specific section.
         'args': [
           '--use-cmd-decoder=validating',
         ],
       },
-      'gl_unittests': {
-        # TODO(kbr): these are actually run on many of the GPU bots, which have
-        # physical hardware for several of the desktop OSs. Once the GPU JSON
-        # generation script is merged with this one, this should be promoted from
-        # the Android-specific section.
-      },
+      'gl_unittests': {},
       'mojo_test_apk': {},
       'ui_android_unittests': {},
       'webview_instrumentation_test_apk': {
@@ -297,6 +259,11 @@
 
     'android_webview_gpu_telemetry_tests': {
       'android_webview_pixel_skia_gold_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -304,11 +271,6 @@
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'telemetry_test_name': 'pixel',
       },
     },
 
@@ -322,12 +284,12 @@
 
     'ash_pixel_gtests': {
       'ash_pixeltests': {
-         'args': [
-          '--enable-pixel-output-in-tests',
-        ],
         'mixins': [
           'skia_gold_test',
         ],
+        'args': [
+          '--enable-pixel-output-in-tests',
+        ],
       },
     },
 
@@ -339,37 +301,37 @@
 
     'bfcache_android_specific_gtests': {
       'bf_cache_android_browsertests': {
+        'test': 'android_browsertests',
         'args': [
           '--disable-features=BackForwardCache',
         ],
         'swarming': {
           'shards': 2,
         },
-        'test': 'android_browsertests',
       },
     },
 
     'bfcache_generic_gtests': {
       'bf_cache_content_browsertests': {
+        'test': 'content_browsertests',
         'args': [
           '--disable-features=BackForwardCache',
         ],
         'swarming': {
           'shards': 20,
         },
-        'test': 'content_browsertests',
       },
     },
 
     'bfcache_linux_specific_gtests': {
       'bf_cache_browser_tests': {
+        'test': 'browser_tests',
         'args': [
           '--disable-features=BackForwardCache',
         ],
         'swarming': {
           'shards': 10,
         },
-       'test': 'browser_tests',
       },
     },
 
@@ -393,7 +355,7 @@
           '--test-launcher-jobs=1',
         ],
         'swarming': {
-          'can_use_on_swarming_builders': False,  # https://crbug.com/861753
+          'can_use_on_swarming_builders': False,
         },
       },
       'cast_shell_unittests': {},
@@ -413,11 +375,12 @@
         'experiment_percentage': 100,
       },
     },
+
     'chrome_android_finch_smoke_tests': {
       'variations_android_smoke_tests': {
         'test': 'variations_desktop_smoke_tests',
         'mixins': [
-          'has_native_resultdb_integration'
+          'has_native_resultdb_integration',
         ],
         'args': [
           '--target-platform=android',
@@ -425,37 +388,39 @@
       },
       'variations_webview_smoke_tests': {
         'test': 'variations_desktop_smoke_tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--target-platform=webview',
         ],
-        'mixins': [
-          'has_native_resultdb_integration'
-        ],
       },
     },
+
     'chrome_finch_smoke_tests': {
       'variations_desktop_smoke_tests': {
         'test': 'variations_desktop_smoke_tests',
-        'lacros_args': [
-          '--target-platform=lacros',
-        ],
-        'chromeos_args': [
-          '--target-platform=cros',
-        ],
         'mixins': [
           'skia_gold_test',
           'has_native_resultdb_integration',
         ],
+        'chromeos_args': [
+          '--target-platform=cros',
+        ],
+        'lacros_args': [
+          '--target-platform=lacros',
+        ],
       },
     },
+
     'chrome_isolated_script_tests': {
       'chrome_sizes': {
-        'merge': {
-          'script': '//tools/perf/process_perf_results.py',
-        },
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
       },
       'variations_smoke_tests': {
         'test': 'variations_smoke_tests',
@@ -464,7 +429,7 @@
         ],
         'resultdb': {
           'enable': True,
-          'result_format': 'single'
+          'result_format': 'single',
         },
       },
     },
@@ -475,33 +440,34 @@
 
     'chrome_profile_generator_tests': {
       'chrome_public_apk_profile_tests': {
+        'test': 'chrome_public_apk_baseline_profile_generator',
         'ci_only': True,
         'experiment_percentage': 100,
-        'test':'chrome_public_apk_baseline_profile_generator',
       },
     },
 
     'chrome_public_tests': {
       'chrome_public_test_apk': {
+        'mixins': [
+          'skia_gold_test',
+        ],
         'swarming': {
           'shards': 19,
         },
+      },
+      'chrome_public_unit_test_apk': {
         'mixins': [
           'skia_gold_test',
         ],
-      },
-      'chrome_public_unit_test_apk': {
         'swarming': {
           'shards': 2,
         },
-        'mixins': [
-          'skia_gold_test',
-        ],
       },
     },
 
     'chrome_public_wpt': {
       'chrome_public_wpt': {
+        'results_handler': 'layout tests',
         'args': [
           '--no-wpt-internal',
         ],
@@ -511,43 +477,30 @@
           'hard_timeout': 14400,
         },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
-        'results_handler': 'layout tests',
       },
     },
 
     'chrome_sizes': {
       'chrome_sizes': {
-        'merge': {
-          'script': '//tools/perf/process_perf_results.py',
-        },
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
       },
     },
 
     'chrome_sizes_android': {
       'chrome_sizes': {
-        'merge': {
-          'script': '//tools/perf/process_perf_results.py',
-        },
         'mixins': [
           'has_native_resultdb_integration',
         ],
-        'args': [
-          '--platform=android',
-        ],
-        'swarming': {
-          "dimensions": {
-            "cpu": "x86-64",
-            "os": "Ubuntu-22.04"
-          },
-        },
         'remove_mixins': [
           'android_r',
           'bullhead',
@@ -559,6 +512,18 @@
           'pie_fleet',
           'walleye',
         ],
+        'args': [
+          '--platform=android',
+        ],
+        'swarming': {
+          'dimensions': {
+            'cpu': 'x86-64',
+            'os': 'Ubuntu-22.04',
+          },
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
       },
     },
 
@@ -582,83 +547,66 @@
 
     'chromeos_browser_all_tast_tests': {
       'chrome_all_tast_tests': {
-        'swarming': {
-          'idempotent': False,  # https://crbug.com/923426#c27
-          # Tast test doesn't always output. See crbug.com/1306300
-          'io_timeout': 3600,
-          'shards': 10,
-        },
-        'args': [
-          '--tast-retries=1',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'args': [
+          '--tast-retries=1',
+        ],
+        'swarming': {
+          'shards': 10,
+          'io_timeout': 3600,
+          'idempotent': False,
+        },
       },
     },
 
     'chromeos_browser_integration_tests': {
       'disk_usage_tast_test': {
-        "args": [
-          # Stripping gives more accurate disk usage data.
-          "--strip-chrome",
-        ],
-        'merge': {
-          'script': '//tools/perf/process_perf_results.py',
-        },
-        'swarming': {
-          'idempotent': False,  # https://crbug.com/923426#c27
-        },
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'args': [
+          '--strip-chrome',
+        ],
+        'swarming': {
+          'idempotent': False,
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
       },
     },
 
     'chromeos_chrome_all_tast_tests': {
       'chrome_all_tast_tests': {
-        'shards': 10,
-        # `tast_expr` must be a non-empty string to run the tast tests. But the value of
-        # would be overridden by `tast_arrt_expr` defined in chromeos/BUILD.gn, so that we
-        # put the stub string here.
         'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS',
         'test_level_retries': 2,
         'timeout_sec': 21600,
+        'shards': 10,
       },
     },
 
-    # Test suite for running critical Tast tests.
     'chromeos_chrome_criticalstaging_tast_tests': {
       'chrome_criticalstaging_tast_tests': {
-        'shards': 3,
-        # `tast_expr` must be a non-empty string to run the tast tests. But the value of
-        # would be overridden by `tast_arrt_expr` defined in chromeos/BUILD.gn, so that we
-        # put the stub string here.
         'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS',
         'test_level_retries': 2,
         'timeout_sec': 7200,
+        'shards': 3,
         'experiment_percentage': 100,
       },
     },
 
-    # Test suite for running disabled Tast tests to collect data to re-enable
-    # them. The test suite should not be critical to builders.
     'chromeos_chrome_disabled_tast_tests': {
       'chrome_disabled_tast_tests': {
-        'shards': 2,
-        # `tast_expr` must be a non-empty string to run the tast tests. But the value of
-        # would be overridden by `tast_arrt_expr` defined in chromeos/BUILD.gn, so that we
-        # put the stub string here.
         'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS',
         'test_level_retries': 1,
         'timeout_sec': 7200,
+        'shards': 2,
         'experiment_percentage': 100,
       },
     },
 
-    # GTests to run on Chrome OS devices, but not Chrome OS VMs. Any differences
-    # between this and chromeos_system_friendly_gtests below should only be due
-    # to resource constraints (ie: not enough devices).
     'chromeos_device_only_gtests': {
       'base_unittests': {
         'args': [
@@ -672,60 +620,49 @@
         'ci_only': True,
       },
     },
+
     'chromeos_isolated_scripts': {
       'telemetry_perf_unittests': {
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--browser=cros-chrome',
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
           '--xvfb',
-          # 3 is arbitrary, but if we're having more than 3 of these tests
-          # fail in a single shard, then something is probably wrong, so fail
-          # fast.
           '--typ-max-failures=3',
         ],
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
           'shards': 12,
+          'idempotent': False,
         },
+      },
+      'telemetry_unittests': {
         'mixins': [
           'has_native_resultdb_integration',
         ],
-      },
-      'telemetry_unittests': {
         'args': [
           '--jobs=1',
           '--browser=cros-chrome',
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
-          # 3 is arbitrary, but if we're having more than 3 of these tests
-          # fail in a single shard, then something is probably wrong, so fail
-          # fast.
           '--typ-max-failures=3',
         ],
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
           'shards': 24,
+          'idempotent': False,
         },
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
-    'chromeos_js_code_coverage_browser_tests' : {
+    'chromeos_js_code_coverage_browser_tests': {
       'chromeos_js_code_coverage_browser_tests': {
-        'args': [],
+        'test': 'browser_tests',
         'swarming': {
           'shards': 16,
         },
-        'test': 'browser_tests',
-      }
+      },
     },
 
-    # Tests that run on Chrome OS systems (ie: VMs, Chromebooks), *not*
-    # linux-chromeos.
-    # NOTE: We only want a small subset of test suites here, because most
-    # suites assume that they stub out the underlying device hardware.
-    # https://crbug.com/865693
     'chromeos_system_friendly_gtests': {
       'aura_unittests': {
         'args': [
@@ -736,8 +673,6 @@
       'capture_unittests': {
         'args': [
           '--test-launcher-jobs=1',
-          # Don't run CaptureMJpeg tests on ChromeOS VM because vivid,
-          # which is the virtual video capture device, doesn't support MJPEG.
           '--gtest_filter=-*UsingRealWebcam_CaptureMjpeg*',
         ],
       },
@@ -746,8 +681,12 @@
       'display_unittests': {},
       'fake_libva_driver_unittest': {
         'args': [
-          '--env-var', 'LIBVA_DRIVERS_PATH', './',
-          '--env-var', 'LIBVA_DRIVER_NAME', 'libfake',
+          '--env-var',
+          'LIBVA_DRIVERS_PATH',
+          './',
+          '--env-var',
+          'LIBVA_DRIVER_NAME',
+          'libfake',
         ],
         'experiment_percentage': 100,
       },
@@ -762,33 +701,25 @@
       },
       'midi_unittests': {},
       'mojo_unittests': {},
-      # net_unittests has a test-time dependency on vpython. So add a CIPD'ed
-      # vpython of the right arch to the task, and tell the test runner to copy
-      # it over to the VM before the test runs.
       'net_unittests': {
         'args': [
           '--vpython-dir=../../vpython_dir_linux_amd64',
-          # PythonUtils.PythonRunTime (as opposed to Python3RunTime) requires a
-          # copy of Python 2, but it's testing test helpers that are only used
-          # outside of net_unittests. This bot runs out of space if trying to
-          # ship two vpythons, so we exclude Python 2 and the one test which
-          # uses it.
           '--gtest_filter=-PythonUtils.PythonRunTime',
         ],
         'swarming': {
+          'shards': 3,
           'cipd_packages': [
             {
-              "cipd_package": 'infra/3pp/tools/cpython3/linux-amd64',
+              'cipd_package': 'infra/3pp/tools/cpython3/linux-amd64',
               'location': 'vpython_dir_linux_amd64',
               'revision': 'version:2@3.8.10.chromium.21',
             },
             {
-              "cipd_package": 'infra/tools/luci/vpython/linux-amd64',
+              'cipd_package': 'infra/tools/luci/vpython/linux-amd64',
               'location': 'vpython_dir_linux_amd64',
               'revision': 'git_revision:0f694cdc06ba054b9960aa1ae9766e45b53d02c1',
-            }
+            },
           ],
-          'shards': 3,
         },
       },
       'ozone_gl_unittests': {
@@ -811,10 +742,12 @@
       'vaapi_unittest': {
         'args': [
           '--stop-ui',
-          # Tell libva to do dummy encoding/decoding. For more info, see:
-          # https://github.com/intel/libva/blob/master/va/va_fool.c#L47
-          '--env-var', 'LIBVA_DRIVERS_PATH', './',
-          '--env-var', 'LIBVA_DRIVER_NAME', 'libfake',
+          '--env-var',
+          'LIBVA_DRIVERS_PATH',
+          './',
+          '--env-var',
+          'LIBVA_DRIVER_NAME',
+          'libfake',
           '--gtest_filter="VaapiTest.*"',
         ],
       },
@@ -842,7 +775,7 @@
       'content_browsertests': {
         'swarming': {
           'shards': 4,
-        }
+        },
       },
       'content_unittests': {},
       'interactive_ui_tests': {},
@@ -861,18 +794,18 @@
       },
       'browser_tests': {
         'swarming': {
+          'shards': 8,
           'dimensions': {
             'cores': '8',
           },
-          'shards': 8,
         },
       },
       'content_browsertests': {
         'swarming': {
+          'shards': 5,
           'dimensions': {
             'cores': '8',
           },
-          'shards': 5,
         },
       },
       'content_unittests': {
@@ -884,10 +817,10 @@
       },
       'interactive_ui_tests': {
         'swarming': {
+          'shards': 3,
           'dimensions': {
             'cores': '8',
           },
-          'shards': 3,
         },
       },
       'net_unittests': {
@@ -934,12 +867,12 @@
         },
       },
       'content_browsertests': {
-        'android_swarming': {
-          'shards': 15,
-        },
         'swarming': {
           'shards': 8,
         },
+        'android_swarming': {
+          'shards': 15,
+        },
       },
       'content_unittests': {
         'android_swarming': {
@@ -973,8 +906,6 @@
         },
       },
       'perfetto_unittests': {},
-       # TODO(crbug.com/1459686): Enable this.
-       # 'rust_gtest_interop_unittests': {},
       'services_unittests': {},
       'shell_dialogs_unittests': {},
       'skia_unittests': {},
@@ -1020,9 +951,6 @@
     },
 
     'chromium_gtests_for_win_and_linux_only': {
-      # pthreadpool is only built on Windows and Linux platforms, that is
-      # determined by `build_tflite_with_xnnpack` defined in
-      # third_party/tflite/features.gni.
       'pthreadpool_unittests': {
         'ci_only': True,
       },
@@ -1045,7 +973,7 @@
           'nougat-x86-emulator',
         ],
       },
-      'build_junit_tests':{
+      'build_junit_tests': {
         'remove_mixins': [
           'nougat-x86-emulator',
         ],
@@ -1174,7 +1102,7 @@
         ],
         'use_isolated_scripts_api': True,
       },
-      'build_junit_tests':{
+      'build_junit_tests': {
         'mixins': [
           'x86-64',
           'linux-jammy',
@@ -1472,118 +1400,97 @@
       },
     },
 
-    # On some bots we don't have capacity to run all standard tests (for example
-    # Android Pie), however there are tracing integration tests we want to
-    # ensure are still working.
     'chromium_tracing_gtests': {
       'services_unittests': {},
     },
 
     'chromium_web_tests_high_dpi_isolated_scripts': {
       'high_dpi_blink_web_tests': {
-        # high_dpi_blink_web_tests provides coverage for
-        # running Layout Tests with forced device scale factor.
-        'args': [
-          '--flag-specific=highdpi',
-          '--skipped=always',
-
-          # layout test failures are retried 3 times when '--test-list' is not
-          # passed, but 0 times when '--test-list' is passed. We want to always
-          # retry 3 times, so we explicitly specify it.
-          '--num-retries=3',
-        ],
         'test': 'blink_web_tests',
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--flag-specific=highdpi',
+          '--skipped=always',
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 1,
         },
-      },
-      'high_dpi_blink_wpt_tests': {
-        # high_dpi_blink_wpt_tests provides coverage for
-        # running Layout Tests with forced device scale factor.
-        'args': [
-          '--flag-specific=highdpi',
-          '--skipped=always',
-
-          # layout test failures are retried 3 times when '--test-list' is not
-          # passed, but 0 times when '--test-list' is passed. We want to always
-          # retry 3 times, so we explicitly specify it.
-          '--num-retries=3',
-        ],
-        'test': 'blink_wpt_tests',
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
+      },
+      'high_dpi_blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--flag-specific=highdpi',
+          '--skipped=always',
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 3,
         },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
     },
 
     'chromium_webkit_isolated_scripts': {
       'blink_web_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-        ],
         'test': 'blink_web_tests',
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 5,
-        }
-      },
-      'blink_wpt_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-        ],
-        'test': 'blink_wpt_tests',
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
+      },
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 7,
-        }
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
     },
 
@@ -1599,7 +1506,7 @@
       },
     },
 
-    'clang_tot_gtests' : {
+    'clang_tot_gtests': {
       'base_unittests': {},
     },
 
@@ -1645,12 +1552,12 @@
       'content_shell_crash_test': {
         'resultdb': {
           'enable': True,
-          'result_format': 'single'
-        }
+          'result_format': 'single',
+        },
       },
       'telemetry_gpu_unittests': {
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
@@ -1659,12 +1566,11 @@
       'telemetry_perf_unittests': {
         'args': [
           '--xvfb',
-          # TODO(crbug.com/1077284): Remove this once Crashpad is the default.
           '--extra-browser-args=--enable-crashpad',
         ],
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
           'shards': 12,
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
@@ -1673,13 +1579,11 @@
       'telemetry_unittests': {
         'args': [
           '--jobs=1',
-          # Disable GPU compositing, telemetry_unittests runs on VMs.
-          # https://crbug.com/871955
           '--extra-browser-args=--disable-gpu',
         ],
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
           'shards': 4,
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
@@ -1687,155 +1591,156 @@
       },
     },
 
-    'components_perftests_isolated_scripts' : {
+    'components_perftests_isolated_scripts': {
       'components_perftests': {
+        'args': [
+          '--gtest-benchmark-name=components_perftests',
+        ],
         'merge': {
           'script': '//tools/perf/process_perf_results.py',
           'args': [
             '--smoke-test-mode',
           ],
         },
-        'args': [
-          '--gtest-benchmark-name=components_perftests',
-        ],
       },
     },
 
-    # TODO(crbug.com/1444855): Delete the cr23_{linux,mac,win}_gtest suites
-    # after the ChromeRefresh2023 is fully rolled out.
     'cr23_linux_gtests': {
       'cr23_browser_tests': {
-        'args': [
-          ('--test-launcher-filter-file='
-           '../../testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter'
-          ),
+        'test': 'browser_tests',
+        'mixins': [
+          'chrome-refresh-2023',
         ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_browser_tests.filter',
+        ],
+        'ci_only': True,
         'swarming': {
           'shards': 20,
         },
-        'ci_only': True,
-        'test': 'browser_tests',
-        'mixins': [ 'chrome-refresh-2023' ],
       },
       'cr23_interactive_ui_tests': {
-        'args': [
-          ('--test-launcher-filter-file='
-           '../../testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter'
-          ),
+        'test': 'interactive_ui_tests',
+        'mixins': [
+          'chrome-refresh-2023',
         ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.linux.cr23_interactive_ui_tests.filter',
+        ],
+        'ci_only': True,
         'swarming': {
           'shards': 10,
         },
-        'ci_only': True,
-        'test': 'interactive_ui_tests',
-        'mixins': [ 'chrome-refresh-2023' ],
       },
       'cr23_views_unittests': {
-        'ci_only': True,
         'test': 'views_unittests',
-        'mixins': [ 'chrome-refresh-2023' ],
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'ci_only': True,
       },
     },
+
     'cr23_mac_gtests': {
       'cr23_browser_tests': {
-        'args': [
-          ('--test-launcher-filter-file='
-           '../../testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter'
-          ),
+        'test': 'browser_tests',
+        'mixins': [
+          'chrome-refresh-2023',
         ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_browser_tests.filter',
+        ],
+        'ci_only': True,
         'swarming': {
           'shards': 20,
         },
-        'ci_only': True,
-        'test': 'browser_tests',
-        'mixins': [ 'chrome-refresh-2023' ],
       },
       'cr23_interactive_ui_tests': {
-        'args': [
-          ('--test-launcher-filter-file='
-           '../../testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter'
-          ),
+        'test': 'interactive_ui_tests',
+        'mixins': [
+          'chrome-refresh-2023',
         ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.mac.cr23_interactive_ui_tests.filter',
+        ],
+        'ci_only': True,
         'swarming': {
           'shards': 10,
         },
-        'ci_only': True,
-        'test': 'interactive_ui_tests',
-        'mixins': [ 'chrome-refresh-2023' ],
       },
       'cr23_views_unittests': {
-        'ci_only': True,
         'test': 'views_unittests',
-        'mixins': [ 'chrome-refresh-2023' ],
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'ci_only': True,
       },
     },
+
     'cr23_pixel_browser_tests_gtests': {
       'cr23_pixel_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'skia_gold_test',
+          'chrome-refresh-2023',
+        ],
         'args': [
           '--browser-ui-tests-verify-pixels',
           '--enable-pixel-output-in-tests',
-          ('--test-launcher-filter-file='
-           '../../testing/buildbot/filters/pixel_tests.filter;'
-           '../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter'
-          ),
+          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter',
           '--test-launcher-jobs=1',
         ],
         'swarming': {
           'shards': 3,
         },
-        'test': 'browser_tests',
+      },
+      'cr23_pixel_interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
         'mixins': [
           'skia_gold_test',
           'chrome-refresh-2023',
         ],
-      },
-      'cr23_pixel_interactive_ui_tests': {
         'args': [
           '--browser-ui-tests-verify-pixels',
           '--enable-pixel-output-in-tests',
-          ('--test-launcher-filter-file='
-           '../../testing/buildbot/filters/pixel_tests.filter;'
-           '../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter'
-          ),
-        ],
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'skia_gold_test',
-          'chrome-refresh-2023',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter;../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter',
         ],
       },
     },
+
     'cr23_win_gtests': {
       'cr23_browser_tests': {
-        'args': [
-          ('--test-launcher-filter-file='
-           '../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter'
-          ),
+        'test': 'browser_tests',
+        'mixins': [
+          'chrome-refresh-2023',
         ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_browser_tests.filter',
+        ],
+        'ci_only': True,
         'swarming': {
           'shards': 20,
         },
-        'ci_only': True,
-        'test': 'browser_tests',
-        'mixins': [ 'chrome-refresh-2023' ],
       },
       'cr23_interactive_ui_tests': {
-        'args': [
-          ('--test-launcher-filter-file='
-           '../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter'
-          ),
+        'test': 'interactive_ui_tests',
+        'mixins': [
+          'chrome-refresh-2023',
         ],
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/cr23.win.cr23_interactive_ui_tests.filter',
+        ],
+        'ci_only': True,
         'swarming': {
           'shards': 10,
         },
-        'ci_only': True,
-        'test': 'interactive_ui_tests',
-        'mixins': [ 'chrome-refresh-2023' ],
       },
       'cr23_views_unittests': {
-        'ci_only': True,
         'test': 'views_unittests',
-        'mixins': [ 'chrome-refresh-2023' ],
+        'mixins': [
+          'chrome-refresh-2023',
+        ],
+        'ci_only': True,
       },
     },
 
@@ -1855,42 +1760,24 @@
 
     'cronet_resource_sizes': {
       'resource_sizes_cronet_sample_apk': {
+        'swarming': {
+          'dimensions': {
+            'os': 'Ubuntu-22.04',
+            'cpu': 'x86-64',
+          },
+        },
         'merge': {
           'script': '//tools/perf/process_perf_results.py',
         },
-        'swarming': {
-          # This suite simply analyzes build targets without running them.
-          # It can thus run on a standard linux machine w/o a device.
-          'dimensions': {
-            'os': 'Ubuntu-22.04',
-            'cpu': 'x86-64'
-          },
-        },
         'resultdb': {
           'enable': True,
-          'result_format': 'single'
+          'result_format': 'single',
         },
       },
     },
 
     'cronet_sizes': {
       'cronet_sizes': {
-        'merge': {
-          'script': '//tools/perf/process_perf_results.py',
-        },
-        'swarming': {
-          # This suite simply analyzes build targets without running them.
-          # It can thus run on a standard linux machine w/o a device.
-          'dimensions': {
-            'os': 'Ubuntu-22.04',
-            'cpu': 'x86-64'
-          },
-        },
-        'resultdb': {
-          'enable': True,
-          'result_format': 'single',
-          'result_file': '${ISOLATED_OUTDIR}/sizes/test_results.json'
-        },
         'remove_mixins': [
           'android_r',
           'bullhead',
@@ -1902,6 +1789,20 @@
           'pie_fleet',
           'walleye',
         ],
+        'swarming': {
+          'dimensions': {
+            'os': 'Ubuntu-22.04',
+            'cpu': 'x86-64',
+          },
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
+        'resultdb': {
+          'enable': True,
+          'result_format': 'single',
+          'result_file': '${ISOLATED_OUTDIR}/sizes/test_results.json',
+        },
       },
     },
 
@@ -1909,65 +1810,59 @@
       'blink_python_tests': {
         'resultdb': {
           'enable': True,
-        }
+        },
       },
       'blink_web_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-        ],
         'test': 'blink_web_tests',
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 5,
-        }
-      },
-      'blink_wpt_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-        ],
-        'test': 'blink_wpt_tests',
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
+      },
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 7,
-        }
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
       'content_shell_crash_test': {
         'resultdb': {
           'enable': True,
-          'result_format': 'single'
-        }
+          'result_format': 'single',
+        },
       },
       'flatbuffers_unittests': {
         'resultdb': {
           'enable': True,
-          'result_format': 'single'
-        }
+          'result_format': 'single',
+        },
       },
       'grit_python_unittests': {
         'resultdb': {
@@ -1976,7 +1871,7 @@
       },
       'telemetry_gpu_unittests': {
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
@@ -1985,32 +1880,29 @@
       'telemetry_unittests': {
         'args': [
           '--jobs=1',
-          # Disable GPU compositing, telemetry_unittests runs on VMs.
-          # https://crbug.com/871955
           '--extra-browser-args=--disable-gpu',
         ],
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
           'shards': 8,
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
         },
       },
       'views_perftests': {
+        'args': [
+          '--gtest-benchmark-name=views_perftests',
+        ],
         'merge': {
           'script': '//tools/perf/process_perf_results.py',
           'args': [
             '--smoke-test-mode',
           ],
         },
-        'args': [
-          '--gtest-benchmark-name=views_perftests',
-        ],
       },
     },
 
-    # Script tests that only need to run on one builder per desktop platform.
     'desktop_once_isolated_scripts': {
       'test_env_py_unittests': {
         'resultdb': {
@@ -2024,156 +1916,142 @@
       },
     },
 
-    'devtools_browser_tests' : {
+    'devtools_browser_tests': {
       'devtools_browser_tests': {
+        'test': 'browser_tests',
         'args': [
           '--gtest_filter=*DevTools*',
         ],
         'swarming': {
           'shards': 1,
         },
-        'test': 'browser_tests',
-      }
+      },
     },
 
-
     'devtools_webkit_and_tab_target_isolated_scripts': {
       'blink_web_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-        ],
         'test': 'blink_web_tests',
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 5,
-        }
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
       'blink_web_tests_dt_tab_target': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
         'args': [
           '--flag-specific=devtools-tab-target',
           '--num-retries=3',
           'http/tests/devtools',
         ],
-        'test': 'blink_web_tests',
+        'swarming': {
+          'shards': 5,
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
+      },
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 5,
-        }
-      },
-      'blink_wpt_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
         'args': [
           '--num-retries=3',
         ],
-        'test': 'blink_wpt_tests',
+        'swarming': {
+          'shards': 7,
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
-        'mixins': [
-          'has_native_resultdb_integration',
-          'blink_tests_write_run_histories',
-        ],
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 7,
-        }
       },
     },
 
     'devtools_webkit_isolated_scripts': {
       'blink_web_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-        ],
         'test': 'blink_web_tests',
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 5,
-        }
-      },
-      'blink_wpt_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
-        'args': [
-          '--num-retries=3',
-        ],
-        'test': 'blink_wpt_tests',
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
+      },
+      'blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 7,
-        }
+        },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
     },
 
     'fieldtrial_android_tests': {
       'android_browsertests_no_fieldtrial': {
+        'test': 'android_browsertests',
         'args': [
           '--disable-field-trial-config',
         ],
         'ci_only': True,
-        'test': 'android_browsertests',
         'swarming': {
           'shards': 3,
         },
       },
     },
+
     'fieldtrial_browser_tests': {
       'browser_tests_no_field_trial': {
+        'test': 'browser_tests',
         'args': [
           '--disable-field-trial-config',
         ],
@@ -2181,37 +2059,37 @@
         'swarming': {
           'shards': 10,
         },
-        'test': 'browser_tests',
       },
       'components_browsertests_no_field_trial': {
+        'test': 'components_browsertests',
         'args': [
           '--disable-field-trial-config',
         ],
         'ci_only': True,
-        'test': 'components_browsertests',
       },
       'interactive_ui_tests_no_field_trial': {
+        'test': 'interactive_ui_tests',
         'args': [
           '--disable-field-trial-config',
         ],
         'ci_only': True,
-        'test': 'interactive_ui_tests',
       },
       'sync_integration_tests_no_field_trial': {
+        'test': 'sync_integration_tests',
         'args': [
           '--disable-field-trial-config',
         ],
         'ci_only': True,
-        'test': 'sync_integration_tests',
       },
     },
+
     'finch_smoke_tests': {
-      # TODO(crbug.com/1227222): Change this to the actual finch smoke test
-      # once it exists.
       'base_unittests': {},
     },
+
     'fuchsia_accessibility_content_browsertests': {
       'accessibility_content_browsertests': {
+        'test': 'content_browsertests',
         'args': [
           '--gtest_filter=*All/DumpAccessibility*/fuchsia*',
           '--test-arg=--disable-gpu',
@@ -2219,9 +2097,8 @@
           '--test-arg=--ozone-platform=headless',
         ],
         'swarming': {
-          'shards': 8,  # this may depend on runtime of a11y CQ
+          'shards': 8,
         },
-        'test': 'content_browsertests',
       },
     },
 
@@ -2296,12 +2173,12 @@
       'mojo_unittests': {},
       'native_theme_unittests': {},
       'net_unittests': {
-        'swarming': {
-          'shards': 4,
-        },
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter',
         ],
+        'swarming': {
+          'shards': 4,
+        },
       },
       'ozone_gl_unittests': {
         'args': [
@@ -2310,8 +2187,6 @@
       },
       'ozone_unittests': {},
       'perfetto_unittests': {},
-      # TODO(crbug.com/1459686): Enable this.
-      # 'rust_gtest_interop_unittests': {},
       'service_manager_unittests': {},
       'services_unittests': {
         'args': [
@@ -2351,10 +2226,6 @@
       },
     },
 
-    # This is a set of selected tests to test the test facility only. The
-    # principle of the selection includes time cost, scenario coverage,
-    # stability, etc; and it's subject to change. In theory, it should only be
-    # used by the EngProd team to verify a new test facility setup.
     'fuchsia_facility_gtests': {
       'aura_unittests': {},
       'blink_common_unittests': {},
@@ -2371,13 +2242,13 @@
 
     'fuchsia_sizes_tests': {
       'fuchsia_sizes': {
-        'merge': {
-          'script': '//tools/perf/process_perf_results.py',
-        },
         'args': [
           '--sizes-path',
           'tools/fuchsia/size_tests/fyi_sizes_smoketest.json',
         ],
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+        },
       },
     },
 
@@ -2387,7 +2258,9 @@
         'args': [
           '--use-cmd-decoder=passthrough',
         ],
-        'linux_args': ['--no-xvfb'],
+        'linux_args': [
+          '--no-xvfb',
+        ],
         'swarming': {
           'shards': 2,
         },
@@ -2407,7 +2280,7 @@
             'cpu': 'x86-64',
             'os': 'Mac-13',
           },
-        }
+        },
       },
       'content_unittests': {
         'swarming': {
@@ -2419,14 +2292,14 @@
       },
     },
 
-    # BEGIN tests which run on the GPU bots
-
     'gpu_angle_fuchsia_unittests_isolated_scripts': {
       'angle_unittests': {
+        'mixins': [
+          'fuchsia_logs',
+        ],
         'args': [
           'bin/run_angle_unittests',
         ],
-        'mixins': ['fuchsia_logs'],
       },
     },
 
@@ -2453,15 +2326,16 @@
         'android_args': [
           '-v',
         ],
-        'linux_args': ['--no-xvfb'],
+        'linux_args': [
+          '--no-xvfb',
+        ],
         'use_isolated_scripts_api': True,
       },
     },
 
-    # The command buffer perf tests are only run on Windows.
-    # They are mostly driver and platform independent.
     'gpu_command_buffer_perf_passthrough_isolated_scripts': {
       'passthrough_command_buffer_perftests': {
+        'test': 'command_buffer_perftests',
         'args': [
           '--gtest-benchmark-name=passthrough_command_buffer_perftests',
           '-v',
@@ -2469,7 +2343,6 @@
           '--use-angle=gl-null',
           '--fast-run',
         ],
-        'test': 'command_buffer_perftests',
         'merge': {
           'script': '//tools/perf/process_perf_results.py',
           'args': [
@@ -2482,11 +2355,13 @@
     'gpu_common_and_optional_telemetry_tests': {
       'info_collection_tests': {
         'telemetry_test_name': 'info_collection',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--expected-vendor-id',
           '${gpu_vendor_id}',
           '$$MAGIC_SUBSTITUTION_GPUExpectedDeviceId',
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--force_high_performance_gpu',
         ],
         'android_args': [
@@ -2502,11 +2377,11 @@
           '--use-weston',
           '--weston-use-gl',
         ],
+      },
+      'trace_test': {
         'mixins': [
           'has_native_resultdb_integration',
         ],
-      },
-      'trace_test': {
         'args': [
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
@@ -2523,17 +2398,13 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
-    # GPU gtests which run on both the main and FYI waterfalls.
     'gpu_common_gtests_passthrough': {
       'gl_tests_passthrough': {
         'test': 'gl_tests',
-        'args' : [
+        'args': [
           '--use-cmd-decoder=passthrough',
           '--use-gl=angle',
         ],
@@ -2543,12 +2414,17 @@
         'desktop_args': [
           '--use-gpu-in-tests',
         ],
-        'linux_args': ['--no-xvfb'],
+        'linux_args': [
+          '--no-xvfb',
+        ],
         'swarming': {
           'shards': 2,
         },
       },
       'gl_unittests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
         'chromeos_args': [
           '--stop-ui',
           '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.gl_unittests.filter',
@@ -2559,15 +2435,13 @@
         'linux_args': [
           '--no-xvfb',
         ],
-        'mixins': [
-          'skia_gold_test',
-        ],
       },
     },
+
     'gpu_common_gtests_validating': {
       'gl_tests_validating': {
         'test': 'gl_tests',
-        'args' : [
+        'args': [
           '--use-cmd-decoder=validating',
         ],
         'chromeos_args': [
@@ -2577,9 +2451,14 @@
         'desktop_args': [
           '--use-gpu-in-tests',
         ],
-        'linux_args': ['--no-xvfb'],
+        'linux_args': [
+          '--no-xvfb',
+        ],
       },
       'gl_unittests': {
+        'mixins': [
+          'skia_gold_test',
+        ],
         'chromeos_args': [
           '--stop-ui',
           '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.gl_unittests.filter',
@@ -2590,17 +2469,13 @@
         'linux_args': [
           '--no-xvfb',
         ],
-        'mixins': [
-          'skia_gold_test',
-        ],
       },
     },
 
     'gpu_dawn_common_isolated_scripts': {
-      # Test that expectations files are well-formed.
       'telemetry_gpu_unittests': {
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
@@ -2608,83 +2483,103 @@
       },
     },
 
-    # GPU gtests that test only Dawn
     'gpu_dawn_gtests': {
       'dawn_end2end_implicit_device_sync_tests': {
-        'mixins': ['dawn_end2end_gpu_test'],
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
         'args': [
           '--enable-implicit-device-sync',
         ],
-        'linux_args': [ '--no-xvfb' ],
-        'test': 'dawn_end2end_tests',
-        'ci_only': True, # https://crbug.com/dawn/1749
+        'linux_args': [
+          '--no-xvfb',
+        ],
+        'ci_only': True,
       },
       'dawn_end2end_skip_validation_tests': {
-        'mixins': ['dawn_end2end_gpu_test'],
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
         'args': [
           '--enable-toggles=skip_validation',
         ],
-        'linux_args': [ '--no-xvfb' ],
-        'test': 'dawn_end2end_tests',
+        'linux_args': [
+          '--no-xvfb',
+        ],
       },
       'dawn_end2end_tests': {
-        'mixins': ['dawn_end2end_gpu_test'],
-        'linux_args': [ '--no-xvfb' ],
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
+        'linux_args': [
+          '--no-xvfb',
+        ],
       },
       'dawn_end2end_wire_tests': {
-        'mixins': ['dawn_end2end_gpu_test'],
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
         'args': [
           '--use-wire',
         ],
-        'linux_args': [ '--no-xvfb' ],
-        'test': 'dawn_end2end_tests',
+        'linux_args': [
+          '--no-xvfb',
+        ],
       },
     },
 
     'gpu_dawn_gtests_no_dxc': {
       'dawn_end2end_no_dxc_tests': {
-        'mixins': ['dawn_end2end_gpu_test'],
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
         'args': [
           '--disable-toggles=use_dxc',
         ],
-        'test': 'dawn_end2end_tests',
       },
     },
 
     'gpu_dawn_gtests_no_dxc_with_validation': {
       'dawn_end2end_no_dxc_validation_layers_tests': {
-        'mixins': ['dawn_end2end_gpu_test'],
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
         'args': [
           '--disable-toggles=use_dxc',
           '--enable-backend-validation',
         ],
-        'test': 'dawn_end2end_tests',
       },
     },
 
-    # GPU gtests that test only Dawn with backend validation layers
     'gpu_dawn_gtests_with_validation': {
       'dawn_end2end_validation_layers_tests': {
-        'mixins': ['dawn_end2end_gpu_test'],
+        'test': 'dawn_end2end_tests',
+        'mixins': [
+          'dawn_end2end_gpu_test',
+        ],
         'args': [
           '--enable-backend-validation',
         ],
-        'linux_args': [ '--no-xvfb' ],
-        'test': 'dawn_end2end_tests',
+        'linux_args': [
+          '--no-xvfb',
+        ],
       },
     },
 
     'gpu_dawn_perf_smoke_isolated_scripts': {
       'dawn_perf_tests': {
         'args': [
-          # Tell the tests to only run one step for faster iteration.
           '--override-steps=1',
           '--gtest-benchmark-name=dawn_perf_tests',
           '-v',
         ],
         'merge': {
           'script': '//tools/perf/process_perf_results.py',
-          # Does not upload to the perf dashboard
           'args': [
             '--smoke-test-mode',
           ],
@@ -2694,83 +2589,81 @@
 
     'gpu_dawn_web_platform_webgpu_cts_force_swiftshader': {
       'webgpu_swiftshader_web_platform_cts_tests': {
-        'args': [
-          '--use-webgpu-adapter=swiftshader',
-          '--test-filter=*web_platform*',
-        ],
+        'telemetry_test_name': 'webgpu_cts',
         'mixins': [
           'has_native_resultdb_integration',
           'webgpu_telemetry_cts',
         ],
+        'args': [
+          '--use-webgpu-adapter=swiftshader',
+          '--test-filter=*web_platform*',
+        ],
         'swarming': {
           'shards': 2,
         },
-        'telemetry_test_name': 'webgpu_cts',
       },
       'webgpu_swiftshader_web_platform_cts_with_validation_tests': {
+        'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
         'args': [
           '--use-webgpu-adapter=swiftshader',
           '--test-filter=*web_platform*',
           '--enable-dawn-backend-validation',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-          'webgpu_telemetry_cts',
-        ],
         'swarming': {
           'shards': 2,
         },
-        'telemetry_test_name': 'webgpu_cts',
       },
     },
 
     'gpu_dawn_webgpu_blink_web_tests': {
       'webgpu_blink_web_tests': {
         'test': 'webgpu_blink_web_tests',
-        'args': [
-          '--flag-specific=webgpu',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
           'webgpu_cts',
         ],
+        'args': [
+          '--flag-specific=webgpu',
+        ],
       },
       'webgpu_blink_web_tests_with_backend_validation': {
         'test': 'webgpu_blink_web_tests',
-        'args': [
-          '--flag-specific=webgpu-with-backend-validation',
-          # Increase the timeout when using backend validation layers (crbug.com/1208253)
-          '--timeout-ms=30000',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
           'webgpu_cts',
         ],
+        'args': [
+          '--flag-specific=webgpu-with-backend-validation',
+          '--timeout-ms=30000',
+        ],
       },
     },
 
     'gpu_dawn_webgpu_blink_web_tests_force_swiftshader': {
       'webgpu_swiftshader_blink_web_tests': {
         'test': 'webgpu_blink_web_tests',
-        'args': [
-          '--flag-specific=webgpu-swiftshader',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
           'webgpu_cts',
         ],
+        'args': [
+          '--flag-specific=webgpu-swiftshader',
+        ],
       },
       'webgpu_swiftshader_blink_web_tests_with_backend_validation': {
         'test': 'webgpu_blink_web_tests',
-        'args': [
-          '--flag-specific=webgpu-swiftshader-with-backend-validation',
-          # Increase the timeout when using backend validation layers (crbug.com/1208253)
-          '--timeout-ms=30000',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
           'webgpu_cts',
         ],
+        'args': [
+          '--flag-specific=webgpu-swiftshader-with-backend-validation',
+          '--timeout-ms=30000',
+        ],
       },
     },
 
@@ -2789,20 +2682,20 @@
         },
       },
       'webgpu_cts_with_validation_tests': {
-        'args': [
-          '--enable-dawn-backend-validation',
-        ],
+        'telemetry_test_name': 'webgpu_cts',
         'mixins': [
           'has_native_resultdb_integration',
           'webgpu_telemetry_cts',
         ],
+        'args': [
+          '--enable-dawn-backend-validation',
+        ],
         'swarming': {
           'shards': 14,
         },
         'android_swarming': {
           'shards': 36,
         },
-        'telemetry_test_name': 'webgpu_cts',
       },
     },
 
@@ -2822,120 +2715,110 @@
     'gpu_dawn_webgpu_cts_dxc': {
       'webgpu_cts_dxc_tests': {
         'telemetry_test_name': 'webgpu_cts',
-        'args': [
-          '--use-dxc',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
           'webgpu_telemetry_cts',
         ],
+        'args': [
+          '--use-dxc',
+        ],
+        'ci_only': True,
         'swarming': {
           'shards': 14,
         },
-        'ci_only': True,
       },
       'webgpu_cts_dxc_with_validation_tests': {
         'telemetry_test_name': 'webgpu_cts',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'webgpu_telemetry_cts',
+        ],
         'args': [
           '--enable-dawn-backend-validation',
           '--use-dxc',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-          'webgpu_telemetry_cts',
-        ],
+        'ci_only': True,
         'swarming': {
           'shards': 14,
         },
-        'ci_only': True,
       },
     },
 
     'gpu_default_and_optional_win_media_foundation_specific_gtests': {
-      # MediaFoundation browser tests, which currently only run on Windows OS,
-      # and require physical hardware.
       'media_foundation_browser_tests': {
+        'test': 'browser_tests',
         'args': [
           '--gtest_filter=MediaFoundationEncryptedMediaTest*',
-          '--use-gpu-in-tests'
+          '--use-gpu-in-tests',
         ],
-        'test': 'browser_tests',
       },
     },
 
     'gpu_default_and_optional_win_specific_gtests': {
       'xr_browser_tests': {
-        # The Windows machines this is run on should always meet all the
-        # requirements, so skip the runtime checks to help catch issues, e.g.
-        # if we're incorrectly being told a DirectX 11.1 device isn't
-        # available
+        'test': 'xr_browser_tests',
         'args': [
           '--ignore-runtime-requirements=*',
         ],
-        'test': 'xr_browser_tests',
       },
     },
 
     'gpu_desktop_specific_gtests': {
       'tab_capture_end2end_tests': {
+        'test': 'browser_tests',
         'args': [
           '--enable-gpu',
           '--test-launcher-bot-mode',
           '--test-launcher-jobs=1',
           '--gtest_filter=TabCaptureApiPixelTest.EndToEnd*',
         ],
-        'linux_args': [ '--no-xvfb' ],
-        'test': 'browser_tests',
+        'linux_args': [
+          '--no-xvfb',
+        ],
       },
     },
 
     'gpu_fyi_and_optional_non_linux_gtests': {
-      # gpu_unittests is killing the Swarmed Linux GPU bots similarly to
-      # how content_unittests was: http://crbug.com/763498 .
-      'gpu_unittests': {
-      },
+      'gpu_unittests': {},
     },
 
     'gpu_fyi_and_optional_win_specific_gtests': {
       'gles2_conform_d3d9_test': {
+        'test': 'gles2_conform_test',
         'args': [
           '--use-gpu-in-tests',
           '--use-angle=d3d9',
         ],
-        'test': 'gles2_conform_test',
       },
       'gles2_conform_gl_test': {
+        'test': 'gles2_conform_test',
         'args': [
           '--use-gpu-in-tests',
           '--use-angle=gl',
           '--disable-gpu-sandbox',
         ],
-        'test': 'gles2_conform_test',
       },
-      # WebNN DirectML backend unit tests, which currently only run on
-      # Windows OS, and require physical hardware.
       'services_webnn_unittests': {
+        'test': 'services_unittests',
         'args': [
           '--gtest_filter=WebNN*',
-          '--use-gpu-in-tests'
+          '--use-gpu-in-tests',
         ],
-        'test': 'services_unittests',
       },
     },
 
     'gpu_fyi_mac_specific_gtests': {
-      # Face and barcode detection unit tests, which currently only run on
-      # Mac OS, and require physical hardware.
       'services_unittests': {
         'args': [
           '--gtest_filter=*Detection*',
-          '--use-gpu-in-tests'
+          '--use-gpu-in-tests',
         ],
       },
     },
 
     'gpu_fyi_vulkan_swiftshader_gtests': {
       'vulkan_swiftshader_content_browsertests': {
+        'test': 'content_browsertests',
         'args': [
           '--enable-gpu',
           '--test-launcher-bot-mode',
@@ -2948,34 +2831,35 @@
           '--disable-vulkan-fallback-to-gl-for-testing',
           '--disable-headless-mode',
         ],
-        'linux_args': [ '--no-xvfb' ],
-        'test': 'content_browsertests',
+        'linux_args': [
+          '--no-xvfb',
+        ],
       },
     },
 
     'gpu_gl_passthrough_ganesh_telemetry_tests': {
       'context_lost_gl_passthrough_ganesh_tests': {
         'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'expected_color_pixel_gl_passthrough_ganesh_test': {
         'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
           '${buildername}',
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
       },
       'gpu_process_launch_tests': {
         'telemetry_test_name': 'gpu_process',
@@ -2990,6 +2874,11 @@
         ],
       },
       'pixel_skia_gold_gl_passthrough_ganesh_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -2997,54 +2886,51 @@
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'telemetry_test_name': 'pixel',
       },
       'screenshot_sync_gl_passthrough_ganesh_tests': {
         'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_gles2_conform_gtests': {
-      # The gles2_conform_tests are closed-source and deliberately only
-      # run on the FYI waterfall and the optional tryservers.
       'gles2_conform_test': {
-        'args': ['--use-gpu-in-tests'],
+        'args': [
+          '--use-gpu-in-tests',
+        ],
       },
     },
 
     'gpu_info_collection_telemetry_tests': {
       'info_collection_tests': {
         'telemetry_test_name': 'info_collection',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--expected-vendor-id',
           '${gpu_vendor_id}',
           '$$MAGIC_SUBSTITUTION_GPUExpectedDeviceId',
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--force_high_performance_gpu',
         ],
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_mediapipe_passthrough_telemetry_tests': {
       'mediapipe_passthrough_tests': {
         'telemetry_test_name': 'mediapipe',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--extra-browser-args=--force_higher_performance_gpu --use-cmd-decoder=passthrough --use-gl=angle',
         ],
@@ -3061,15 +2947,15 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_mediapipe_validating_telemetry_tests': {
       'mediapipe_validating_tests': {
         'telemetry_test_name': 'mediapipe',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--extra-browser-args=--force_higher_performance_gpu --use-cmd-decoder=validating',
         ],
@@ -3086,35 +2972,32 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_metal_passthrough_ganesh_telemetry_tests': {
       'context_lost_metal_passthrough_ganesh_tests': {
         'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'expected_color_pixel_metal_passthrough_ganesh_test': {
         'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
           '${buildername}',
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
       },
       'gpu_process_launch_tests': {
         'telemetry_test_name': 'gpu_process',
@@ -3129,6 +3012,11 @@
         ],
       },
       'pixel_skia_gold_metal_passthrough_ganesh_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3136,47 +3024,42 @@
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'telemetry_test_name': 'pixel',
       },
       'screenshot_sync_metal_passthrough_ganesh_tests': {
         'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_metal_passthrough_graphite_telemetry_tests': {
       'context_lost_metal_passthrough_graphite_tests': {
         'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'expected_color_pixel_metal_passthrough_graphite_test': {
         'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
           '${buildername}',
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
       },
       'gpu_process_launch_tests': {
         'telemetry_test_name': 'gpu_process',
@@ -3191,6 +3074,11 @@
         ],
       },
       'pixel_skia_gold_metal_passthrough_graphite_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3198,31 +3086,20 @@
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'telemetry_test_name': 'pixel',
       },
       'screenshot_sync_metal_passthrough_graphite_tests': {
         'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_noop_sleep_telemetry_test': {
-      # The former GPU-specific generator script contained logic to
-      # detect whether the so-called "experimental" GPU bots, which test
-      # newer driver versions, were identical to the "stable" versions
-      # of the bots, and if so to mirror their configurations. We prefer
-      # to keep this new script simpler and to just configure this by
-      # hand in waterfalls.pyl.
       'noop_sleep_tests': {
         'telemetry_test_name': 'noop_sleep',
         'android_args': [
@@ -3237,6 +3114,13 @@
     'gpu_passthrough_telemetry_tests': {
       'context_lost_passthrough_tests': {
         'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3250,16 +3134,13 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'args': [
-          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
-          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
-        ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'expected_color_pixel_passthrough_test': {
         'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3267,7 +3148,6 @@
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
         ],
         'android_args': [
-          # TODO(crbug.com/1093085): Remove this once we fix the tests.
           '--extra-browser-args=--force-online-connection-state-for-indicator',
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3281,13 +3161,12 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
       },
       'gpu_process_launch_tests': {
         'telemetry_test_name': 'gpu_process',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3301,12 +3180,12 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'hardware_accelerated_feature_tests': {
         'telemetry_test_name': 'hardware_accelerated_feature',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3320,11 +3199,13 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'pixel_skia_gold_passthrough_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3333,7 +3214,6 @@
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
         'android_args': [
-          # TODO(crbug.com/1093085): Remove this once we fix the tests.
           '--extra-browser-args=--force-online-connection-state-for-indicator',
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3347,20 +3227,17 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'telemetry_test_name': 'pixel',
       },
       'screenshot_sync_passthrough_tests': {
         'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
         ],
         'android_args': [
-          # TODO(crbug.com/1093085): Remove this once we fix the tests.
           '--extra-browser-args=--force-online-connection-state-for-indicator',
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3374,15 +3251,16 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_pixel_passthrough_telemetry_tests': {
       'expected_color_pixel_passthrough_test': {
         'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3392,12 +3270,13 @@
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
+      },
+      'pixel_skia_gold_passthrough_test': {
+        'telemetry_test_name': 'pixel',
         'mixins': [
           'skia_gold_test',
           'has_native_resultdb_integration',
         ],
-      },
-      'pixel_skia_gold_passthrough_test': {
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3408,16 +3287,16 @@
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'telemetry_test_name': 'pixel',
       },
     },
 
     'gpu_skia_renderer_vulkan_passthrough_telemetry_tests': {
       'vulkan_pixel_skia_gold_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3426,21 +3305,22 @@
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
         'android_args': [
-          # TODO(crbug.com/1093085): Remove this once we fix the tests.
           '--extra-browser-args=--force-online-connection-state-for-indicator',
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'telemetry_test_name': 'pixel',
       },
     },
 
     'gpu_validating_telemetry_tests': {
       'context_lost_validating_tests': {
         'telemetry_test_name': 'context_lost',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=validating',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3454,16 +3334,13 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'args': [
-          '--extra-browser-args=--use-cmd-decoder=validating',
-          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
-        ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'expected_color_pixel_validating_test': {
         'telemetry_test_name': 'expected_color',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3471,7 +3348,6 @@
           '--extra-browser-args=--use-cmd-decoder=validating',
         ],
         'android_args': [
-          # TODO(crbug.com/1093085): Remove this once we fix the tests.
           '--extra-browser-args=--force-online-connection-state-for-indicator',
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3485,13 +3361,12 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
       },
       'gpu_process_launch_tests': {
         'telemetry_test_name': 'gpu_process',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3505,12 +3380,12 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'hardware_accelerated_feature_tests': {
         'telemetry_test_name': 'hardware_accelerated_feature',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3524,11 +3399,13 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
       'pixel_skia_gold_validating_test': {
+        'telemetry_test_name': 'pixel',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
@@ -3537,7 +3414,6 @@
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
         'android_args': [
-          # TODO(crbug.com/1093085): Remove this once we fix the tests.
           '--extra-browser-args=--force-online-connection-state-for-indicator',
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3551,20 +3427,17 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'telemetry_test_name': 'pixel',
       },
       'screenshot_sync_validating_tests': {
         'telemetry_test_name': 'screenshot_sync',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--dont-restore-color-profile-after-test',
           '--extra-browser-args=--use-cmd-decoder=validating',
-         ],
+        ],
         'android_args': [
-          # TODO(crbug.com/1093085): Remove this once we fix the tests.
           '--extra-browser-args=--force-online-connection-state-for-indicator',
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3578,9 +3451,6 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
@@ -3589,13 +3459,18 @@
         'desktop_args': [
           '--use-gpu-in-tests',
         ],
-        'linux_args': ['--no-xvfb'],
+        'linux_args': [
+          '--no-xvfb',
+        ],
       },
     },
 
     'gpu_webcodecs_telemetry_test': {
       'webcodecs_tests': {
         'telemetry_test_name': 'webcodecs',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
@@ -3605,7 +3480,6 @@
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
-        # TODO(https://crbug.com/1359405): having --xvfb and --no-xvfb is confusing.
         'lacros_args': [
           '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
           '--xvfb',
@@ -3613,15 +3487,15 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_webcodecs_validating_telemetry_test': {
       'webcodecs_tests': {
         'telemetry_test_name': 'webcodecs',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--extra-browser-args=--use-cmd-decoder=validating',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
@@ -3632,7 +3506,6 @@
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
-        # TODO(https://crbug.com/1359405): having --xvfb and --no-xvfb is confusing.
         'lacros_args': [
           '--extra-browser-args=--enable-features=UseOzonePlatform --ozone-platform=wayland',
           '--xvfb',
@@ -3640,28 +3513,22 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests': {
       'webgl2_conformance_d3d11_passthrough_tests': {
         'telemetry_test_name': 'webgl2_conformance',
-        'args': [
-          '--webgl-conformance-version=2.0.1',
-          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
-          # On dual-GPU devices we want the high-performance GPU to be active
-          '--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu',
-          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'args': [
+          '--webgl-conformance-version=2.0.1',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
         'swarming': {
-          # These tests currently take about an hour and fifteen minutes
-          # to run. Split them into roughly 5-minute shards.
           'shards': 20,
         },
       },
@@ -3670,10 +3537,12 @@
     'gpu_webgl2_conformance_gl_passthrough_telemetry_tests': {
       'webgl2_conformance_gl_passthrough_tests': {
         'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--webgl-conformance-version=2.0.1',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
@@ -3690,12 +3559,7 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
-          # These tests currently take about an hour and fifteen minutes
-          # to run. Split them into roughly 5-minute shards.
           'shards': 20,
         },
       },
@@ -3704,10 +3568,12 @@
     'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': {
       'webgl2_conformance_gles_passthrough_tests': {
         'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--webgl-conformance-version=2.0.1',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
@@ -3717,12 +3583,7 @@
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
-          # These tests currently take about an hour and fifteen minutes
-          # to run. Split them into roughly 5-minute shards.
           'shards': 20,
         },
       },
@@ -3731,17 +3592,16 @@
     'gpu_webgl2_conformance_metal_passthrough_telemetry_tests': {
       'webgl2_conformance_metal_passthrough_tests': {
         'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--webgl-conformance-version=2.0.1',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
           '--enable-metal-debug-layers',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
           'shards': 20,
         },
@@ -3751,10 +3611,12 @@
     'gpu_webgl2_conformance_validating_telemetry_tests': {
       'webgl2_conformance_validating_tests': {
         'telemetry_test_name': 'webgl2_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--webgl-conformance-version=2.0.1',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
@@ -3771,12 +3633,7 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
-          # These tests currently take about an hour and fifteen minutes
-          # to run. Split them into roughly 5-minute shards.
           'shards': 20,
         },
       },
@@ -3785,15 +3642,14 @@
     'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests': {
       'webgl_conformance_d3d11_passthrough_tests': {
         'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
           'shards': 2,
         },
@@ -3803,15 +3659,14 @@
     'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests': {
       'webgl_conformance_d3d9_passthrough_tests': {
         'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-gl=angle --use-angle=d3d9 --use-cmd-decoder=passthrough --force_high_performance_gpu',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
           'shards': 2,
         },
@@ -3821,8 +3676,10 @@
     'gpu_webgl_conformance_gl_passthrough_telemetry_tests': {
       'webgl_conformance_gl_passthrough_tests': {
         'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
@@ -3840,9 +3697,6 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
           'shards': 2,
         },
@@ -3852,8 +3706,10 @@
     'gpu_webgl_conformance_gles_passthrough_telemetry_tests': {
       'webgl_conformance_gles_passthrough_tests': {
         'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
@@ -3871,9 +3727,6 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
           'shards': 6,
         },
@@ -3883,33 +3736,29 @@
     'gpu_webgl_conformance_metal_passthrough_telemetry_tests': {
       'webgl_conformance_metal_passthrough_tests': {
         'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
           '--enable-metal-debug-layers',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
       },
     },
 
     'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests': {
       'webgl_conformance_swangle_passthrough_tests': {
         'telemetry_test_name': 'webgl1_conformance',
-        'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
-          '--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough --force_high_performance_gpu',
-          # We are only interested in running a 'smoketest' to test swangle
-          # integration, not the full conformance suite.
-          '--test-filter=conformance/rendering/gl-drawelements.html',
-          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'args': [
+          '--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '--test-filter=conformance/rendering/gl-drawelements.html',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
         'swarming': {
           'shards': 1,
         },
@@ -3919,14 +3768,14 @@
     'gpu_webgl_conformance_swangle_passthrough_telemetry_tests': {
       'webgl_conformance_swangle_passthrough_tests': {
         'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough',
           '--xvfb',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
           'shards': 1,
         },
@@ -3936,11 +3785,10 @@
     'gpu_webgl_conformance_telemetry_tests': {
       'webgl_conformance_tests': {
         'telemetry_test_name': 'webgl1_conformance',
-        'chromeos_args': [
-          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        'mixins': [
+          'has_native_resultdb_integration',
         ],
         'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
           '--extra-browser-args=--force_high_performance_gpu',
           '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
           '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
@@ -3948,8 +3796,8 @@
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
-        'mixins': [
-          'has_native_resultdb_integration',
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
         'swarming': {
           'shards': 2,
@@ -3966,6 +3814,14 @@
     'gpu_webgl_conformance_validating_telemetry_tests': {
       'webgl_conformance_validating_tests': {
         'telemetry_test_name': 'webgl1_conformance',
+        'mixins': [
+          'has_native_resultdb_integration',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
         'android_args': [
           '$$MAGIC_SUBSTITUTION_GPUTelemetryNoRootForUnrootedDevices',
         ],
@@ -3979,15 +3835,6 @@
           '--use-weston',
           '--weston-use-gl',
         ],
-        'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
-          '--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu',
-          '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile',
-          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
-        ],
-        'mixins': [
-          'has_native_resultdb_integration',
-        ],
         'swarming': {
           'shards': 2,
         },
@@ -4000,14 +3847,13 @@
     'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests': {
       'webgl_conformance_vulkan_passthrough_tests': {
         'telemetry_test_name': 'webgl1_conformance',
-        'args': [
-          # On dual-GPU devices we want the high-performance GPU to be active
-          '--extra-browser-args=--use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu',
-          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
-        ],
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'args': [
+          '--extra-browser-args=--use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu',
+          '$$MAGIC_SUBSTITUTION_GPUParallelJobs',
+        ],
         'swarming': {
           'shards': 2,
         },
@@ -4044,9 +3890,9 @@
         ],
         'timeout_sec': 14400,
         'swarming': {
+          'shards': 8,
           'expiration': 10800,
           'hard_timeout': 14400,
-          'shards': 8,
         },
       },
       'content_unittests': {},
@@ -4110,8 +3956,6 @@
       'net_unittests': {},
       'services_unittests': {},
       'sql_unittests': {},
-      # TODO(https://bugs.chromium.org/p/gn/issues/detail?id=340): Enable this.
-      # 'rust_gtest_interop_unittests': {},
       'url_unittests': {},
     },
 
@@ -4132,18 +3976,14 @@
       'ios_web_shell_eg2tests_module': {},
     },
 
-    # Test suites in ios_eg2_cq_tests_parallel should be the same test suites as
-    # ios_eg2_cq_tests. The swarming shards between the versions can differ.
-    # Effectiveness of ios_parallel_simulators is determined by
-    # the number of test classes in the suite and the number of swarming shards.
-    # For ios_parallel_simulators to be most effective there should be twice as
-    # many test classes in the suite as there are swarming shards.
     'ios_eg2_cq_tests_parallel': {
       'ios_chrome_integration_eg2tests_module': {
+        'mixins': [
+          'ios_parallel_simulators',
+        ],
         'swarming': {
           'shards': 8,
         },
-        'mixins': ['ios_parallel_simulators'],
       },
       'ios_web_shell_eg2tests_module': {},
     },
@@ -4156,7 +3996,7 @@
         },
       },
       'ios_chrome_signin_eg2tests_module': {
-      'swarming': {
+        'swarming': {
           'shards': 6,
         },
       },
@@ -4174,31 +4014,29 @@
       'ios_showcase_eg2tests_module': {},
     },
 
-    # Test suites in ios_eg2_tests_parallel should be the same test suites as
-    # ios_eg2_tests. The swarming shards between the versions can differ.
-    # Effectiveness of ios_parallel_simulators is determined by
-    # the number of test classes in the suite and the number of swarming shards.
-    # For ios_parallel_simulators to be most effective there should be twice as
-    # many test classes in the suite as there are swarming shards.
     'ios_eg2_tests_parallel': {
       'ios_chrome_bookmarks_eg2tests_module': {},
       'ios_chrome_settings_eg2tests_module': {
+        'mixins': [
+          'ios_parallel_simulators',
+        ],
         'swarming': {
           'shards': 4,
         },
-        'mixins': ['ios_parallel_simulators',]
       },
       'ios_chrome_signin_eg2tests_module': {
-      'swarming': {
+        'swarming': {
           'shards': 6,
         },
       },
       'ios_chrome_smoke_eg2tests_module': {},
       'ios_chrome_ui_eg2tests_module': {
+        'mixins': [
+          'ios_parallel_simulators',
+        ],
         'swarming': {
           'shards': 12,
         },
-        'mixins': ['ios_parallel_simulators',]
       },
       'ios_chrome_web_eg2tests_module': {
         'swarming': {
@@ -4225,48 +4063,45 @@
       'ui_base_unittests': {},
     },
 
-    # END tests which run on the GPU bots
-
-    'js_code_coverage_browser_tests' : {
+    'js_code_coverage_browser_tests': {
       'js_code_coverage_browser_tests': {
-        'args': [],
+        'test': 'browser_tests',
         'swarming': {
           'shards': 16,
         },
-        'test': 'browser_tests',
-      }
+      },
     },
 
     'lacros_all_tast_tests': {
       'lacros_all_tast_tests': {
-        'swarming': {
-          'idempotent': False,  # https://crbug.com/923426#c27
-        },
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'swarming': {
+          'idempotent': False,
+        },
       },
     },
 
     'lacros_all_tast_tests_informational': {
       'lacros_all_tast_tests_informational': {
-        'swarming': {
-          'idempotent': False,  # https://crbug.com/923426#c27
-        },
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'swarming': {
+          'idempotent': False,
+        },
       },
     },
 
     'lacros_cq_tast_tests_eve': {
       'lacros_cq_tast_tests_eve': {
-        'swarming': {
-          'idempotent': False,  # https://crbug.com/923426#c27
-        },
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'swarming': {
+          'idempotent': False,
+        },
         'experiment_percentage': 5,
       },
     },
@@ -4279,10 +4114,12 @@
       'vaapi_unittest': {
         'args': [
           '--stop-ui',
-          # Tell libva to do dummy encoding/decoding. For more info, see:
-          # https://github.com/intel/libva/blob/master/va/va_fool.c#L47
-          '--env-var', 'LIBVA_DRIVERS_PATH', './',
-          '--env-var', 'LIBVA_DRIVER_NAME', 'libfake',
+          '--env-var',
+          'LIBVA_DRIVERS_PATH',
+          './',
+          '--env-var',
+          'LIBVA_DRIVER_NAME',
+          'libfake',
           '--gtest_filter="VaapiTest.*"',
         ],
       },
@@ -4290,12 +4127,12 @@
 
     'lacros_fyi_tast_tests': {
       'lacros_fyi_tast_tests': {
-        'swarming': {
-          'idempotent': False,  # https://crbug.com/923426#c27
-        },
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'swarming': {
+          'idempotent': False,
+        },
       },
     },
 
@@ -4309,9 +4146,6 @@
       },
     },
 
-    # create this temporary lacros arm test suites that runs on skylab
-    # TODO(crbug.com/1247425): remove it if it is the same as
-    # lacros_skylab
     'lacros_skylab_arm_tests_fyi': {
       'lacros_all_tast_tests': {
         'tast_expr': '("group:mainline" && "dep:lacros" && !informational)',
@@ -4325,17 +4159,15 @@
       },
     },
 
-    # Lacros tests that run on Skylab, and these tests are usually HW sensative,
-    # Currently we only run Tast tests.
     'lacros_skylab_tests': {
       'lacros_all_tast_tests': {
         'tast_expr': '("group:mainline" && ("dep:lacros_stable" || "dep:lacros") && !informational)',
-        'timeout_sec': 10800,
         'test_level_retries': 2,
-        'shards': 2,
         'mixins': [
           'has_native_resultdb_integration',
         ],
+        'timeout_sec': 10800,
+        'shards': 2,
       },
     },
 
@@ -4349,29 +4181,29 @@
 
     'leak_detection_isolated_scripts': {
       'memory.leak_detection': {
+        'test': 'performance_test_suite',
+        'override_compile_targets': [
+          'performance_test_suite',
+        ],
         'args': [
           '--pageset-repeat=1',
           '--test-shard-map-filename=linux_leak_detection_shard_map.json',
           '--upload-results',
           '--output-format=histograms',
           '--browser=release',
-          '--xvfb'
+          '--xvfb',
         ],
-        'test': 'performance_test_suite',
-        'override_compile_targets': [
-          'performance_test_suite',
-        ],
-        'merge': {
-          'args': [
-            '--smoke-test-mode',
-          ],
-          'script': '//tools/perf/process_perf_results.py',
-        },
         'swarming': {
+          'shards': 10,
           'expiration': 36000,
           'hard_timeout': 10800,
           'io_timeout': 3600,
-          'shards': 10
+        },
+        'merge': {
+          'script': '//tools/perf/process_perf_results.py',
+          'args': [
+            '--smoke-test-mode',
+          ],
         },
       },
     },
@@ -4383,11 +4215,11 @@
 
     'linux_chromeos_browser_tests_require_lacros': {
       'browser_tests_require_lacros': {
+        'test': 'browser_tests',
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter',
           '--lacros-chrome-path=lacros_clang_x64',
         ],
-        'test': 'browser_tests',
         'swarming': {
           'shards': 8,
         },
@@ -4395,29 +4227,24 @@
     },
 
     'linux_chromeos_lacros_gtests': {
-      # Chrome OS (Ash) and Lacros only.
       'chromeos_unittests': {},
     },
 
     'linux_chromeos_oobe_specific_tests': {
-      # TODO(crbug.com/1071693): Merge this suite back in to the main
-      # browser_tests when the tests no longer fail on MSAN.
       'oobe_only_browser_tests': {
+        'test': 'browser_tests',
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter',
         ],
-        'experiment_percentage': 100,
-        'test': 'browser_tests',
         'swarming': {
           'shards': 20,
         },
+        'experiment_percentage': 100,
       },
     },
 
     'linux_chromeos_specific_gtests': {
-      # Chrome OS only.
       'ash_components_unittests': {},
-      # TODO(crbug.com/1351793) Enable on CQ when stable.
       'ash_crosapi_tests': {
         'ci_only': True,
       },
@@ -4449,7 +4276,6 @@
     },
 
     'linux_flavor_specific_chromium_gtests': {
-      # Android, Chrome OS and Linux
       'sandbox_linux_unittests': {},
     },
 
@@ -4542,136 +4368,113 @@
 
     'linux_specific_chromium_isolated_scripts': {
       'not_site_per_process_blink_web_tests': {
-        # not_site_per_process_blink_web_tests provides coverage for
-        # running Layout Tests without site-per-process.  This is the mode used
-        # on Android and Android bots currently do not run the full set of
-        # layout tests.  Running in this mode on linux compensates for lack of
-        # direct Android coverage.
-        'args': [
-          '--flag-specific=disable-site-isolation-trials',
-          # layout test failures are retried 3 times when '--test-list' is not
-          # passed, but 0 times when '--test-list' is passed. We want to always
-          # retry 3 times, so we explicitly specify it.
-          '--num-retries=3',
-        ],
         'test': 'blink_web_tests',
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--flag-specific=disable-site-isolation-trials',
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 8,
         },
-      },
-      'not_site_per_process_blink_wpt_tests': {
-        # not_site_per_process_blink_wpt_tests provides coverage for
-        # running WPTs without site-per-process.  This is the mode used
-        # on Android and Android bots currently do not run the full set of
-        # layout tests.  Running in this mode on linux compensates for lack of
-        # direct Android coverage.
-        'args': [
-          '--flag-specific=disable-site-isolation-trials',
-          # layout test failures are retried 3 times when '--test-list' is not
-          # passed, but 0 times when '--test-list' is passed. We want to always
-          # retry 3 times, so we explicitly specify it.
-          '--num-retries=3',
-        ],
-        'test': 'blink_wpt_tests',
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
+      },
+      'not_site_per_process_blink_wpt_tests': {
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
           'blink_tests_write_run_histories',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--flag-specific=disable-site-isolation-trials',
+          '--num-retries=3',
+        ],
         'swarming': {
           'shards': 10,
         },
-      },
-      'webdriver_tests_suite': {
-        'args': [
-          '--test-type=wdspec',
-        ],
-        'test': 'chrome_wpt_tests',
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
+      },
+      'webdriver_tests_suite': {
+        'test': 'chrome_wpt_tests',
+        'results_handler': 'layout tests',
         'mixins': [
           'has_native_resultdb_integration',
         ],
-        'results_handler': 'layout tests',
+        'args': [
+          '--test-type=wdspec',
+        ],
         'swarming': {
           'shards': 2,
         },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
     },
 
     'linux_specific_xr_gtests': {
       'xr_browser_tests': {
         'test': 'xr_browser_tests',
-      }
+      },
     },
 
     'live_companion_tests': {
       'live_companion_tests': {
+        'test': 'browser_tests',
+        'override_compile_targets': [
+          'browser_tests',
+        ],
         'args': [
           '--gtest_filter=CompanionLiveTest.*',
           '--run-live-tests',
           '--run-manual',
           '--sync-status-change-checker-timeout=600',
-          # Timeout values below are in milliseconds.
           '--test-tiny-timeout=85000',
           '--ui-test-action-timeout=90000',
           '--ui-test-action-max-timeout=95000',
           '--test-launcher-timeout=100000',
           '--isolated-script-test-launcher-retry-limit=5',
         ],
-        'override_compile_targets': [
-          'browser_tests',
-        ],
         'swarming': {
           'expiration': 3600,
           'hard_timeout': 3600,
         },
-        'test': 'browser_tests',
       },
     },
 
-    # TODO(crbug.com/1320449): Remove this set of test suites when LSan can be
-    # enabled Mac ASan bots. This list will be gradually filled with more tests
-    # until the bot has parity with ASan bots, and the ASan bot can then enable
-    # LSan and the mac-lsan-fyi-rel bot go away.
     'mac_lsan_fyi_gtests': {
-      'absl_hardening_tests':{},
-      'accessibility_unittests':{},
-      'app_shell_unittests':{},
-      'base_unittests':{},
-      'blink_heap_unittests':{},
-      'blink_platform_unittests':{},
-      'blink_unittests':{},
-      'cc_unittests':{},
-      'components_unittests':{},
-      'content_unittests':{},
-      'crashpad_tests':{},
-      'cronet_unittests':{},
-      'device_unittests':{},
-      'net_unittests':{},
-      # TODO(crbug.com/1459686): Enable this.
-      # 'rust_gtest_interop_unittests': {},
+      'absl_hardening_tests': {},
+      'accessibility_unittests': {},
+      'app_shell_unittests': {},
+      'base_unittests': {},
+      'blink_heap_unittests': {},
+      'blink_platform_unittests': {},
+      'blink_unittests': {},
+      'cc_unittests': {},
+      'components_unittests': {},
+      'content_unittests': {},
+      'crashpad_tests': {},
+      'cronet_unittests': {},
+      'device_unittests': {},
+      'net_unittests': {},
     },
 
     'mac_specific_chromium_gtests': {
@@ -4697,7 +4500,7 @@
       'model_validation_tests': {
         'resultdb': {
           'enable': True,
-          'result_format': 'single'
+          'result_format': 'single',
         },
       },
     },
@@ -4712,16 +4515,6 @@
 
     'monochrome_public_apk_checker_isolated_script': {
       'monochrome_public_apk_checker': {
-        'swarming': {
-          'dimensions': {
-            'os': 'Ubuntu-18.04',
-            'cpu': 'x86-64',
-            'device_os': None,
-            'device_os_flavor': None,
-            'device_playstore_version': None,
-            'device_type': None,
-          },
-        },
         'remove_mixins': [
           'android_r',
           'bullhead',
@@ -4733,59 +4526,70 @@
           'pie_fleet',
           'walleye',
         ],
+        'swarming': {
+          'dimensions': {
+            'os': 'Ubuntu-18.04',
+            'cpu': 'x86-64',
+            'device_os': None,
+            'device_os_flavor': None,
+            'device_playstore_version': None,
+            'device_type': None,
+          },
+        },
       },
     },
 
     'network_sandbox_browser_tests': {
       'browser_tests_network_sandbox': {
+        'test': 'browser_tests',
         'args': [
           '--enable-features=NetworkServiceSandbox',
         ],
         'swarming': {
           'shards': 10,
         },
-        'test': 'browser_tests',
       },
       'components_browsertests_network_sandbox': {
+        'test': 'components_browsertests',
         'args': [
           '--enable-features=NetworkServiceSandbox',
         ],
-        'test': 'components_browsertests',
       },
       'content_browsertests_network_sandbox': {
+        'test': 'content_browsertests',
         'args': [
           '--enable-features=NetworkServiceSandbox',
         ],
         'swarming': {
           'shards': 10,
         },
-        'test': 'content_browsertests',
       },
       'interactive_ui_tests_network_sandbox': {
+        'test': 'interactive_ui_tests',
         'args': [
           '--enable-features=NetworkServiceSandbox',
         ],
         'swarming': {
           'shards': 3,
         },
-        'test': 'interactive_ui_tests',
       },
       'sync_integration_tests_network_sandbox': {
+        'test': 'sync_integration_tests',
         'args': [
           '--enable-features=NetworkServiceSandbox',
         ],
-        'test': 'sync_integration_tests',
       },
     },
+
     'network_service_fyi_gtests': {
       'network_service_web_request_proxy_browser_tests': {
+        'test': 'browser_tests',
         'args': [
           '--enable-features=ForceWebRequestProxyForTest',
         ],
         'swarming': {
           'shards': 15,
         },
-        'test': 'browser_tests',
       },
     },
 
@@ -4809,7 +4613,7 @@
       'chromedriver_unittests': {},
       'extensions_browsertests': {},
       'extensions_unittests': {},
-      'filesystem_service_unittests': {},  # https://crbug.com/862712
+      'filesystem_service_unittests': {},
       'interactive_ui_tests': {
         'swarming': {
           'shards': 3,
@@ -4822,7 +4626,7 @@
       'ppapi_unittests': {},
       'printing_unittests': {},
       'remoting_unittests': {},
-      'service_manager_unittests': {}, # https://crbug.com/843134
+      'service_manager_unittests': {},
       'snapshot_unittests': {},
       'sync_integration_tests': {
         'swarming': {
@@ -4846,7 +4650,7 @@
       'chromedriver_unittests': {},
       'extensions_browsertests': {},
       'extensions_unittests': {},
-      'filesystem_service_unittests': {},  # https://crbug.com/862712
+      'filesystem_service_unittests': {},
       'interactive_ui_tests': {
         'swarming': {
           'shards': 3,
@@ -4857,7 +4661,7 @@
       'pdf_unittests': {},
       'printing_unittests': {},
       'remoting_unittests': {},
-      'service_manager_unittests': {}, # https://crbug.com/843134
+      'service_manager_unittests': {},
       'snapshot_unittests': {},
       'sync_integration_tests': {
         'swarming': {
@@ -4878,6 +4682,7 @@
 
     'oop_network_service_tests': {
       'oop_network_service_content_browsertests': {
+        'test': 'content_browsertests',
         'args': [
           '--enable-features=NetworkServiceOutOfProcessMemoryThreshold:network_service_oop_threshold_mb/1077',
           '--disable-features=NetworkServiceInProcess2',
@@ -4885,32 +4690,30 @@
         'swarming': {
           'shards': 25,
         },
-        'test': 'content_browsertests',
       },
     },
 
     'optimization_guide_android_gtests': {
       'optimization_guide_components_unittests': {
-        'args': [
-            '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*',
-        ],
         'test': 'components_unittests',
+        'args': [
+          '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*',
+        ],
       },
-      # TODO(mgeorgaklis): Add optimization_guide_unittests when they become Android compatible.
     },
 
     'optimization_guide_gtests': {
       'optimization_guide_browser_tests': {
-        'args': [
-            '--gtest_filter=*OptimizationGuide*:*PageContentAnnotations*',
-        ],
         'test': 'browser_tests',
+        'args': [
+          '--gtest_filter=*OptimizationGuide*:*PageContentAnnotations*',
+        ],
       },
       'optimization_guide_components_unittests': {
-        'args': [
-            '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*',
-        ],
         'test': 'components_unittests',
+        'args': [
+          '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*',
+        ],
       },
       'optimization_guide_unittests': {},
     },
@@ -4923,12 +4726,12 @@
         ],
       },
       'content_browsertests': {
-        'android_swarming': {
-          'shards': 15,
-        },
         'swarming': {
           'shards': 8,
         },
+        'android_swarming': {
+          'shards': 15,
+        },
       },
       'perfetto_unittests': {},
       'services_unittests': {},
@@ -4942,12 +4745,12 @@
       },
       'base_unittests': {},
       'content_browsertests': {
-        'android_swarming': {
-          'shards': 15,
-        },
         'swarming': {
           'shards': 8,
         },
+        'android_swarming': {
+          'shards': 15,
+        },
       },
       'perfetto_unittests': {},
       'services_unittests': {},
@@ -4960,14 +4763,14 @@
           '--test-shard-map-filename=smoke_test_benchmark_shard_map.json',
         ],
         'swarming': {
-          'hard_timeout': 960,
           'shards': 2,
+          'hard_timeout': 960,
         },
         'merge': {
+          'script': '//tools/perf/process_perf_results.py',
           'args': [
             '--smoke-test-mode',
           ],
-          'script': '//tools/perf/process_perf_results.py',
         },
         'resultdb': {
           'enable': True,
@@ -4977,6 +4780,10 @@
 
     'pixel_browser_tests_gtests': {
       'pixel_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'skia_gold_test',
+        ],
         'args': [
           '--browser-ui-tests-verify-pixels',
           '--enable-pixel-output-in-tests',
@@ -4986,46 +4793,39 @@
         'swarming': {
           'shards': 3,
         },
-        'test': 'browser_tests',
+      },
+      'pixel_interactive_ui_tests': {
+        'test': 'interactive_ui_tests',
         'mixins': [
           'skia_gold_test',
         ],
-      },
-      'pixel_interactive_ui_tests': {
         'args': [
           '--browser-ui-tests-verify-pixels',
           '--enable-pixel-output-in-tests',
           '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter',
         ],
-        'test': 'interactive_ui_tests',
-        'mixins': [
-          'skia_gold_test',
-        ],
       },
     },
 
     'pixel_experimental_browser_tests_gtests': {
       'pixel_experimental_browser_tests': {
+        'test': 'browser_tests',
+        'mixins': [
+          'skia_gold_test',
+        ],
         'args': [
           '--browser-ui-tests-verify-pixels',
           '--enable-pixel-output-in-tests',
           '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.pixel_tests.filter',
         ],
         'experiment_percentage': 100,
-        'test': 'browser_tests',
-        'mixins': [
-          'skia_gold_test',
-        ],
       },
     },
 
     'private_code_failure_test_isolated_scripts': {
-      'private_code_failure_test': {}
+      'private_code_failure_test': {},
     },
 
-    # TODO(dpranke): These are run on the p/chromium waterfall; they should
-    # probably be run on other builders, and we should get rid of the p/chromium
-    # waterfall.
     'public_build_scripts': {
       'checkbins': {
         'script': 'checkbins.py',
@@ -5060,10 +4860,9 @@
       },
     },
 
-    # Rust tests run on all targets.
     'rust_common_gtests': {
       'base_unittests': {},
-      'components_unittests': {  # For go/rusty-qr-code-generator
+      'components_unittests': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/rust.components_unittests.filter',
         ],
@@ -5072,103 +4871,99 @@
       'mojo_rust_unittests': {},
       'rust_gtest_interop_unittests': {},
       'test_cpp_including_rust_unittests': {
-        'swarming': {},
         'test': 'test_cpp_including_rust_unittests',
       },
       'test_serde_json_lenient': {
-        'swarming': {},
         'test': 'test_serde_json_lenient',
       },
     },
 
     'rust_native_tests': {
       'build_rust_tests': {
-        'swarming': {},
         'test': 'build_rust_tests',
       },
     },
 
     'site_isolation_android_fyi_gtests': {
       'site_per_process_android_browsertests': {
+        'test': 'android_browsertests',
         'args': [
           '--site-per-process',
         ],
         'swarming': {
           'shards': 1,
         },
-        'test': 'android_browsertests',
       },
       'site_per_process_chrome_public_test_apk': {
+        'test': 'chrome_public_test_apk',
+        'mixins': [
+          'skia_gold_test',
+          'has_native_resultdb_integration',
+        ],
         'args': [
           '--site-per-process',
         ],
         'swarming': {
           'shards': 20,
         },
-        'mixins': [
-          'skia_gold_test',
-          'has_native_resultdb_integration',
-        ],
-        'test': 'chrome_public_test_apk',
       },
       'site_per_process_chrome_public_unit_test_apk': {
-        'args': [
-          '--site-per-process',
-        ],
+        'test': 'chrome_public_unit_test_apk',
         'mixins': [
           'skia_gold_test',
         ],
-        'test': 'chrome_public_unit_test_apk',
-      },
-      'site_per_process_components_browsertests': {
         'args': [
           '--site-per-process',
         ],
+      },
+      'site_per_process_components_browsertests': {
         'test': 'components_browsertests',
+        'args': [
+          '--site-per-process',
+        ],
       },
       'site_per_process_components_unittests': {
+        'test': 'components_unittests',
         'args': [
           '--site-per-process',
         ],
         'swarming': {
           'shards': 5,
         },
-        'test': 'components_unittests',
       },
       'site_per_process_content_browsertests': {
+        'test': 'content_browsertests',
         'args': [
           '--site-per-process',
           '--test-launcher-filter-file=../../testing/buildbot/filters/site_isolation_android.content_browsertests.filter',
-
         ],
         'swarming': {
           'shards': 10,
         },
-        'test': 'content_browsertests',
       },
       'site_per_process_content_shell_test_apk': {
+        'test': 'content_shell_test_apk',
         'args': [
           '--site-per-process',
         ],
         'swarming': {
           'shards': 3,
         },
-        'test': 'content_shell_test_apk',
       },
       'site_per_process_content_unittests': {
-        'args': [
-          '--site-per-process'
-        ],
         'test': 'content_unittests',
+        'args': [
+          '--site-per-process',
+        ],
       },
       'site_per_process_unit_tests': {
+        'test': 'unit_tests',
         'args': [
-          '--site-per-process'
+          '--site-per-process',
         ],
         'swarming': {
           'shards': 10,
         },
-        'test': 'unit_tests',
       },
     },
 
@@ -5271,6 +5066,7 @@
 
     'system_webview_wpt': {
       'system_webview_wpt': {
+        'results_handler': 'layout tests',
         'args': [
           '--no-wpt-internal',
         ],
@@ -5280,17 +5076,17 @@
           'hard_timeout': 14400,
         },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
-        'results_handler': 'layout tests',
       },
     },
 
     'telemetry_android_minidump_unittests_isolated_scripts': {
       'telemetry_chromium_minidump_unittests': {
+        'test': 'telemetry_perf_unittests_android_chrome',
         'args': [
           'BrowserMinidumpTest',
           '--browser=android-chromium',
@@ -5298,12 +5094,12 @@
           '--passthrough',
           '--retry-limit=2',
         ],
-        'test': 'telemetry_perf_unittests_android_chrome',
         'resultdb': {
           'enable': True,
         },
       },
       'telemetry_monochrome_minidump_unittests': {
+        'test': 'telemetry_perf_unittests_android_monochrome',
         'args': [
           'BrowserMinidumpTest',
           '--browser=android-chromium-monochrome',
@@ -5311,7 +5107,6 @@
           '--passthrough',
           '--retry-limit=2',
         ],
-        'test': 'telemetry_perf_unittests_android_monochrome',
         'resultdb': {
           'enable': True,
         },
@@ -5319,15 +5114,14 @@
     },
 
     'telemetry_desktop_minidump_unittests_isolated_scripts': {
-      # Takes ~2.5 minutes of bot time to run.
       'telemetry_desktop_minidump_unittests': {
+        'test': 'telemetry_perf_unittests',
         'args': [
           'BrowserMinidumpTest',
           '-v',
           '--passthrough',
           '--retry-limit=2',
         ],
-        'test': 'telemetry_perf_unittests',
         'resultdb': {
           'enable': True,
         },
@@ -5337,12 +5131,11 @@
     'telemetry_perf_unittests_isolated_scripts': {
       'telemetry_perf_unittests': {
         'args': [
-          # TODO(crbug.com/1077284): Remove this once Crashpad is the default.
           '--extra-browser-args=--enable-crashpad',
         ],
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
           'shards': 12,
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
@@ -5354,12 +5147,11 @@
       'telemetry_perf_unittests': {
         'test': 'telemetry_perf_unittests_android_chrome',
         'args': [
-          # TODO(crbug.com/1077284): Remove this once Crashpad is the default.
           '--extra-browser-args=--enable-crashpad',
         ],
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
           'shards': 12,
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
@@ -5370,13 +5162,12 @@
     'telemetry_perf_unittests_isolated_scripts_xvfb': {
       'telemetry_perf_unittests': {
         'args': [
-          # TODO(crbug.com/1077284): Remove this once Crashpad is the default.
           '--extra-browser-args=--enable-crashpad',
           '--xvfb',
         ],
         'swarming': {
-          'idempotent': False,  # https://crbug.com/549140
           'shards': 12,
+          'idempotent': False,
         },
         'resultdb': {
           'enable': True,
@@ -5386,8 +5177,6 @@
 
     'test_traffic_annotation_auditor_script': {
       'test_traffic_annotation_auditor': {
-        'hard_timeout': 14400,
-        'io_timeout': 14400,
         'script': 'test_traffic_annotation_auditor.py',
       },
     },
@@ -5398,7 +5187,6 @@
           'updater-default-pool',
         ],
       },
-      # 'updater_tests_system' is not yet supported on Linux.
     },
 
     'updater_gtests_mac': {
@@ -5455,17 +5243,11 @@
         ],
         'resultdb': {
           'enable': True,
-          'result_format': 'single'
+          'result_format': 'single',
         },
       },
     },
 
-    # Not applicable for android x86 & x64 since the targets here assert
-    # "enable_vr" in GN which is only true for android arm & arm64.
-    # For details, see the following files:
-    #  * //chrome/android/BUILD.gn
-    #  * //chrome/browser/android/vr/BUILD.gn
-    #  * //device/vr/buildflags/buildflags.gni
     'vr_android_specific_chromium_tests': {
       'chrome_public_test_vr_apk': {
         'args': [
@@ -5480,33 +5262,28 @@
     },
 
     'vr_platform_specific_chromium_gtests': {
-      # Only run on platforms that intend to support WebVR in the near
-      # future.
       'vr_common_unittests': {},
     },
 
     'vulkan_swiftshader_isolated_scripts': {
       'vulkan_swiftshader_blink_web_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
+        'test': 'blink_web_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
         'args': [
           '--num-retries=3',
           '--skipped=always',
           '--flag-specific=skia-vulkan-swiftshader',
         ],
-        'test': 'blink_web_tests',
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
-        'mixins': [
-          'has_native_resultdb_integration',
-          'blink_tests_write_run_histories',
-        ],
-        'results_handler': 'layout tests',
       },
     },
 
@@ -5524,10 +5301,13 @@
     },
 
     'webrtc_chromium_baremetal_gtests': {
-      # Run capture unittests on bots that have real webcams.
       'capture_unittests': {
-        'args': ['--enable-logging', '--v=1', '--test-launcher-jobs=1',
-                 '--test-launcher-print-test-stdio=always'],
+        'args': [
+          '--enable-logging',
+          '--v=1',
+          '--test-launcher-jobs=1',
+          '--test-launcher-print-test-stdio=always',
+        ],
         'swarming': {
           'dimensions': {
             'pool': 'WebRTC-chromium',
@@ -5539,11 +5319,7 @@
     'webrtc_chromium_gtests': {
       'browser_tests': {
         'args': [
-          '--gtest_filter=WebRtcStatsPerfBrowserTest.*:'
-           'WebRtcVideoDisplayPerfBrowserTests*:'
-           'WebRtcVideoQualityBrowserTests*:'
-           'WebRtcVideoHighBitrateBrowserTest*:'
-           'WebRtcWebcamBrowserTests*',
+          '--gtest_filter=WebRtcStatsPerfBrowserTest.*:WebRtcVideoDisplayPerfBrowserTests*:WebRtcVideoQualityBrowserTests*:WebRtcVideoHighBitrateBrowserTest*:WebRtcWebcamBrowserTests*',
           '--run-manual',
           '--ui-test-action-max-timeout=300000',
           '--test-launcher-timeout=350000',
@@ -5552,34 +5328,35 @@
           '--test-launcher-print-test-stdio=always',
         ],
       },
-      # TODO(b/246519185) - Py3 incompatible, decide if to keep test.:
-      #'browser_tests_apprtc': {
-      #  'args': ['--gtest_filter=WebRtcApprtcBrowserTest.*',
-      #           '--run-manual', '--test-launcher-jobs=1'],
-      #},
       'browser_tests_functional': {
+        'test': 'browser_tests',
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/webrtc_functional.browser_tests.filter',
-          '--run-manual', '--test-launcher-jobs=1'],
-        'test': 'browser_tests',
+          '--run-manual',
+          '--test-launcher-jobs=1',
+        ],
       },
       'content_browsertests': {
-        # Run all normal WebRTC content_browsertests. This is mostly so
-        # the FYI bots can detect breakages.
-        'args': ['--gtest_filter=WebRtc*'],
+        'args': [
+          '--gtest_filter=WebRtc*',
+        ],
       },
       'content_browsertests_sequential': {
-        # These run a few tests on fake webcams. They need to run sequentially,
-        # otherwise tests may interfere with each other.
-        'args': ['--gtest_filter=UsingRealWebcam*', '--run-manual',
-                 '--test-launcher-jobs=1'],
         'test': 'content_browsertests',
+        'args': [
+          '--gtest_filter=UsingRealWebcam*',
+          '--run-manual',
+          '--test-launcher-jobs=1',
+        ],
       },
       'content_browsertests_stress': {
-        'args': ['--gtest_filter=WebRtc*MANUAL*:-UsingRealWebcam*',
-                 '--run-manual', '--ui-test-action-max-timeout=110000',
-                 '--test-launcher-timeout=120000'],
         'test': 'content_browsertests',
+        'args': [
+          '--gtest_filter=WebRtc*MANUAL*:-UsingRealWebcam*',
+          '--run-manual',
+          '--ui-test-action-max-timeout=110000',
+          '--test-launcher-timeout=120000',
+        ],
       },
       'content_unittests': {
         'args': [
@@ -5587,28 +5364,36 @@
         ],
       },
       'remoting_unittests': {
-        'args': ['--gtest_filter=Webrtc*'],
+        'args': [
+          '--gtest_filter=Webrtc*',
+        ],
       },
     },
 
     'webrtc_chromium_simple_gtests': {
       'content_browsertests': {
-        'args': ['--gtest_filter=WebRtc*'],
+        'args': [
+          '--gtest_filter=WebRtc*',
+        ],
       },
       'content_browsertests_sequential': {
-        # These run a few tests on fake webcams. They need to run sequentially,
-        # otherwise tests may interfere with each other.
-        'args': ['--gtest_filter=UsingRealWebcam*', '--run-manual',
-                 '--test-launcher-jobs=1'],
         'test': 'content_browsertests',
+        'args': [
+          '--gtest_filter=UsingRealWebcam*',
+          '--run-manual',
+          '--test-launcher-jobs=1',
+        ],
       },
     },
 
     'webrtc_chromium_wpt_tests': {
       'blink_wpt_tests': {
-        # layout test failures are retried 3 times when '--test-list' is not
-        # passed, but 0 times when '--test-list' is passed. We want to always
-        # retry 3 times, so we explicitly specify it.
+        'test': 'blink_wpt_tests',
+        'results_handler': 'layout tests',
+        'mixins': [
+          'has_native_resultdb_integration',
+          'blink_tests_write_run_histories',
+        ],
         'args': [
           '--num-retries=3',
           '-t',
@@ -5620,18 +5405,12 @@
           'external/wpt/webrtc-stats',
           'external/wpt/webrtc-svc',
         ],
-        'test': 'blink_wpt_tests',
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
-        'mixins': [
-          'has_native_resultdb_integration',
-          'blink_tests_write_run_histories',
-        ],
-        'results_handler': 'layout tests',
       },
     },
 
@@ -5641,18 +5420,20 @@
           'shards': 2,
           'cipd_packages': [
             {
-              "cipd_package": 'chromium/android_webview/tools/cts_archive',
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
               'location': 'android_webview/tools/cts_archive',
               'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
-            }
-          ]
+            },
+          ],
         },
       },
     },
 
     'webview_bot_instrumentation_test_apk_gtest': {
       'webview_instrumentation_test_apk': {
-        'args': ['--use-apk-under-test-flags-file'],
+        'args': [
+          '--use-apk-under-test-flags-file',
+        ],
         'swarming': {
           'shards': 12,
         },
@@ -5661,11 +5442,13 @@
 
     'webview_bot_instrumentation_test_apk_no_field_trial_gtest': {
       'webview_instrumentation_test_apk_no_field_trial': {
-        'args': ['--disable-field-trial-config'],
+        'test': 'webview_instrumentation_test_apk',
+        'args': [
+          '--disable-field-trial-config',
+        ],
         'swarming': {
           'shards': 12,
         },
-        'test': 'webview_instrumentation_test_apk',
       },
     },
 
@@ -5679,17 +5462,18 @@
           'shards': 2,
           'cipd_packages': [
             {
-              "cipd_package": 'chromium/android_webview/tools/cts_archive',
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
               'location': 'android_webview/tools/cts_archive',
               'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
-            }
-          ]
+            },
+          ],
         },
       },
     },
 
     'webview_cts_tests_gtest_no_field_trial': {
       'webview_cts_tests_no_field_trial': {
+        'test': 'webview_cts_tests',
         'args': [
           '--disable-field-trial-config',
         ],
@@ -5697,19 +5481,20 @@
           'shards': 2,
           'cipd_packages': [
             {
-              "cipd_package": 'chromium/android_webview/tools/cts_archive',
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
               'location': 'android_webview/tools/cts_archive',
               'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
-            }
-          ]
+            },
+          ],
         },
-        'test': 'webview_cts_tests',
       },
     },
 
     'webview_trichrome_64_cts_field_trial_tests': {
       'webview_trichrome_64_cts_tests': {
-        'args': [ '--store-data-dependencies-in-temp' ],
+        'args': [
+          '--store-data-dependencies-in-temp',
+        ],
         'swarming': {
           'shards': 2,
           'cipd_packages': [
@@ -5717,8 +5502,8 @@
               'cipd_package': 'chromium/android_webview/tools/cts_archive',
               'location': 'android_webview/tools/cts_archive',
               'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
-            }
-          ]
+            },
+          ],
         },
       },
     },
@@ -5732,14 +5517,15 @@
               'cipd_package': 'chromium/android_webview/tools/cts_archive',
               'location': 'android_webview/tools/cts_archive',
               'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
-            }
-          ]
+            },
+          ],
         },
       },
     },
 
     'webview_trichrome_64_cts_tests_no_field_trial': {
       'webview_trichrome_64_cts_tests_no_field_trial': {
+        'test': 'webview_trichrome_64_cts_tests',
         'args': [
           '--disable-field-trial-config',
         ],
@@ -5747,13 +5533,12 @@
           'shards': 2,
           'cipd_packages': [
             {
-              "cipd_package": 'chromium/android_webview/tools/cts_archive',
+              'cipd_package': 'chromium/android_webview/tools/cts_archive',
               'location': 'android_webview/tools/cts_archive',
               'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
-            }
-          ]
+            },
+          ],
         },
-        'test': 'webview_trichrome_64_cts_tests',
       },
     },
 
@@ -5765,8 +5550,8 @@
               'cipd_package': 'chromium/android_webview/tools/cts_archive',
               'location': 'android_webview/tools/cts_archive',
               'revision': 'akIIr4yAFQwo3j5WYo2PQvy6z8XI51UiwiikPYzI4tUC',
-            }
-          ]
+            },
+          ],
         },
       },
     },
@@ -5777,10 +5562,10 @@
 
     'webview_ui_instrumentation_tests_no_field_trial': {
       'webview_ui_test_app_test_apk_no_field_trial': {
+        'test': 'webview_ui_test_app_test_apk',
         'args': [
           '--disable-field-trial-config',
         ],
-        'test': 'webview_ui_test_app_test_apk',
       },
     },
 
@@ -5835,6 +5620,7 @@
 
     'win_specific_xr_perf_tests': {
       'xr.webxr.static': {
+        'test': 'vr_perf_tests',
         'args': [
           '--benchmarks=xr.webxr.static',
           '-v',
@@ -5842,111 +5628,109 @@
           '--output-format=histograms',
           '--browser=release_x64',
         ],
-        'test': 'vr_perf_tests',
         'merge': {
           'script': '//tools/perf/process_perf_results.py',
         },
-        # Experimental until we're sure these are stable.
         'experiment_percentage': 100,
-      }
+      },
     },
 
     'wpt_tests_ios': {
       'wpt_tests_ios': {
+        'test': 'chrome_ios_wpt',
+        'results_handler': 'layout tests',
         'args': [
           '--no-wpt-internal',
         ],
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'test': 'chrome_ios_wpt',
-        'results_handler': 'layout tests',
         'swarming': {
           'shards': 15,
           'expiration': 18000,
           'hard_timeout': 14400,
         },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
         'experiment_percentage': 100,
       },
     },
 
     'wpt_web_tests': {
       'wpt_tests_suite': {
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
         'test': 'chrome_wpt_tests',
         'results_handler': 'layout tests',
         'swarming': {
           'shards': 15,
         },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
     },
 
     'wpt_web_tests_android': {
       'chrome_public_wpt': {
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
         'results_handler': 'layout tests',
         'swarming': {
           'shards': 15,
         },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
       'system_webview_wpt': {
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
         'results_handler': 'layout tests',
         'swarming': {
           'shards': 15,
         },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
     },
 
     'wpt_web_tests_content_shell': {
       'wpt_tests_suite': {
-        'merge': {
-          'args': [
-            '--verbose',
-          ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
         'test': 'content_shell_wpt',
         'results_handler': 'layout tests',
         'swarming': {
           'shards': 15,
         },
+        'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+          'args': [
+            '--verbose',
+          ],
+        },
       },
     },
 
     'wpt_web_tests_enable_leak_detection': {
       'wpt_tests_suite': {
+        'test': 'content_shell_wpt',
+        'results_handler': 'layout tests',
         'args': [
           '--enable-leak-detection',
         ],
+        'swarming': {
+          'shards': 15,
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'test': 'content_shell_wpt',
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 15,
         },
         'experiment_percentage': 100,
       },
@@ -5954,46 +5738,48 @@
 
     'wpt_web_tests_highdpi': {
       'wpt_tests_suite_highdpi': {
+        'test': 'content_shell_wpt',
+        'results_handler': 'layout tests',
         'args': [
           '--flag-specific',
           'highdpi',
         ],
+        'swarming': {
+          'shards': 3,
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'test': 'content_shell_wpt',
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 3,
         },
       },
     },
 
     'wpt_web_tests_identity': {
       'wpt_tests_suite': {
+        'test': 'chrome_wpt_tests',
+        'results_handler': 'layout tests',
         'args': [
           '--no-wpt-internal',
           'webauthn/',
         ],
+        'swarming': {
+          'shards': 1,
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'test': 'chrome_wpt_tests',
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 1,
         },
       },
     },
 
     'wpt_web_tests_input': {
       'wpt_tests_suite': {
+        'test': 'chrome_wpt_tests',
+        'results_handler': 'layout tests',
         'args': [
           '--no-wpt-internal',
           'infrastructure/testdriver/actions/',
@@ -6002,16 +5788,14 @@
           'touch-events/',
           'uievents/',
         ],
+        'swarming': {
+          'shards': 1,
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'test': 'chrome_wpt_tests',
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 1,
         },
         'experiment_percentage': 100,
       },
@@ -6019,31 +5803,28 @@
 
     'wpt_web_tests_not_site_per_process': {
       'wpt_tests_suite_not_site_per_process': {
+        'test': 'content_shell_wpt',
+        'results_handler': 'layout tests',
         'args': [
           '--child-processes=8',
           '--flag-specific',
           'disable-site-isolation-trials',
         ],
+        'swarming': {
+          'shards': 10,
+        },
         'merge': {
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
           'args': [
             '--verbose',
           ],
-          'script': '//third_party/blink/tools/merge_web_test_results.py',
-        },
-        'test': 'content_shell_wpt',
-        'results_handler': 'layout tests',
-        'swarming': {
-          'shards': 10,
         },
       },
     },
   },
 
-  ##############################################################################
-  # Compound test suites.                                                      #
-  ##############################################################################
-
   'compound_suites': {
+
     'android_10_rel_gtests': [
       'android_trichrome_smoke_tests',
       'android_ar_gtests',
@@ -6056,7 +5837,7 @@
 
     'android_marshmallow_gtests': [
       'android_smoke_tests',
-      'android_specific_chromium_gtests',  # Already includes gl_gtests.
+      'android_specific_chromium_gtests',
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
       'chrome_public_tests',
@@ -6069,12 +5850,12 @@
       'android_emulator_specific_chrome_public_tests',
       'android_monochrome_smoke_tests',
       'android_smoke_tests',
-      'android_specific_chromium_gtests',  # Already includes gl_gtests.
+      'android_specific_chromium_gtests',
       'android_wpr_record_replay_tests',
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
       'linux_flavor_specific_chromium_gtests',
-      'system_webview_shell_instrumentation_tests', # Not an experimental test
+      'system_webview_shell_instrumentation_tests',
       'webview_cts_tests_gtest',
       'webview_ui_instrumentation_tests',
     ],
@@ -6108,40 +5889,27 @@
       'android_monochrome_smoke_tests',
       'android_smoke_tests',
       'chromium_tracing_gtests',
-      # No standard tests due to capacity, no Vega tests since it's currently
-      # O only.
     ],
 
-     # Keep in sync with android_pie_rel_gtests below, except for
-     # vr_{android,platform}_specific_chromium_gtests which are not applicable
-     # to android emulators on x86 & x64.
     'android_pie_rel_emulator_gtests': [
       'android_emulator_specific_chrome_public_tests',
       'android_monochrome_smoke_tests',
       'android_smoke_tests',
-      'android_specific_chromium_gtests',  # Already includes gl_gtests.
+      'android_specific_chromium_gtests',
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
       'linux_flavor_specific_chromium_gtests',
-      'system_webview_shell_instrumentation_tests', # Not an experimental test
+      'system_webview_shell_instrumentation_tests',
       'webview_cts_tests_gtest',
       'webview_ui_instrumentation_tests',
     ],
 
     'android_pie_rel_gtests': [
-      # TODO(crbug.com/1111436): Deprecate this when all the test suites below
-      # it are re-enabled.
       'android_pie_rel_reduced_capacity_gtests',
       'android_monochrome_smoke_tests',
       'android_smoke_tests',
-    #   'android_specific_chromium_gtests',  # Already includes gl_gtests.
-    #   'chromium_gtests',
-    #   'chromium_gtests_for_devices_with_graphical_output',
       'chrome_public_tests',
-    #   'linux_flavor_specific_chromium_gtests',
       'system_webview_shell_instrumentation_tests',
-    #   'vr_android_specific_chromium_tests',
-    #   'vr_platform_specific_chromium_gtests',
       'webview_64_cts_tests_gtest',
       'webview_ui_instrumentation_tests',
     ],
@@ -6181,7 +5949,7 @@
 
     'chromium_android_gtests': [
       'android_smoke_tests',
-      'android_specific_chromium_gtests',  # Already includes gl_gtests.
+      'android_specific_chromium_gtests',
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
       'chrome_public_tests',
@@ -6196,8 +5964,6 @@
       'telemetry_perf_unittests_isolated_scripts',
     ],
 
-    # This is meant to be a superset of 'chromium_linux_and_gl_gtests'. Any
-    # changes there must be reflected here.
     'chromium_linux_and_gl_and_vulkan_gtests': [
       'aura_gtests',
       'chromium_gtests',
@@ -6215,8 +5981,6 @@
       'vr_platform_specific_chromium_gtests',
     ],
 
-    # gl_tests requires dedicated slaves with GPUs on linux, so have a separate
-    # test list with gl_tests included. This is chromium_linux_gtests + gl_gtests.
     'chromium_linux_and_gl_gtests': [
       'aura_gtests',
       'chromium_gtests',
@@ -6259,9 +6023,6 @@
       'telemetry_perf_unittests_isolated_scripts',
     ],
 
-    # When changing something here, change chromium_linux_and_gl_gtests,
-    # chromium_linux_and_gl_and_vulkan_gtests, and
-    # chromium_linux_rel_gtests_once in the same way.
     'chromium_linux_gtests': [
       'aura_gtests',
       'chromium_gtests',
@@ -6277,13 +6038,6 @@
       'vr_platform_specific_chromium_gtests',
     ],
 
-    # TODO(crbug.com/1444855): This set should match chromium_linux_gtests,
-    # except that it also runs tests that we can afford to run only once on
-    # Linux machines (for now, this is just the cr23_linux_gtests).
-    #
-    # Delete this test suite after the ChromeRefresh2023 is fully rolled out
-    # (assuming no other test suites are being run only once) and make sure
-    # any bots go back to using chromium_linux_gtests.
     'chromium_linux_gtests_once': [
       'aura_gtests',
       'chromium_gtests',
@@ -6323,11 +6077,6 @@
       'gpu_dawn_webgpu_blink_web_tests',
     ],
 
-    # Like chromium_linux_rel_isolated_scripts above, but should only
-    # include test suites that aren't affected by things like extra GN args
-    # (e.g. is_debug) or OS versions (e.g. Mac-12 vs Mac-13). Note: use
-    # chromium_linux_rel_isolated_scripts if you're setting up a new builder.
-    # This group should only be used across ~3 builders.
     'chromium_linux_rel_isolated_scripts_once': [
       'chromedriver_py_tests_isolated_scripts',
       'desktop_chromium_isolated_scripts',
@@ -6338,7 +6087,6 @@
       'telemetry_perf_unittests_isolated_scripts',
       'vulkan_swiftshader_isolated_scripts',
       'chromium_web_tests_high_dpi_isolated_scripts',
-      # TODO(weizhong): Remove wptrunner steps once experimenting completes.
       'wpt_web_tests_content_shell',
       'wpt_web_tests_highdpi',
     ],
@@ -6352,8 +6100,6 @@
       'non_android_chromium_gtests',
     ],
 
-    # When changing something here, change
-    # chromium_mac_gtests_no_nacl_once in the same way.
     'chromium_mac_gtests_no_nacl': [
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
@@ -6363,14 +6109,6 @@
       'non_android_chromium_gtests_no_nacl',
     ],
 
-    # TODO(crbug.com/1444855): This set should match
-    # chromium_mac_gtests_no_nacl, except that it also runs tests that we can
-    # only afford to run once on Mac machines (for now, this is just the
-    # cr23_mac_gtests).
-    #
-    # Delete this test suite after the ChromeRefresh2023 is fully rolled out
-    # and make sure any bots go back to using
-    # chromium_mac_gtests_no_nacl_no_nocompile.
     'chromium_mac_gtests_no_nacl_once': [
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
@@ -6400,14 +6138,8 @@
     ],
 
     'chromium_mac_rel_isolated_scripts_code_coverage': [
-      # TODO(crbug.com/1399354): Enable gpu_dawn_webgpu_blink_web_tests
     ],
 
-    # Like chromium_mac_rel_isolated_scripts above, but should only
-    # include test suites that aren't affected by things like extra GN args
-    # (e.g. is_debug) or OS versions (e.g. Mac-12 vs Mac-13). Note: use
-    # chromium_mac_rel_isolated_scripts if you're setting up a new builder.
-    # This group should only be used across ~3 builders.
     'chromium_mac_rel_isolated_scripts_once': [
       'chromedriver_py_tests_isolated_scripts',
       'components_perftests_isolated_scripts',
@@ -6416,14 +6148,9 @@
       'mac_specific_isolated_scripts',
       'mojo_python_unittests_isolated_scripts',
       'telemetry_perf_unittests_isolated_scripts',
-      # TODO(weizhong): Remove wptrunner steps once experimenting completes.
       'wpt_web_tests_content_shell',
     ],
 
-    # Pixel tests only enabled on Win 10. So this is
-    # 'chromium_win_gtests' + 'pixel_browser_tests_gtests' +
-    # 'non_android_chromium_gtests_skia_gold'. When changing
-    # something here, also change chromium_win10_gtests_once in the same way.
     'chromium_win10_gtests': [
       'aura_gtests',
       'chromium_gtests',
@@ -6439,12 +6166,6 @@
       'win_specific_chromium_gtests',
     ],
 
-    # TODO(crbug.com/1444855): This set should match chromium_win10_gtests,
-    # except that it also runs tests that we can afford to run only once
-    # on Windows machines (for now this is just the cr23_win_gtests).
-    #
-    # Delete this test suite after the ChromeRefresh2023 is fully rolled out
-    # and make sure any bots go back to using chromium_win10_gtests.
     'chromium_win10_gtests_once': [
       'aura_gtests',
       'chromium_gtests',
@@ -6494,11 +6215,6 @@
       'gpu_dawn_webgpu_blink_web_tests',
     ],
 
-    # Like chromium_win_rel_isolated_scripts above, but should only
-    # include test suites that aren't affected by things like extra GN args
-    # (e.g. is_debug) or OS versions (e.g. Mac-12 vs Mac-13). Note: use
-    # chromium_win_rel_isolated_scripts if you're setting up a new builder.
-    # This group should only be used across ~3 builders.
     'chromium_win_rel_isolated_scripts_once': [
       'chromedriver_py_tests_isolated_scripts',
       'components_perftests_isolated_scripts',
@@ -6508,7 +6224,6 @@
       'telemetry_desktop_minidump_unittests_isolated_scripts',
       'telemetry_perf_unittests_isolated_scripts',
       'win_specific_isolated_scripts',
-      # TODO(weizhong): Remove wptrunner steps once experimenting completes.
       'wpt_web_tests_content_shell',
     ],
 
@@ -6526,8 +6241,6 @@
       'blink_unittests',
     ],
 
-    # Runs only the accessibility tests in CI/CQ to reduce accessibility
-    # failures that land.
     'fuchsia_accessibility_browsertests': [
       'fuchsia_accessibility_content_browsertests',
     ],
@@ -6537,7 +6250,6 @@
       'gpu_angle_fuchsia_unittests_isolated_scripts',
     ],
 
-    # All gtests that can be run on Fuchsia CI/CQ
     'fuchsia_gtests': [
       'fuchsia_chrome_small_gtests',
       'fuchsia_common_gtests',
@@ -6547,7 +6259,7 @@
 
     'fuchsia_isolated_scripts': [
       'chromium_webkit_isolated_scripts',
-      'gpu_angle_fuchsia_unittests_isolated_scripts'
+      'gpu_angle_fuchsia_unittests_isolated_scripts',
     ],
 
     'fuchsia_web_engine_non_graphical_gtests': [
@@ -6555,8 +6267,6 @@
       'web_engine_gtests',
     ],
 
-    # BEGIN composition test suites used by the GPU bots
-
     'gpu_angle_linux_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
       'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
@@ -6615,16 +6325,11 @@
     ],
 
     'gpu_dawn_android_isolated_scripts': [
-      # Same as gpu_dawn_isolated_scripts, but with some suites removed:
-      # * telemetry_gpu_unittests since those aren't built for Android
-      # * SwiftShader-related tests since SwiftShader is not used on Android.
       'gpu_dawn_perf_smoke_isolated_scripts',
       'gpu_dawn_webgpu_blink_web_tests',
     ],
 
     'gpu_dawn_android_telemetry_tests': [
-      # Same as gpu_dawn_telemetry_tests, but without SwiftShader tests since
-      # SwiftShader is not used on Android.
       'gpu_dawn_webgpu_cts',
     ],
 
@@ -6641,8 +6346,6 @@
       'gpu_common_gtests_passthrough',
     ],
 
-    # GPU gtests that test Dawn and integration with Chromium
-    # These tests are run both on the CI and trybots which test DEPS Dawn.
     'gpu_dawn_integration_gtests_passthrough': [
       'gpu_dawn_gtests',
       'gpu_dawn_gtests_with_validation',
@@ -6715,42 +6418,20 @@
       'gpu_webgl2_conformance_validating_telemetry_tests',
     ],
 
-    # TODO(crbug.com/1080424): Merge with an existing set of tests such as
-    # gpu_fyi_linux_release_gtests once all CrOS tests have been enabled.
     'gpu_fyi_chromeos_release_gtests': [
-      # TODO(crbug.com/1135720): Missing cros wrapper script.
-      # 'gpu_angle_unit_gtests',
-      # TODO(crbug.com/1087567, crbug.com/1087590): Enable once there are tests
-      # that actually pass.
       'gpu_common_gtests_validating',
-      # TODO(crbug.com/1087563): Enable once tab_capture_end2end_tests passes
-      # on CrOS.
-      # 'gpu_desktop_specific_gtests',
     ],
 
-    # TODO(crbug.com/1080424): Merge with an existing set of tests such as
-    # gpu_fyi_linux_release_telemetry_tests once all CrOS tests
-    # have been enabled.
     'gpu_fyi_chromeos_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
       'gpu_mediapipe_validating_telemetry_tests',
       'gpu_validating_telemetry_tests',
       'gpu_webcodecs_validating_telemetry_test',
       'gpu_webgl_conformance_validating_telemetry_tests',
-      # Large amounts of WebGL/WebGL2 tests are failing due to issues that are
-      # possibly related to other CrOS issues that are already reported.
-      # TODO(crbug.com/1080424): Try enabling these again once some of the
-      # existing CrOS WebGL issues are resolved.
       'gpu_webgl2_conformance_gles_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_validating_telemetry_tests',
-      # 'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
     ],
 
-
-    # The same as gpu_fyi_chromeos_release_telemetry_tests, but using
-    # passthrough instead of validating since the Lacros bots are actually
-    # Lacros-like Linux bots, and Linux uses the passthrough decoder.
-    # Additionally, we use GLES instead of GL since that's what is supported.
     'gpu_fyi_lacros_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
       'gpu_mediapipe_passthrough_telemetry_tests',
@@ -6787,10 +6468,6 @@
       'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
     ],
 
-    # TODO(jonross): remove this once Vulkan Swiftshader and Vulkan GL interop
-    # paths are merged. This should mirror
-    # `gpu_fyi_linux_release_telemetry_tests` but with additional
-    # `gpu_skia_renderer_vulkan_passthrough_telemetry_tests`
     'gpu_fyi_linux_release_vulkan_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
       'gpu_mediapipe_passthrough_telemetry_tests',
@@ -6954,14 +6631,7 @@
       'gpu_desktop_specific_gtests',
     ],
 
-    # END composition test suites used by the GPU bots
-
     'linux_chromeos_gtests': [
-      # This is:
-      #   linux_chromium_gtests
-      #   - non_android_and_cast_and_chromeos_chromium_gtests
-      #   + linux_chromeos_lacros_gtests
-      #   + linux_chromeos_specific_gtests
       'aura_gtests',
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
@@ -6987,9 +6657,6 @@
     ],
 
     'linux_chromeos_specific_and_lacros_dependent_gtests': [
-      # This is:
-      #   linux_chromeos_gtests
-      #   + 'linux_chromeos_browser_tests_require_lacros'
       'aura_gtests',
       'chromium_gtests',
       'chromium_gtests_for_devices_with_graphical_output',
@@ -7008,14 +6675,6 @@
       'gpu_fyi_vulkan_swiftshader_gtests',
     ],
 
-    # TODO(crbug.com/1111436): Re-enable this if/when additional capacity
-    #'marshmallow_nougat_pie_isolated_scripts_with_proguard': [
-    #  'android_isolated_scripts',
-    #  'components_perftests_isolated_scripts',
-    #  'telemetry_android_minidump_unittests_isolated_scripts',
-    #  'telemetry_perf_unittests_isolated_scripts_android',
-    #],
-
     'network_service_extra_gtests': [
       'network_service_fyi_gtests',
     ],
@@ -7029,7 +6688,6 @@
       'telemetry_perf_unittests_isolated_scripts_android',
     ],
 
-    # Rust tests run on non-cross builds.
     'rust_host_gtests': [
       'rust_common_gtests',
     ],
@@ -7067,26 +6725,22 @@
     ],
   },
 
-  ##############################################################################
-  # Matrix compound test suites.                                               #
-  ##############################################################################
-
   'matrix_compound_suites': {
 
     'android_11_emulator_gtests': {
       'android_emulator_specific_chrome_public_tests': {},
       'android_trichrome_smoke_tests': {},
       'android_smoke_tests': {},
-      'android_specific_chromium_gtests': {},  # Already includes gl_gtests.
+      'android_specific_chromium_gtests': {},
       'chromium_gtests': {},
       'chromium_gtests_for_devices_with_graphical_output': {},
       'linux_flavor_specific_chromium_gtests': {},
-      'system_webview_shell_instrumentation_tests': {}, # Not an experimental test
+      'system_webview_shell_instrumentation_tests': {},
       'webview_trichrome_cts_tests': {
         'variants': [
           'WEBVIEW_TRICHROME_FULL_CTS_TESTS',
           'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS',
-        ]
+        ],
       },
       'webview_ui_instrumentation_tests': {},
     },
@@ -7100,19 +6754,19 @@
       'android_emulator_specific_chrome_public_tests': {},
       'android_trichrome_smoke_tests': {},
       'android_smoke_tests': {},
-      'android_specific_chromium_gtests': {},  # Already includes gl_gtests.
+      'android_specific_chromium_gtests': {},
       'chrome_profile_generator_tests': {},
       'chromium_gtests': {},
       'chromium_gtests_for_devices_with_graphical_output': {},
       'fieldtrial_android_tests': {},
       'linux_flavor_specific_chromium_gtests': {},
       'minidump_uploader_tests': {},
-      'system_webview_shell_instrumentation_tests': {}, # Not an experimental test
+      'system_webview_shell_instrumentation_tests': {},
       'webview_trichrome_64_cts_tests': {
         'variants': [
           'WEBVIEW_TRICHROME_FULL_CTS_TESTS',
           'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS',
-        ]
+        ],
       },
       'webview_ui_instrumentation_tests': {},
     },
@@ -7121,11 +6775,11 @@
       'android_emulator_specific_chrome_public_tests': {},
       'android_trichrome_smoke_tests': {},
       'android_smoke_tests': {},
-      'android_specific_chromium_gtests': {},  # Already includes gl_gtests.
+      'android_specific_chromium_gtests': {},
       'chromium_gtests': {},
       'chromium_gtests_for_devices_with_graphical_output': {},
       'linux_flavor_specific_chromium_gtests': {},
-      'system_webview_shell_instrumentation_tests': {}, # Not an experimental test
+      'system_webview_shell_instrumentation_tests': {},
       'webview_ui_instrumentation_tests': {},
     },
 
@@ -7133,16 +6787,16 @@
       'android_emulator_specific_chrome_public_tests': {},
       'android_trichrome_smoke_tests': {},
       'android_smoke_tests': {},
-      'android_specific_chromium_gtests': {},  # Already includes gl_gtests.
+      'android_specific_chromium_gtests': {},
       'chromium_gtests': {},
       'chromium_gtests_for_devices_with_graphical_output': {},
       'linux_flavor_specific_chromium_gtests': {},
-      'system_webview_shell_instrumentation_tests': {}, # Not an experimental test
+      'system_webview_shell_instrumentation_tests': {},
       'webview_trichrome_64_cts_tests': {
         'variants': [
           'WEBVIEW_TRICHROME_FULL_CTS_TESTS',
           'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS',
-        ]
+        ],
       },
       'webview_trichrome_64_cts_tests_no_field_trial': {},
       'webview_ui_instrumentation_tests': {},
@@ -7155,14 +6809,14 @@
           'DISABLE_FIELD_TRIAL_CONFIG',
           'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR',
           'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR',
-        ]
+        ],
       },
       'webview_trichrome_64_cts_field_trial_tests': {
         'variants': [
           'DISABLE_FIELD_TRIAL_CONFIG',
           'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR',
           'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR',
-        ]
+        ],
       },
       'webview_ui_instrumentation_tests': {
         'variants': [
@@ -7177,24 +6831,24 @@
           'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR_WEBVIEW_COMMANDLINE',
           'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR_WEBVIEW_COMMANDLINE',
         ],
-      }
+      },
     },
 
     'chromeos_brya_skylab_tests': {
       'chromeos_chrome_all_tast_tests': {
         'variants': [
           'CROS_BRYA_RELEASE_ASH_LKGM',
-        ]
+        ],
       },
       'chromeos_chrome_criticalstaging_tast_tests': {
         'variants': [
           'CROS_BRYA_RELEASE_ASH_LKGM',
-        ]
+        ],
       },
       'chromeos_chrome_disabled_tast_tests': {
         'variants': [
           'CROS_BRYA_RELEASE_ASH_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7202,17 +6856,17 @@
       'chromeos_chrome_all_tast_tests': {
         'variants': [
           'CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM',
-        ]
+        ],
       },
       'chromeos_chrome_criticalstaging_tast_tests': {
         'variants': [
           'CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM',
-        ]
+        ],
       },
       'chromeos_chrome_disabled_tast_tests': {
         'variants': [
           'CROS_JACUZZI_RELEASE_CHROME_FROM_TLS_ASH_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7220,7 +6874,7 @@
       'chromeos_chrome_all_tast_tests': {
         'variants': [
           'CROS_OCTOPUS_RELEASE_CHROME_FROM_TLS_ASH_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7228,7 +6882,7 @@
       'chromeos_chrome_all_tast_tests': {
         'variants': [
           'CROS_TROGDOR_RELEASE_ASH_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7236,17 +6890,17 @@
       'chromeos_chrome_all_tast_tests': {
         'variants': [
           'CROS_VOLTEER_RELEASE_ASH_LKGM',
-        ]
+        ],
       },
       'chromeos_chrome_criticalstaging_tast_tests': {
         'variants': [
           'CROS_VOLTEER_RELEASE_ASH_LKGM',
-        ]
+        ],
       },
       'chromeos_chrome_disabled_tast_tests': {
         'variants': [
           'CROS_VOLTEER_RELEASE_ASH_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7259,7 +6913,7 @@
         'variants': [
           'SIM_IPAD_AIR_2_15_5',
           'SIM_IPHONE_13_15_5',
-        ]
+        ],
       },
       'ios_eg2_tests': {
         'mixins': [
@@ -7269,7 +6923,7 @@
         'variants': [
           'SIM_IPAD_AIR_2_15_5',
           'SIM_IPHONE_13_15_5',
-        ]
+        ],
       },
     },
 
@@ -7340,7 +6994,7 @@
       'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': {
         'variants': [
           'LACROS_ASH_TOT',
-          ],
+        ],
       },
     },
 
@@ -7351,21 +7005,27 @@
         ],
       },
       'ios_eg2_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_10TH_GEN_16_4',
           'SIM_IPAD_PRO_6TH_GEN_16_4',
-        ]
+        ],
       },
       'ios_eg2_cq_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPAD_10TH_GEN_16_4',
           'SIM_IPAD_AIR_5TH_GEN_16_4',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7376,10 +7036,12 @@
         ],
       },
       'ios_crash_xcuitests': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
-        ]
+        ],
       },
     },
 
@@ -7390,26 +7052,34 @@
         ],
       },
       'ios_crash_xcuitests': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
-        ]
+        ],
       },
       'ios_eg2_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_PRO_6TH_GEN_16_4',
-        ]
+        ],
       },
       'ios_eg2_cq_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_PRO_6TH_GEN_16_4',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7429,18 +7099,24 @@
         ],
       },
       'ios_eg2_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_cq_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7450,11 +7126,13 @@
         ],
       },
       'ios_crash_xcuitests': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
     },
 
@@ -7466,18 +7144,22 @@
         ],
       },
       'ios_eg2_tests_parallel': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_cq_tests_parallel': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPAD_AIR_5TH_GEN_17_0',
           'SIM_IPHONE_14_17_0',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7493,21 +7175,21 @@
         'variants': [
           'SIM_IPHONE_X_15_5',
           'SIM_IPAD_AIR_2_15_5',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
           'SIM_IPHONE_X_15_5',
           'SIM_IPAD_AIR_2_15_5',
-        ]
-      }
+        ],
+      },
     },
 
     'ios_blink_dbg_tests': {
       'ios_blink_tests': {
         'variants': [
           'SIM_IPHONE_14_17_0',
-        ]
+        ],
       },
     },
 
@@ -7516,19 +7198,17 @@
         'variants': [
           'IPHONE_7_15_4_1',
         ],
-      }
+      },
     },
 
     'ios_clang_tot_sim_tests': {
       'clang_tot_gtests': {
         'variants': [
           'SIM_IPHONE_6S_15_5',
-        ]
-      }
+        ],
+      },
     },
 
-    # This suite is a union of ios_simulator_tests and
-    # ios_simulator_full_configs_tests.
     'ios_code_coverage_tests': {
       'ios_common_tests': {
         'variants': [
@@ -7539,7 +7219,9 @@
         ],
       },
       'ios_eg2_cq_tests_parallel': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_13_15_5',
           'SIM_IPHONE_14_16_4',
@@ -7552,7 +7234,9 @@
         ],
       },
       'ios_eg2_tests_parallel': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_13_15_5',
           'SIM_IPHONE_14_16_4',
@@ -7589,14 +7273,20 @@
         ],
       },
       'ios_eg2_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_cq_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPAD_10TH_GEN_16_4',
@@ -7606,7 +7296,7 @@
           'SIM_IPAD_10TH_GEN_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
           'SIM_IPAD_PRO_6TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7626,29 +7316,32 @@
       'ios_cronet_tests': {
         'variants': [
           'SIM_IPHONE_13_15_5',
-        ]
-      }
+        ],
+      },
     },
 
-    # Please also change ios_code_coverage_tests for any change in this suite.
     'ios_simulator_full_configs_tests': {
       'ios_common_tests': {
         'variants': [
           'SIM_IPHONE_14_PLUS_16_4',
           'SIM_IPHONE_14_PLUS_17_0',
-        ]
+        ],
       },
       'ios_eg2_tests_parallel': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_PRO_6TH_GEN_16_4',
           'SIM_IPAD_PRO_6TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_cq_tests_parallel': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPAD_PRO_6TH_GEN_16_4',
           'SIM_IPAD_PRO_6TH_GEN_17_0',
@@ -7656,7 +7349,7 @@
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7664,8 +7357,8 @@
           'SIM_IPAD_PRO_6TH_GEN_17_0',
           'SIM_IPHONE_14_16_4',
           'SIM_IPHONE_14_17_0',
-        ]
-      }
+        ],
+      },
     },
 
     'ios_simulator_multi_window_tests': {
@@ -7673,46 +7366,56 @@
         'variants': [
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_cq_tests': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_tests': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
-      }
+        ],
+      },
     },
 
     'ios_simulator_noncq_tests': {
       'ios_eg2_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_13_15_5',
           'SIM_IPAD_PRO_6TH_GEN_16_4',
           'SIM_IPAD_PRO_6TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_cq_tests': {
-        'mixins': ['xcode_parallelization', 'record_failed_tests'],
+        'mixins': [
+          'xcode_parallelization',
+          'record_failed_tests',
+        ],
         'variants': [
           'SIM_IPHONE_13_15_5',
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7726,32 +7429,35 @@
           'SIM_IPAD_AIR_5TH_GEN_17_0',
           'SIM_IPHONE_SE_3RD_GEN_17_0',
           'SIM_IPAD_PRO_6TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_crash_xcuitests': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_13_15_5',
           'SIM_IPHONE_SE_3RD_GEN_16_4',
           'SIM_IPHONE_SE_3RD_GEN_17_0',
-        ]
+        ],
       },
     },
 
-    # Please also change ios_code_coverage_tests for any change in this suite.
     'ios_simulator_tests': {
       'ios_common_tests': {
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPHONE_14_17_0',
-        ]
+        ],
       },
       'ios_eg2_cq_tests_parallel': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPHONE_14_17_0',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7759,8 +7465,8 @@
           'SIM_IPAD_PRO_6TH_GEN_16_4',
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_PRO_6TH_GEN_17_0',
-        ]
-      }
+        ],
+      },
     },
 
     'ios_webkit_tot_tests': {
@@ -7770,25 +7476,29 @@
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_cq_tests_parallel': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_eg2_tests': {
-        'mixins': ['xcode_parallelization'],
+        'mixins': [
+          'xcode_parallelization',
+        ],
         'variants': [
           'SIM_IPHONE_14_16_4',
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
@@ -7796,7 +7506,7 @@
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
     },
 
@@ -7807,7 +7517,7 @@
           'SIM_IPAD_AIR_5TH_GEN_16_4',
           'SIM_IPHONE_14_17_0',
           'SIM_IPAD_AIR_5TH_GEN_17_0',
-        ]
+        ],
       },
     },
 
@@ -7816,7 +7526,7 @@
         'variants': [
           'CROS_OCTOPUS_PUBLIC_LKGM',
           'CROS_EVE_PUBLIC_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7824,7 +7534,7 @@
       'lacros_skylab_tests': {
         'variants': [
           'CROS_TROGDOR_PUBLIC_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7834,7 +7544,7 @@
           'CROS_JACUZZI_PUBLIC_LKGM',
           'CROS_JACUZZI_CQ_PUBLIC_LKGM',
           'CROS_TROGDOR_PUBLIC_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7842,12 +7552,12 @@
       'lacros_skylab_tests': {
         'variants': [
           'CROS_JACUZZI_PUBLIC_LKGM',
-        ]
+        ],
       },
       'lacros_skylab_tests_with_gtests': {
         'variants': [
           'CROS_JACUZZI_PUBLIC_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7856,7 +7566,7 @@
         'variants': [
           'CROS_JACUZZI_PUBLIC_LKGM',
           'CROS_TROGDOR_PUBLIC_LKGM',
-        ]
+        ],
       },
     },
 
@@ -7865,29 +7575,29 @@
         'variants': [
           'LACROS_AMD64_GENERIC',
           'LACROS_EVE',
-        ]
+        ],
       },
       'lacros_all_tast_tests': {
         'variants': [
           'LACROS_AMD64_GENERIC',
           'LACROS_EVE',
-        ]
+        ],
       },
       'lacros_cq_tast_tests_eve': {
         'variants': [
           'LACROS_EVE',
-        ]
+        ],
       },
       'lacros_device_or_vm_gtests': {
         'variants': [
           'LACROS_AMD64_GENERIC',
           'LACROS_EVE',
-        ]
+        ],
       },
       'lacros_vm_gtests': {
         'variants': [
           'LACROS_AMD64_GENERIC',
-        ]
+        ],
       },
     },
 
@@ -7896,23 +7606,22 @@
         'variants': [
           'LACROS_AMD64_GENERIC',
           'LACROS_EVE',
-        ]
+        ],
       },
       'lacros_device_or_vm_gtests': {
         'variants': [
           'LACROS_AMD64_GENERIC',
           'LACROS_EVE',
-        ]
+        ],
       },
       'lacros_fyi_tast_tests': {
         'variants': [
           'LACROS_AMD64_GENERIC',
           'LACROS_EVE',
-        ]
+        ],
       },
     },
 
-    # Check go/lacros-on-skylab for details of Skylab configurations.
     'lacros_skylab_arm': {
       'lacros_skylab_tests': {
         'variants': [
@@ -7920,7 +7629,7 @@
           'CROS_JACUZZI_RELEASE_DEV',
           'CROS_JACUZZI_RELEASE_BETA',
           'CROS_JACUZZI_RELEASE_STABLE',
-        ]
+        ],
       },
     },
 
@@ -7928,11 +7637,10 @@
       'lacros_skylab_tests': {
         'variants': [
           'CROS_STRONGBAD_RELEASE_LKGM',
-        ]
+        ],
       },
     },
 
-    # Check go/lacros-on-skylab for details of Skylab configurations.
     'lacros_skylab_arm_fyi': {
       'lacros_skylab_arm_tests_fyi': {
         'variants': [
@@ -7944,11 +7652,10 @@
           'CROS_STRONGBAD_RELEASE_DEV',
           'CROS_STRONGBAD_RELEASE_BETA',
           'CROS_STRONGBAD_RELEASE_STABLE',
-        ]
+        ],
       },
     },
 
-    # Check go/lacros-on-skylab for details of Skylab configurations.
     'lacros_skylab_tests_amd64_generic': {
       'lacros_skylab_tests': {
         'variants': [
@@ -7972,7 +7679,7 @@
           'CROS_PUFF_RELEASE_DEV',
           'CROS_PUFF_RELEASE_BETA',
           'CROS_PUFF_RELEASE_STABLE',
-        ]
+        ],
       },
     },
 
@@ -7983,7 +7690,7 @@
           'CROS_OCTOPUS_RELEASE_DEV',
           'CROS_OCTOPUS_RELEASE_BETA',
           'CROS_OCTOPUS_RELEASE_STABLE',
-        ]
+        ],
       },
     },
 
@@ -7991,55 +7698,48 @@
       'lacros_skylab_tests': {
         'variants': [
           'CROS_VOLTEER_PUBLIC_LKGM',
-        ]
+        ],
       },
     },
 
     'linux_lacros_gtests': {
-      # This is:
-      #   linux_chromeos_gtests
-      #   - linux_chromeos_specific_gtests
-      #   + linux_chromeos_lacros_gtests
-      #   + linux_lacros_chrome_browsertests_version_skew
-      #   + linux_lacros_specific_gtests
       'aura_gtests': {},
       'chromium_gtests': {},
       'chromium_gtests_for_devices_with_graphical_output': {},
       'chromium_gtests_for_linux_and_chromeos_only': {},
       'chromium_gtests_for_win_and_linux_only': {},
-      'linux_chromeos_lacros_gtests': { },
-      'linux_flavor_specific_chromium_gtests': {  },
-      'linux_lacros_specific_gtests': {  },
-      'non_android_chromium_gtests': {
-      },
-      'linux_lacros_chrome_browsertests_non_version_skew': { },
+      'linux_chromeos_lacros_gtests': {},
+      'linux_flavor_specific_chromium_gtests': {},
+      'linux_lacros_specific_gtests': {},
+      'non_android_chromium_gtests': {},
+      'linux_lacros_chrome_browsertests_non_version_skew': {},
       'linux_lacros_chrome_browsertests_version_skew': {
         'variants': [
           'LACROS_VERSION_SKEW_CANARY',
           'LACROS_VERSION_SKEW_DEV',
           'LACROS_VERSION_SKEW_BETA',
           'LACROS_VERSION_SKEW_STABLE',
-        ]
+        ],
       },
       'linux_lacros_chrome_interactive_ui_tests_version_skew': {
         'variants': [
           'LACROS_VERSION_SKEW_CANARY',
-        ]
+        ],
       },
       'linux_lacros_chrome_interactive_ui_tests_version_skew_beta': {
         'variants': [
           'LACROS_VERSION_SKEW_BETA',
-        ]
+        ],
       },
       'linux_lacros_chrome_interactive_ui_tests_version_skew_dev': {
         'variants': [
           'LACROS_VERSION_SKEW_DEV',
-        ]
+        ],
       },
       'linux_lacros_chrome_interactive_ui_tests_version_skew_stable': {
         'variants': [
           'LACROS_VERSION_SKEW_STABLE',
-        ]
+        ],
       },
     },
 
@@ -8050,7 +7750,7 @@
           'LACROS_VERSION_SKEW_DEV',
           'LACROS_VERSION_SKEW_BETA',
           'LACROS_VERSION_SKEW_STABLE',
-        ]
+        ],
       },
     },
 
@@ -8196,8 +7896,8 @@
         'variants': [
           'WEBVIEW_TRICHROME_FULL_CTS_TESTS',
           'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS',
-        ]
-      }
+        ],
+      },
     },
 
     'win_optional_gpu_tests_rel_gpu_telemetry_tests': {
@@ -8284,5 +7984,5 @@
         ],
       },
     },
-  }
+  },
 }
diff --git a/testing/buildbot/tryserver.chromium.chromiumos.json b/testing/buildbot/tryserver.chromium.chromiumos.json
index 36d64b7..3e5cbd5 100644
--- a/testing/buildbot/tryserver.chromium.chromiumos.json
+++ b/testing/buildbot/tryserver.chromium.chromiumos.json
@@ -7,7 +7,6 @@
     ],
     "skylab_tests": [
       {
-        "autotest_name": "tast.lacros-from-gcs",
         "bucket": "chromiumos-image-archive",
         "cros_board": "volteer",
         "cros_img": "volteer-public/R119-15623.0.0",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index c0117ce2..cc87d404 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -70,16 +70,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 119.0.6029.0',
+    'description': 'Run with ash-chrome version 119.0.6030.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6029.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v119.0.6030.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v119.0.6029.0',
-          'revision': 'version:119.0.6029.0',
+          'location': 'lacros_version_skew_tests_v119.0.6030.0',
+          'revision': 'version:119.0.6030.0',
         },
       ],
     },
@@ -787,7 +787,6 @@
       'cros_board': 'volteer',
       'cros_model': 'voxel',
       'cros_img': 'volteer-public/R119-15623.0.0',
-      'autotest_name': 'tast.lacros-from-gcs',
       'bucket': 'chromiumos-image-archive',
       'dut_pool': 'chromium',
       'public_builder': 'cros_test_platform_public',
diff --git a/testing/scripts/run_finch_smoke_tests_android.py b/testing/scripts/run_finch_smoke_tests_android.py
index 462a10b..4a9605a 100755
--- a/testing/scripts/run_finch_smoke_tests_android.py
+++ b/testing/scripts/run_finch_smoke_tests_android.py
@@ -606,8 +606,7 @@
     # of the scoped storage feature.
     tests_root_dir = posixpath.join(self._device.GetExternalStoragePath(),
                                     'chromium_tests_root')
-    local_device_environment.place_nomedia_on_device(self._device,
-                                                     tests_root_dir)
+    self._device.PlaceNomediaFile(tests_root_dir)
 
     # Store screenshot tests on the device's external storage.
     for test_file in self.pixel_tests:
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 9aaa458..0551939e0 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -9973,28 +9973,6 @@
             ]
         }
     ],
-    "MetricsClearLogsOnClonedInstall": [
-        {
-            "platforms": [
-                "android",
-                "android_webview",
-                "chromeos",
-                "chromeos_lacros",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "MetricsClearLogsOnClonedInstall"
-                    ]
-                }
-            ]
-        }
-    ],
     "MetricsServiceAsyncIndependentLogs": [
         {
             "platforms": [
@@ -10389,6 +10367,21 @@
             ]
         }
     ],
+    "NotificationGesturesUpdate": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "NotificationGesturesUpdate"
+                    ]
+                }
+            ]
+        }
+    ],
     "NotifierCollision": [
         {
             "platforms": [
diff --git a/third_party/androidx/README.chromium b/third_party/androidx/README.chromium
index 040c568..43f0da60 100644
--- a/third_party/androidx/README.chromium
+++ b/third_party/androidx/README.chromium
@@ -41,4 +41,5 @@
   it manually and out-of-band with the rest of androidx. Use the
   update_source.sh script to pull in changes from androidx-main.
   https://crbug.com/1414452
+* Added a no-op version of androidx.window
 * Pin androidx_recycleview_recycleview to avoid https://crbug.com/1421341.
diff --git a/third_party/androidx/customizations.gni b/third_party/androidx/customizations.gni
index fefa279..012ad63c 100644
--- a/third_party/androidx/customizations.gni
+++ b/third_party/androidx/customizations.gni
@@ -112,6 +112,13 @@
       ]
     }
   }
+
+  # Arbitrarily use this target to add new top-level GN targets.
+  if (target_name == "androidx_annotation_annotation_jvm_java") {
+    java_group("androidx_window_stubs_java") {
+      deps = [ "//third_party/androidx/local_modifications/window:androidx_window_shims_java" ]
+    }
+  }
 }
 
 template("androidx_java_prebuilt") {
diff --git a/third_party/androidx/local_modifications/window/BUILD.gn b/third_party/androidx/local_modifications/window/BUILD.gn
new file mode 100644
index 0000000..5bbb91d9
--- /dev/null
+++ b/third_party/androidx/local_modifications/window/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+# Target contains no-op implementations of androidx.window symbols needed by internal chrome.
+# See b/301417565 and https://crbug.com/1415351
+android_library("androidx_window_shims_java") {
+  visibility = [
+    ":*",
+    "//third_party/androidx:*",
+  ]
+  sources = [
+    "java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapter.java",
+    "java/androidx/window/layout/DisplayFeature.java",
+    "java/androidx/window/layout/FoldingFeature.java",
+    "java/androidx/window/layout/WindowInfoTracker.java",
+    "java/androidx/window/layout/WindowLayoutInfo.java",
+  ]
+  deps = [
+    "//third_party/androidx:androidx_annotation_annotation_jvm_java",
+    "//third_party/androidx:androidx_core_core_java",
+  ]
+}
diff --git a/third_party/androidx/local_modifications/window/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapter.java b/third_party/androidx/local_modifications/window/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapter.java
new file mode 100644
index 0000000..f8ebb84
--- /dev/null
+++ b/third_party/androidx/local_modifications/window/java/androidx/window/java/layout/WindowInfoTrackerCallbackAdapter.java
@@ -0,0 +1,27 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package androidx.window.java.layout;
+
+import android.app.Activity;
+import android.content.Context;
+import androidx.annotation.UiContext;
+import androidx.core.util.Consumer;
+import androidx.window.layout.WindowInfoTracker;
+import androidx.window.layout.WindowLayoutInfo;
+import java.util.concurrent.Executor;
+
+/**
+ * Placeholder so that things that use it compile.
+ */
+public class WindowInfoTrackerCallbackAdapter {
+
+  public WindowInfoTrackerCallbackAdapter(WindowInfoTracker tracker) {
+  }
+  public void addWindowLayoutInfoListener(Activity activity, Executor executor, Consumer<WindowLayoutInfo> consumer) {
+  }
+  public void addWindowLayoutInfoListener( @UiContext Context context, Executor executor, Consumer<WindowLayoutInfo> consumer) {
+  }
+  public void removeWindowLayoutInfoListener(Consumer<WindowLayoutInfo> consumer) {
+  }
+}
diff --git a/third_party/androidx/local_modifications/window/java/androidx/window/layout/DisplayFeature.java b/third_party/androidx/local_modifications/window/java/androidx/window/layout/DisplayFeature.java
new file mode 100644
index 0000000..1ebf00e
--- /dev/null
+++ b/third_party/androidx/local_modifications/window/java/androidx/window/layout/DisplayFeature.java
@@ -0,0 +1,13 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package androidx.window.layout;
+
+import android.graphics.Rect;
+
+/**
+ * Placeholder so that things that use it compile.
+ */
+public interface DisplayFeature {
+    Rect getBounds();
+}
diff --git a/third_party/androidx/local_modifications/window/java/androidx/window/layout/FoldingFeature.java b/third_party/androidx/local_modifications/window/java/androidx/window/layout/FoldingFeature.java
new file mode 100644
index 0000000..6e5ae0d
--- /dev/null
+++ b/third_party/androidx/local_modifications/window/java/androidx/window/layout/FoldingFeature.java
@@ -0,0 +1,27 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package androidx.window.layout;
+
+/**
+ * Placeholder so that things that use it compile.
+ */
+public interface FoldingFeature extends DisplayFeature {
+  public class OcclusionType {
+      public static final OcclusionType NONE = null;
+      public static final OcclusionType FULL = null;
+  }
+  public class Orientation {
+      public static final Orientation VERTICAL = null;
+      public static final Orientation HORIZONTAL = null;
+  }
+  public class State {
+      public static final State FLAT = null;
+      public static final State HALF_OPENED = null;
+  }
+
+  boolean isSeparating();
+  OcclusionType getOcclusionType();
+  Orientation getOrientation();
+  State getState();
+}
diff --git a/third_party/androidx/local_modifications/window/java/androidx/window/layout/WindowInfoTracker.java b/third_party/androidx/local_modifications/window/java/androidx/window/layout/WindowInfoTracker.java
new file mode 100644
index 0000000..db3f6e2e
--- /dev/null
+++ b/third_party/androidx/local_modifications/window/java/androidx/window/layout/WindowInfoTracker.java
@@ -0,0 +1,15 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package androidx.window.layout;
+
+import android.content.Context;
+
+/**
+ * Placeholder so that things that use it compile.
+ */
+public interface WindowInfoTracker {
+  public static WindowInfoTracker getOrCreate(Context context) {
+    return new WindowInfoTracker() {};
+  }
+}
diff --git a/third_party/androidx/local_modifications/window/java/androidx/window/layout/WindowLayoutInfo.java b/third_party/androidx/local_modifications/window/java/androidx/window/layout/WindowLayoutInfo.java
new file mode 100644
index 0000000..4901ec1
--- /dev/null
+++ b/third_party/androidx/local_modifications/window/java/androidx/window/layout/WindowLayoutInfo.java
@@ -0,0 +1,16 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package androidx.window.layout;
+
+import java.util.List;
+
+/**
+ * Placeholder so that things that use it compile.
+ */
+public class WindowLayoutInfo {
+
+  List<DisplayFeature> getDisplayFeatures() {
+   return null;
+  }
+}
diff --git a/third_party/blink/common/indexeddb/indexeddb_key.cc b/third_party/blink/common/indexeddb/indexeddb_key.cc
index 2ec7f65..59ed55f 100644
--- a/third_party/blink/common/indexeddb/indexeddb_key.cc
+++ b/third_party/blink/common/indexeddb/indexeddb_key.cc
@@ -83,6 +83,7 @@
                      (string_.length() * sizeof(std::u16string::value_type))) {}
 
 IndexedDBKey::IndexedDBKey(const IndexedDBKey& other) = default;
+IndexedDBKey::IndexedDBKey(IndexedDBKey&& other) = default;
 IndexedDBKey::~IndexedDBKey() = default;
 IndexedDBKey& IndexedDBKey::operator=(const IndexedDBKey& other) = default;
 
diff --git a/third_party/blink/public/common/indexeddb/indexeddb_key.h b/third_party/blink/public/common/indexeddb/indexeddb_key.h
index 9579cd4..2d2fda70 100644
--- a/third_party/blink/public/common/indexeddb/indexeddb_key.h
+++ b/third_party/blink/public/common/indexeddb/indexeddb_key.h
@@ -33,6 +33,7 @@
   IndexedDBKey(double number,
                mojom::IDBKeyType type);  // must be date or number
   IndexedDBKey(const IndexedDBKey& other);
+  IndexedDBKey(IndexedDBKey&& other);
   ~IndexedDBKey();
   IndexedDBKey& operator=(const IndexedDBKey& other);
 
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index c233d48..2ecfc12 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -4008,6 +4008,7 @@
   kOutOfFlowAlignSelfNoInsets = 4668,
   kOutOfFlowAlignSelfSingleInset = 4669,
   kOutOfFlowAlignSelfBothInsets = 4670,
+  kV8WebAssemblyJSStringBuiltins = 4671,
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
   // Also, run update_use_counter_feature_enum.py in
diff --git a/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc b/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
index 744fefc8..f443c55 100644
--- a/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
+++ b/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
@@ -348,6 +348,9 @@
     case v8::Isolate::kWasmGC:
       blink_feature = WebFeature::kV8WasmGC;
       break;
+    case v8::Isolate::kWasmImportedStrings:
+      blink_feature = WebFeature::kV8WebAssemblyJSStringBuiltins;
+      break;
     default:
       // This can happen if V8 has added counters that this version of Blink
       // does not know about. It's harmless.
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
index 314b9db6..0a476b4 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -578,6 +578,15 @@
   return RuntimeEnabledFeatures::WebAssemblyGCEnabled(execution_context);
 }
 
+bool WasmJSStringBuiltinsEnabledCallback(v8::Local<v8::Context> context) {
+  ExecutionContext* execution_context = ToExecutionContext(context);
+  if (!execution_context) {
+    return false;
+  }
+  return RuntimeEnabledFeatures::WebAssemblyJSStringBuiltinsEnabled(
+      execution_context);
+}
+
 bool JavaScriptCompileHintsMagicEnabledCallback(
     v8::Local<v8::Context> context) {
   ExecutionContext* execution_context = ToExecutionContext(context);
@@ -706,6 +715,8 @@
   isolate->SetWasmModuleCallback(WasmModuleOverride);
   isolate->SetWasmInstanceCallback(WasmInstanceOverride);
   isolate->SetWasmGCEnabledCallback(WasmGCEnabledCallback);
+  isolate->SetWasmImportedStringsEnabledCallback(
+      WasmJSStringBuiltinsEnabledCallback);
   isolate->SetSharedArrayBufferConstructorEnabledCallback(
       SharedArrayBufferConstructorEnabledCallback);
   isolate->SetJavaScriptCompileHintsMagicEnabledCallback(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
index aa4e2841..6684653a0 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
@@ -279,6 +279,13 @@
       // This descendant starts in a later container. So this isn't the last
       // container for the culled inline.
       *is_last_container = false;
+      if (!found_item && descendant->IsFloating()) {
+        // Keep looking if we haven't found anything here. Even if this float
+        // starts in a later container, there may still be something to be found
+        // in this container. A float may be pushed to the next fragmentainer,
+        // while subsequent in-flow content may still fit in this container.
+        continue;
+      }
       return found_item;
     }
 
diff --git a/third_party/blink/renderer/core/svg/build.gni b/third_party/blink/renderer/core/svg/build.gni
index 8b0bcff0..4a78a51 100644
--- a/third_party/blink/renderer/core/svg/build.gni
+++ b/third_party/blink/renderer/core/svg/build.gni
@@ -320,6 +320,8 @@
   "svg_title_element.h",
   "svg_transform.cc",
   "svg_transform.h",
+  "svg_transformable_element.cc",
+  "svg_transformable_element.h",
   "svg_transform_distance.cc",
   "svg_transform_distance.h",
   "svg_transform_list.cc",
diff --git a/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc b/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc
index bca6fa3..b7c11389 100644
--- a/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc
@@ -41,8 +41,12 @@
 bool TargetCanHaveMotionTransform(const SVGElement& target) {
   // We don't have a special attribute name to verify the animation type. Check
   // the element name instead.
-  if (!IsA<SVGGraphicsElement>(target))
+  if (IsA<SVGClipPathElement>(target)) {
+    return true;
+  }
+  if (!IsA<SVGGraphicsElement>(target)) {
     return false;
+  }
   // Spec: SVG 1.1 section 19.2.15
   // FIXME: svgTag is missing. Needs to be checked, if transforming <svg> could
   // cause problems.
@@ -52,11 +56,11 @@
          IsA<SVGRectElement>(target) || IsA<SVGCircleElement>(target) ||
          IsA<SVGEllipseElement>(target) || IsA<SVGLineElement>(target) ||
          IsA<SVGPolylineElement>(target) || IsA<SVGPolygonElement>(target) ||
-         IsA<SVGTextElement>(target) || IsA<SVGClipPathElement>(target) ||
-         IsA<SVGMaskElement>(target) || IsA<SVGAElement>(target) ||
+         IsA<SVGTextElement>(target) || IsA<SVGAElement>(target) ||
          IsA<SVGForeignObjectElement>(target);
 }
-}
+
+}  // namespace
 
 SVGAnimateMotionElement::SVGAnimateMotionElement(Document& document)
     : SVGAnimationElement(svg_names::kAnimateMotionTag, document) {
diff --git a/third_party/blink/renderer/core/svg/svg_clip_path_element.cc b/third_party/blink/renderer/core/svg/svg_clip_path_element.cc
index fbae7c0a..827209c 100644
--- a/third_party/blink/renderer/core/svg/svg_clip_path_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_clip_path_element.cc
@@ -27,7 +27,7 @@
 namespace blink {
 
 SVGClipPathElement::SVGClipPathElement(Document& document)
-    : SVGGraphicsElement(svg_names::kClipPathTag, document),
+    : SVGTransformableElement(svg_names::kClipPathTag, document),
       clip_path_units_(MakeGarbageCollected<
                        SVGAnimatedEnumeration<SVGUnitTypes::SVGUnitType>>(
           this,
@@ -36,26 +36,24 @@
 
 void SVGClipPathElement::Trace(Visitor* visitor) const {
   visitor->Trace(clip_path_units_);
-  SVGGraphicsElement::Trace(visitor);
+  SVGTransformableElement::Trace(visitor);
 }
 
 void SVGClipPathElement::SvgAttributeChanged(
     const SvgAttributeChangedParams& params) {
   if (params.name == svg_names::kClipPathUnitsAttr) {
     SVGElement::InvalidationGuard invalidation_guard(this);
-
     auto* layout_object = To<LayoutSVGResourceContainer>(GetLayoutObject());
     if (layout_object) {
       layout_object->InvalidateCache();
     }
     return;
   }
-
-  SVGGraphicsElement::SvgAttributeChanged(params);
+  SVGTransformableElement::SvgAttributeChanged(params);
 }
 
 void SVGClipPathElement::ChildrenChanged(const ChildrenChange& change) {
-  SVGGraphicsElement::ChildrenChanged(change);
+  SVGTransformableElement::ChildrenChanged(change);
 
   if (change.ByParser())
     return;
@@ -74,15 +72,14 @@
     const QualifiedName& attribute_name) const {
   if (attribute_name == svg_names::kClipPathUnitsAttr) {
     return clip_path_units_.Get();
-  } else {
-    return SVGGraphicsElement::PropertyFromAttribute(attribute_name);
   }
+  return SVGTransformableElement::PropertyFromAttribute(attribute_name);
 }
 
 void SVGClipPathElement::SynchronizeAllSVGAttributes() const {
   SVGAnimatedPropertyBase* attrs[]{clip_path_units_.Get()};
   SynchronizeListOfSVGAttributes(attrs);
-  SVGGraphicsElement::SynchronizeAllSVGAttributes();
+  SVGTransformableElement::SynchronizeAllSVGAttributes();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_clip_path_element.h b/third_party/blink/renderer/core/svg/svg_clip_path_element.h
index 87a9546..a571ce58 100644
--- a/third_party/blink/renderer/core/svg/svg_clip_path_element.h
+++ b/third_party/blink/renderer/core/svg/svg_clip_path_element.h
@@ -22,15 +22,12 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_CLIP_PATH_ELEMENT_H_
 
 #include "third_party/blink/renderer/core/svg/svg_animated_enumeration.h"
-#include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
+#include "third_party/blink/renderer/core/svg/svg_transformable_element.h"
 #include "third_party/blink/renderer/core/svg/svg_unit_types.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
 namespace blink {
 
-class LayoutObject;
-
-class SVGClipPathElement final : public SVGGraphicsElement {
+class SVGClipPathElement final : public SVGTransformableElement {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/blink/renderer/core/svg/svg_clip_path_element.idl b/third_party/blink/renderer/core/svg/svg_clip_path_element.idl
index d477641d..8a7b559 100644
--- a/third_party/blink/renderer/core/svg/svg_clip_path_element.idl
+++ b/third_party/blink/renderer/core/svg/svg_clip_path_element.idl
@@ -26,11 +26,9 @@
 
 // https://drafts.fxtf.org/css-masking/#InterfaceSVGClipPathElement
 
-// TODO(foolip): SVGClipPathElement should inherit from SVGElement and
-// implement SVGUnitTypes. The transform attribute (which is on
-// SVGGraphicsElement) should also be on SVGClipPathElement.
 [
     Exposed=Window
-] interface SVGClipPathElement : SVGGraphicsElement {
+] interface SVGClipPathElement : SVGElement {
     [Measure] readonly attribute SVGAnimatedEnumeration clipPathUnits;
+    readonly attribute SVGAnimatedTransformList transform;
 };
diff --git a/third_party/blink/renderer/core/svg/svg_element.cc b/third_party/blink/renderer/core/svg/svg_element.cc
index 7aa8b69..3e2df33e 100644
--- a/third_party/blink/renderer/core/svg/svg_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_element.cc
@@ -301,8 +301,8 @@
 }
 
 AffineTransform SVGElement::LocalCoordinateSpaceTransform(CTMScope) const {
-  // To be overriden by SVGGraphicsElement (or as special case SVGTextElement
-  // and SVGPatternElement)
+  // To be overridden by SVGTransformableElement (or as special case
+  // SVGTextElement and SVGPatternElement)
   return AffineTransform();
 }
 
diff --git a/third_party/blink/renderer/core/svg/svg_graphics_element.cc b/third_party/blink/renderer/core/svg/svg_graphics_element.cc
index 4cacbc9a..ecc1e25 100644
--- a/third_party/blink/renderer/core/svg/svg_graphics_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_graphics_element.cc
@@ -21,14 +21,10 @@
 
 #include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
 
-#include "third_party/blink/renderer/core/css/style_change_reason.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/svg/svg_animated_transform_list.h"
-#include "third_party/blink/renderer/core/svg/svg_element_rare_data.h"
 #include "third_party/blink/renderer/core/svg/svg_matrix_tear_off.h"
 #include "third_party/blink/renderer/core/svg/svg_rect_tear_off.h"
-#include "third_party/blink/renderer/core/svg_names.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/transforms/affine_transform.h"
@@ -38,18 +34,13 @@
 SVGGraphicsElement::SVGGraphicsElement(const QualifiedName& tag_name,
                                        Document& document,
                                        ConstructionType construction_type)
-    : SVGElement(tag_name, document, construction_type),
-      SVGTests(this),
-      transform_(MakeGarbageCollected<SVGAnimatedTransformList>(
-          this,
-          svg_names::kTransformAttr,
-          CSSPropertyID::kTransform)) {}
+    : SVGTransformableElement(tag_name, document, construction_type),
+      SVGTests(this) {}
 
 SVGGraphicsElement::~SVGGraphicsElement() = default;
 
 void SVGGraphicsElement::Trace(Visitor* visitor) const {
-  visitor->Trace(transform_);
-  SVGElement::Trace(visitor);
+  SVGTransformableElement::Trace(visitor);
   SVGTests::Trace(visitor);
 }
 
@@ -105,28 +96,6 @@
   return MakeGarbageCollected<SVGMatrixTearOff>(ComputeCTM(kScreenScope));
 }
 
-void SVGGraphicsElement::CollectStyleForPresentationAttribute(
-    const QualifiedName& name,
-    const AtomicString& value,
-    MutableCSSPropertyValueSet* style) {
-  if (name == svg_names::kTransformAttr) {
-    AddPropertyToPresentationAttributeStyle(
-        style, CSSPropertyID::kTransform,
-        *transform_->CurrentValue()->CssValue());
-    return;
-  }
-  SVGElement::CollectStyleForPresentationAttribute(name, value, style);
-}
-
-AffineTransform SVGGraphicsElement::LocalCoordinateSpaceTransform(
-    CTMScope) const {
-  return CalculateTransform(kIncludeMotionTransform);
-}
-
-AffineTransform* SVGGraphicsElement::AnimateMotionTransform() {
-  return EnsureSVGRareData()->AnimateMotionTransform();
-}
-
 void SVGGraphicsElement::SvgAttributeChanged(
     const SvgAttributeChangedParams& params) {
   const QualifiedName& attr_name = params.name;
@@ -137,20 +106,7 @@
     SetForceReattachLayoutTree();
     return;
   }
-
-  if (attr_name == svg_names::kTransformAttr) {
-    SVGElement::InvalidationGuard invalidation_guard(this);
-    InvalidateSVGPresentationAttributeStyle();
-    // TODO(fs): The InvalidationGuard will make sure all instances are
-    // invalidated, but the style recalc will propagate to instances too. So
-    // there is some redundant operations being performed here. Could we get
-    // away with removing the InvalidationGuard?
-    SetNeedsStyleRecalc(kLocalStyleChange,
-                        StyleChangeReasonForTracing::FromAttribute(attr_name));
-    return;
-  }
-
-  SVGElement::SvgAttributeChanged(params);
+  SVGTransformableElement::SvgAttributeChanged(params);
 }
 
 SVGElement* SVGGraphicsElement::nearestViewportElement() const {
@@ -196,33 +152,17 @@
 
 SVGAnimatedPropertyBase* SVGGraphicsElement::PropertyFromAttribute(
     const QualifiedName& attribute_name) const {
-  if (attribute_name == svg_names::kTransformAttr) {
-    return transform_.Get();
-  } else {
-    SVGAnimatedPropertyBase* ret =
-        SVGTests::PropertyFromAttribute(attribute_name);
-    if (ret) {
-      return ret;
-    }
-    return SVGElement::PropertyFromAttribute(attribute_name);
+  SVGAnimatedPropertyBase* ret =
+      SVGTests::PropertyFromAttribute(attribute_name);
+  if (ret) {
+    return ret;
   }
+  return SVGTransformableElement::PropertyFromAttribute(attribute_name);
 }
 
 void SVGGraphicsElement::SynchronizeAllSVGAttributes() const {
-  SVGAnimatedPropertyBase* attrs[]{transform_.Get()};
-  SynchronizeListOfSVGAttributes(attrs);
   SVGTests::SynchronizeAllSVGAttributes();
-  SVGElement::SynchronizeAllSVGAttributes();
-}
-
-void SVGGraphicsElement::CollectExtraStyleForPresentationAttribute(
-    MutableCSSPropertyValueSet* style) {
-  DCHECK(transform_->HasPresentationAttributeMapping());
-  if (transform_->IsAnimating()) {
-    CollectStyleForPresentationAttribute(svg_names::kTransformAttr,
-                                         g_empty_atom, style);
-  }
-  SVGElement::CollectExtraStyleForPresentationAttribute(style);
+  SVGTransformableElement::SynchronizeAllSVGAttributes();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_graphics_element.h b/third_party/blink/renderer/core/svg/svg_graphics_element.h
index 732cd4e..499eb84 100644
--- a/third_party/blink/renderer/core/svg/svg_graphics_element.h
+++ b/third_party/blink/renderer/core/svg/svg_graphics_element.h
@@ -23,18 +23,16 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_GRAPHICS_ELEMENT_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/svg/svg_element.h"
 #include "third_party/blink/renderer/core/svg/svg_tests.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/core/svg/svg_transformable_element.h"
 
 namespace blink {
 
-class AffineTransform;
-class SVGAnimatedTransformList;
 class SVGMatrixTearOff;
 class SVGRectTearOff;
 
-class CORE_EXPORT SVGGraphicsElement : public SVGElement, public SVGTests {
+class CORE_EXPORT SVGGraphicsElement : public SVGTransformableElement,
+                                       public SVGTests {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -46,17 +44,11 @@
   SVGElement* nearestViewportElement() const;
   SVGElement* farthestViewportElement() const;
 
-  AffineTransform LocalCoordinateSpaceTransform(CTMScope) const override;
-  AffineTransform* AnimateMotionTransform() override;
-
   virtual gfx::RectF GetBBox();
   SVGRectTearOff* getBBoxFromJavascript();
 
   bool IsValid() const final { return SVGTests::IsValid(); }
 
-  SVGAnimatedTransformList* transform() { return transform_.Get(); }
-  const SVGAnimatedTransformList* transform() const { return transform_.Get(); }
-
   AffineTransform ComputeCTM(
       CTMScope mode,
       const SVGGraphicsElement* ancestor = nullptr) const;
@@ -72,19 +64,11 @@
     return Element::SupportsFocus() || HasFocusEventListeners();
   }
 
-  void CollectStyleForPresentationAttribute(
-      const QualifiedName&,
-      const AtomicString&,
-      MutableCSSPropertyValueSet*) override;
   void SvgAttributeChanged(const SvgAttributeChangedParams&) override;
 
   SVGAnimatedPropertyBase* PropertyFromAttribute(
       const QualifiedName& attribute_name) const override;
   void SynchronizeAllSVGAttributes() const override;
-  void CollectExtraStyleForPresentationAttribute(
-      MutableCSSPropertyValueSet* style) override;
-
-  Member<SVGAnimatedTransformList> transform_;
 
  private:
   bool IsSVGGraphicsElement() const final { return true; }
diff --git a/third_party/blink/renderer/core/svg/svg_transformable_element.cc b/third_party/blink/renderer/core/svg/svg_transformable_element.cc
new file mode 100644
index 0000000..37f79e6
--- /dev/null
+++ b/third_party/blink/renderer/core/svg/svg_transformable_element.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
+
+#include "third_party/blink/renderer/core/css/style_change_reason.h"
+#include "third_party/blink/renderer/core/svg/svg_animated_transform_list.h"
+#include "third_party/blink/renderer/core/svg/svg_element_rare_data.h"
+#include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
+
+namespace blink {
+
+SVGTransformableElement::SVGTransformableElement(
+    const QualifiedName& tag_name,
+    Document& document,
+    ConstructionType construction_type)
+    : SVGElement(tag_name, document, construction_type),
+      transform_(MakeGarbageCollected<SVGAnimatedTransformList>(
+          this,
+          svg_names::kTransformAttr,
+          CSSPropertyID::kTransform)) {}
+
+SVGTransformableElement::~SVGTransformableElement() = default;
+
+void SVGTransformableElement::Trace(Visitor* visitor) const {
+  visitor->Trace(transform_);
+  SVGElement::Trace(visitor);
+}
+
+void SVGTransformableElement::CollectStyleForPresentationAttribute(
+    const QualifiedName& name,
+    const AtomicString& value,
+    MutableCSSPropertyValueSet* style) {
+  if (name == svg_names::kTransformAttr) {
+    AddPropertyToPresentationAttributeStyle(
+        style, CSSPropertyID::kTransform,
+        *transform_->CurrentValue()->CssValue());
+    return;
+  }
+  SVGElement::CollectStyleForPresentationAttribute(name, value, style);
+}
+
+void SVGTransformableElement::CollectExtraStyleForPresentationAttribute(
+    MutableCSSPropertyValueSet* style) {
+  DCHECK(transform_->HasPresentationAttributeMapping());
+  if (transform_->IsAnimating()) {
+    CollectStyleForPresentationAttribute(svg_names::kTransformAttr,
+                                         g_empty_atom, style);
+  }
+  SVGElement::CollectExtraStyleForPresentationAttribute(style);
+}
+
+AffineTransform SVGTransformableElement::LocalCoordinateSpaceTransform(
+    CTMScope) const {
+  return CalculateTransform(kIncludeMotionTransform);
+}
+
+AffineTransform* SVGTransformableElement::AnimateMotionTransform() {
+  return EnsureSVGRareData()->AnimateMotionTransform();
+}
+
+void SVGTransformableElement::SvgAttributeChanged(
+    const SvgAttributeChangedParams& params) {
+  const QualifiedName& attr_name = params.name;
+  if (attr_name == svg_names::kTransformAttr) {
+    SVGElement::InvalidationGuard invalidation_guard(this);
+    InvalidateSVGPresentationAttributeStyle();
+    // TODO(fs): The InvalidationGuard will make sure all instances are
+    // invalidated, but the style recalc will propagate to instances too. So
+    // there is some redundant operations being performed here. Could we get
+    // away with removing the InvalidationGuard?
+    SetNeedsStyleRecalc(kLocalStyleChange,
+                        StyleChangeReasonForTracing::FromAttribute(attr_name));
+    return;
+  }
+
+  SVGElement::SvgAttributeChanged(params);
+}
+
+SVGAnimatedPropertyBase* SVGTransformableElement::PropertyFromAttribute(
+    const QualifiedName& attribute_name) const {
+  if (attribute_name == svg_names::kTransformAttr) {
+    return transform_.Get();
+  }
+  return SVGElement::PropertyFromAttribute(attribute_name);
+}
+
+void SVGTransformableElement::SynchronizeAllSVGAttributes() const {
+  SVGAnimatedPropertyBase* attrs[]{transform_.Get()};
+  SynchronizeListOfSVGAttributes(attrs);
+  SVGElement::SynchronizeAllSVGAttributes();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_transformable_element.h b/third_party/blink/renderer/core/svg/svg_transformable_element.h
new file mode 100644
index 0000000..7f2268f
--- /dev/null
+++ b/third_party/blink/renderer/core/svg/svg_transformable_element.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_TRANSFORMABLE_ELEMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_TRANSFORMABLE_ELEMENT_H_
+
+#include "third_party/blink/renderer/core/svg/svg_element.h"
+
+namespace blink {
+
+class AffineTransform;
+class SVGAnimatedTransformList;
+
+// Intermediate class for SVGElements that have a 'transform' IDL
+// attribute. Not exposed in IDL.
+class SVGTransformableElement : public SVGElement {
+ public:
+  ~SVGTransformableElement() override;
+
+  AffineTransform LocalCoordinateSpaceTransform(CTMScope) const override;
+  AffineTransform* AnimateMotionTransform() override;
+
+  SVGAnimatedTransformList* transform() { return transform_.Get(); }
+  const SVGAnimatedTransformList* transform() const { return transform_.Get(); }
+
+  void Trace(Visitor*) const override;
+
+ protected:
+  SVGTransformableElement(const QualifiedName&,
+                          Document&,
+                          ConstructionType = kCreateSVGElement);
+
+  void CollectStyleForPresentationAttribute(
+      const QualifiedName&,
+      const AtomicString&,
+      MutableCSSPropertyValueSet*) override;
+  void CollectExtraStyleForPresentationAttribute(
+      MutableCSSPropertyValueSet* style) override;
+  void SvgAttributeChanged(const SvgAttributeChangedParams&) override;
+
+  SVGAnimatedPropertyBase* PropertyFromAttribute(
+      const QualifiedName& attribute_name) const override;
+  void SynchronizeAllSVGAttributes() const override;
+
+  Member<SVGAnimatedTransformList> transform_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_TRANSFORMABLE_ELEMENT_H_
diff --git a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc
index ae1d80de..1101f1b 100644
--- a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc
+++ b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc
@@ -171,7 +171,7 @@
   while (!same_document_navigation_tasks_.empty()) {
     auto task = same_document_navigation_tasks_.front();
     same_document_navigation_tasks_.pop_front();
-    if (task->Id() == task_id) {
+    if (task && task->Id() == task_id) {
       return task;
     }
   }
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc
index fe3615e..a8fd83c 100644
--- a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc
+++ b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc
@@ -333,7 +333,8 @@
     return true;
   }
 
-  if (feature == OriginTrialFeature::kJavaScriptCompileHintsMagicRuntime) {
+  if (feature == OriginTrialFeature::kJavaScriptCompileHintsMagicRuntime ||
+      feature == OriginTrialFeature::kWebAssemblyJSStringBuiltins) {
     return false;
   }
 
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc
index 6f1a2b57..bfa8f63a 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc
@@ -324,6 +324,7 @@
   scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
   scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
   media::GpuVideoAcceleratorFactories* gpu_factories_;
+  std::unique_ptr<media::MediaLog> media_log_;
   mojo::Remote<media::mojom::InterfaceFactory> media_interface_factory_;
   std::unique_ptr<WebCodecsVideoDecoderSelector> selector_;
   std::unique_ptr<media::DecoderFactory> decoder_factory_;
@@ -337,8 +338,6 @@
       fuchsia_media_codec_provider_;
 #endif
 
-  std::unique_ptr<media::MediaLog> media_log_;
-
   SEQUENCE_CHECKER(sequence_checker_);
 
   // Using unretained for decoder/selector callbacks is generally not safe /
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
index 87a330ea..869ed5c0 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
@@ -192,9 +192,6 @@
   }
 
   ~VideoDecoderBrokerTest() override {
-    if (media_thread_)
-      media_thread_->Stop();
-
     // Clean up this override, or else we we fail or DCHECK in SetupMojo().
     Platform::Current()->GetBrowserInterfaceBroker()->SetBinderForTesting(
         media::mojom::InterfaceFactory::Name_,
@@ -328,11 +325,11 @@
 
  protected:
   media::NullMediaLog null_media_log_;
+  std::unique_ptr<base::Thread> media_thread_;
   std::unique_ptr<VideoDecoderBroker> decoder_broker_;
   std::vector<scoped_refptr<media::VideoFrame>> output_frames_;
   std::unique_ptr<media::MockGpuVideoAcceleratorFactories> gpu_factories_;
   std::unique_ptr<FakeInterfaceFactory> interface_factory_;
-  std::unique_ptr<base::Thread> media_thread_;
 
   base::test::ScopedFeatureList feature_list_;
 };
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index 04c0445..79616bd 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -325,8 +325,10 @@
   if (is_hidden_ == hidden)
     return;
   is_hidden_ = hidden;
-  if (is_hidden_)
+  if (is_hidden_) {
     recycled_color_buffer_queue_.clear();
+    recycled_bitmaps_.clear();
+  }
 
   // Make sure to interrupt pixel local storage.
   ScopedStateRestorer scoped_state_restorer(this);
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h
index 3443f71..65a9ae7 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_stream_adapter.h
@@ -33,10 +33,6 @@
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/size.h"
 
-namespace base {
-class SequencedThreadTaskRunner;
-}  // namespace base
-
 namespace media {
 class DecoderBuffer;
 class DecoderFactory;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index bd5fd5e..8c00e52 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -4030,6 +4030,12 @@
       status: "experimental",
       base_feature: "none",
     },
+    {
+      name: "WebAssemblyJSStringBuiltins",
+      origin_trial_feature_name: "WebAssemblyJSStringBuiltins",
+      status: "experimental",
+      base_feature: "none",
+    },
     // WebAuth is disabled on Android versions prior to N (7.0) due to lack of
     // supporting APIs, see runtime_features.cc.
     {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 956be09f..87a8c6d 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -5724,7 +5724,7 @@
 crbug.com/1406027 [ Win ] virtual/media-foundation-for-clear-dcomp/media/controls/overflow-menu-hide-on-resize.html [ Failure ]
 crbug.com/1289607 [ Linux ] external/wpt/cookie-store/cookieStore_subscribe_arguments.https.any.html [ Failure ]
 crbug.com/1408294 [ Debug Linux ] virtual/gpu/external/wpt/mediacapture-record/MediaRecorder-canvas-media-source.https.html [ Failure ]
-crbug.com/1229708 [ Debug Linux ] fast/events/pointerevents/pointer-event-in-slop-region.html [ Failure ]
+crbug.com/1229708 fast/events/pointerevents/pointer-event-in-slop-region.html [ Failure Pass ]
 crbug.com/1406896 [ Linux ] http/tests/inspector-protocol/cpu-profiler/record-cpu-profile-with-cpu-throttling.js [ Crash ]
 crbug.com/1370749 [ Debug Linux ] virtual/threaded-no-composited-antialiasing/animations/add-keyframes-recalc.html [ Failure ]
 crbug.com/1422340 [ Win ] virtual/media-foundation-for-clear-dcomp/media/video-move-to-document-pip.html [ Failure ]
@@ -6748,3 +6748,6 @@
 
 # Gardener 2023-09-21
 external/wpt/html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/window-open-204-fragment.html [ Failure ]
+
+# Gardener 2023-09-25
+crbug.com/1486580 virtual/view-transition/external/wpt/css/css-view-transitions/snapshot-containing-block-absolute.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/xml-parser-error-message-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/xml-parser-error-message-crash-expected.txt
index 9ae360d..75d472a 100644
--- a/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/xml-parser-error-message-crash-expected.txt
+++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/xml-parser-error-message-crash-expected.txt
@@ -1,5 +1,5 @@
 CONSOLE WARNING: Listener added for a synchronous 'DOMNodeInsertedIntoDocument' DOM Mutation Event. This event type is deprecated (https://w3c.github.io/uievents/#legacy-event-types) and work is underway to remove it from this browser. Usage of this event listener will cause performance issues today, and represents a risk of future incompatibility. Consider using MutationObserver instead.
 This page contains the following errors:
-error on line 14 at column 1: Extra content at the end of the document
+error on line 14 at column 1: Premature end of data in tag svg line 1
 
 Below is a rendering of the page up to the first error.
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 120832d7..311de3e 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
@@ -1245,6 +1245,13 @@
          {}
         ]
        ],
+       "chrome-custom-highlight-crash.html": [
+        "61e5075ed4e1b485019d96b402bbf17926bd1098",
+        [
+         null,
+         {}
+        ]
+       ],
        "chrome-layout-root-crash.html": [
         "e3e709a240bd870250b2747c94fe96880bdf52e3",
         [
@@ -192566,7 +192573,7 @@
      },
      "text-spacing-trim": {
       "text-spacing-trim-001.html": [
-       "93518d0af4f1a25109a2e848a0fb4e7784419e34",
+       "cf79e09247b52105833cbce464158838980dc739",
        [
         null,
         [
@@ -192579,7 +192586,7 @@
        ]
       ],
       "text-spacing-trim-chws-001.html": [
-       "1565c89a184713daf25104c4c687f5125cbb490c",
+       "24e23962842ec1eabb9ef9c4f9c11d7fddf12ec2",
        [
         null,
         [
@@ -192592,7 +192599,7 @@
        ]
       ],
       "text-spacing-trim-colon-001.html": [
-       "2a7dfb18fabbbef5b8d16d105325d6c037a4e6bf",
+       "d543df758f661d93977e13eb1e562130b52d4095",
        [
         null,
         [
@@ -192605,7 +192612,7 @@
        ]
       ],
       "text-spacing-trim-dot-001.html": [
-       "861ce875ff9d0cf230a2f438e888b9976bd4f733",
+       "dfbb4ae960135754e2762db0d4e856c0086b6081",
        [
         null,
         [
@@ -275470,6 +275477,19 @@
         ],
         {}
        ]
+      ],
+      "clear-mapped-animation.svg": [
+       "518fe6129faa2e00de0e30442eacc59dbee37527",
+       [
+        null,
+        [
+         [
+          "/svg/embedded/reference/green-rect-100x100.svg",
+          "=="
+         ]
+        ],
+        {}
+       ]
       ]
      },
      "use-animate-display-none-symbol.html": [
@@ -282357,11 +282377,11 @@
   "support": {
    ".cache": {
     "gitignore2.json": [
-     "a60a9eaab0b1145388f74540cec5cd1ac9afd6f7",
+     "7458c49ff58909e8e048e7d33cb7044a4a314319",
      []
     ],
     "mtime.json": [
-     "9f1d368a1b8f7bd92d8805486ee422ce92fd2388",
+     "f86346d91d0ccdec5b98333a93b5ce594fc6998c",
      []
     ]
    },
@@ -297913,7 +297933,7 @@
      ],
      "mix-blend-mode": {
       "mix-blend-mode-blended-with-transform-and-perspective.html.ini": [
-       "7fb2a4ba05f32e9950573acbb4bd54d531fefa53",
+       "3aa42fbc7251d58ba9e6b2cc444411c95e7dc3dc",
        []
       ],
       "mix-blend-mode-border-image.html.ini": [
@@ -299416,6 +299436,10 @@
        "37c62fde6d402777343e0badbb23a56dbc06573f",
        []
       ],
+      "background-repeat-repeat-x.xht.ini": [
+       "de91251c7684ceb70ea3e3d7fb7940f79e10d354",
+       []
+      ],
       "background-repeat-round-roundup.xht.ini": [
        "f20284a539621ce15b4179cfbb5adf50b0805fb4",
        []
@@ -299545,7 +299569,7 @@
        []
       ],
       "background-size-cover.xht.ini": [
-       "69a24b2cfea31f67f69efee29f20803bb3d4a3dd",
+       "a20dce1443ec79689b22d80b578deb08aa2f4eaa",
        []
       ],
       "background-size-near-zero-png.html.ini": [
@@ -303109,6 +303133,14 @@
       "f596b559b0e26b9c03d47b7dcab966a4d091308b",
       []
      ],
+     "all-prop-revert-layer-expected.txt": [
+      "34fe75fe857f21ec3f4b7644185e0862a89d7c51",
+      []
+     ],
+     "all-prop-revert-layer.html.ini": [
+      "d958bfb728d0bfc1c2bcdc0dc9621740584440ad",
+      []
+     ],
      "all-prop-revert-visited-ref.html": [
       "0ef326c2722a4f65f6657d7740a990c079b08289",
       []
@@ -322425,7 +322457,7 @@
        []
       ],
       "clip-path-rotated-will-change-transform.html.ini": [
-       "1dc7d220e520f9209654b100ef24102a9d9471f1",
+       "bc26a9582b5dcfed68cedebc0cedc0457858760b",
        []
       ],
       "clip-path-round-zero-size-ref.html": [
@@ -323346,6 +323378,14 @@
        "1ad470a62cd54ef7c30b0946c9600aaa69ca7b36",
        []
       ],
+      "clip-path-valid-expected.txt": [
+       "4d4d15e3144effdf829b5c14c5261de2bde029f6",
+       []
+      ],
+      "clip-path-valid.html.ini": [
+       "88f0aad0656251539ba3f6bcf24fee9dd32e5fda",
+       []
+      ],
       "mask-position-valid-expected.txt": [
        "f495730a977d05a59e0a2660f846587a52c219ff",
        []
@@ -329108,7 +329148,7 @@
         []
        ],
        "shape-image-015.html.ini": [
-        "2b81201f42deab533c349472ba22cbb7a66a4590",
+        "2da362cdcaaf243ced19cbfd018f1ac9494fdb70",
         []
        ],
        "shape-image-018.html.ini": [
@@ -329120,7 +329160,11 @@
         []
        ],
        "shape-image-026.html.ini": [
-        "433b21a7f625079de9aa282f43fb3b3ca4c2aabb",
+        "d701cf20bd5d9edced4b9ef00257e52189b54725",
+        []
+       ],
+       "shape-image-027.html.ini": [
+        "8616b6435ce81b0a6027cf8bddefa38524c5a61a",
         []
        ],
        "support": {
@@ -334584,40 +334628,20 @@
       ]
      },
      "text-spacing-trim": {
-      "support": {
-       "fonts": {
-        "LICENSE.txt": [
-         "d952d62c065f3f35fb83a173496e90b21525aef3",
-         []
-        ],
-        "NotoSansCJKjp-Regular-subset-chws.otf": [
-         "18859d5e2fe1200da5caef5f88d15864d0477963",
-         []
-        ],
-        "NotoSansCJKjp-Regular-subset-halt.otf": [
-         "773282263e6e0fe11c4b319ee156f403d824bc5e",
-         []
-        ],
-        "README.md": [
-         "8ff42d0f441ab9c9e0af92fc2f8b49d5c54089af",
-         []
-        ]
-       }
-      },
       "text-spacing-trim-001-ref.html": [
-       "34fe27ebf0c2a27a8e8107372c7d2569da29cd65",
+       "db57fd28158327d31aaa46110012ef8aa1ef5947",
        []
       ],
       "text-spacing-trim-001.html.ini": [
-       "af185e10c4f6d245691e453f13ecc7898167d6c6",
+       "fda94579e2d009a631b350679246d167db0d208a",
        []
       ],
       "text-spacing-trim-colon-001-ref.html": [
-       "33303f3fe85121bee7cacd196a92b7bbc06917a4",
+       "0452e68cf700cbb6d3c61c6efefe0b8640a49b4e",
        []
       ],
       "text-spacing-trim-colon-001.html.ini": [
-       "cef3413ef978b079060a745bef187d81a1d789eb",
+       "c0869ec4f3d174e5b0daa7a55410e252c12d40ae",
        []
       ],
       "text-spacing-trim-combinations-001-expected.txt": [
@@ -334629,11 +334653,11 @@
        []
       ],
       "text-spacing-trim-dot-001-ref.html": [
-       "1bd62d3881fe92c7616b1e31ccd15a7e6de32907",
+       "f1c4154a7511da1a00fdac3f297daa8af1b2dce0",
        []
       ],
       "text-spacing-trim-dot-001.html.ini": [
-       "3e192c8e7da1d199bf15a98a45d0b1807479efc6",
+       "f9b8d0962c4c8253fb8f703160993ccd809600a7",
        []
       ]
      },
@@ -335018,6 +335042,10 @@
        "82bf193fcb14382cf7bdea7ac15a07fe1ac3f4c4",
        []
       ],
+      "text-transform-capitalize-005.html.ini": [
+       "e272f367a6cc2d03d778be3f7d6a0f39e7e41536",
+       []
+      ],
       "text-transform-capitalize-007.html.ini": [
        "eccd490d21bb962ad58b65c6ee46ced1f63eda76",
        []
@@ -340876,6 +340904,10 @@
        "49428ddcbf5e050f5ec2dd2dd4b188c07f959f16",
        []
       ],
+      "kind-of-widget-fallback-input-search-border-bottom-right-radius-001.html.ini": [
+       "9afaedf7f9f431fef53d59ee1726e053d96d8414",
+       []
+      ],
       "kind-of-widget-fallback-input-search-border-bottom-style-001.html.ini": [
        "a3fbde8733b22ae0d474da12c04e04ca884db1a0",
        []
@@ -340904,6 +340936,10 @@
        "7013f55aba7162cbaf7fd92bf09bb9fe6c1ab2d8",
        []
       ],
+      "kind-of-widget-fallback-input-submit-border-block-end-style-001.html.ini": [
+       "a91edd5f560174b91a3c82ed0bae4a8cbde7f5a2",
+       []
+      ],
       "kind-of-widget-fallback-input-submit-border-block-end-width-001.html.ini": [
        "80ba57aa016a9f27b7807aa80b9144f82ec46e22",
        []
@@ -340912,6 +340948,10 @@
        "9fe4ab88dec37b929096bb2b0b759a6c724a688b",
        []
       ],
+      "kind-of-widget-fallback-input-submit-border-top-color-001.html.ini": [
+       "d56785ed04d7828ad7f54ca874ae3680abd97f27",
+       []
+      ],
       "kind-of-widget-fallback-input-text-border-block-start-width-001.html.ini": [
        "30611dc21c6a0bd019377edf69d584d42183318c",
        []
@@ -343717,6 +343757,10 @@
       "b09f938d23b91e9942425954a81ff46f5e101282",
       []
      ],
+     "new-content-with-overflow-zoomed.html.ini": [
+      "3689c97913742016cf52f0089a4628802e7e6be9",
+      []
+     ],
      "new-element-on-start-ref.html": [
       "b3db1f2e190106b85543d920b1a35c644b76ca4e",
       []
@@ -347342,7 +347386,7 @@
       []
      ],
      "scroll-behavior-main-frame-window.html.ini": [
-      "8ad2826dc3eb8dccd01c79692d00b3d8e4429c4a",
+      "b794e9563b1e86706d763badd3b0352d4e39a5a2",
       []
      ],
      "scroll-behavior-scrollintoview-nested.html.ini": [
@@ -357491,7 +357535,7 @@
      ]
     },
     "script-focus.https.html.ini": [
-     "aa4e5d0047f59f8e00015f3bbaa11e85f5a80c4d",
+     "663f4ab3b97c765cf03f1ef8c94d0759803e7735",
      []
     ]
    },
@@ -359762,7 +359806,7 @@
       []
      ],
      "fenced-frame.tentative.https.window.js.ini": [
-      "5541b59e2f19e5936dfbe120ab4665378243e885",
+      "ccd1c6dc4c5fa5d7e7e69b842bd3c964be702b40",
       []
      ],
      "fetch.tentative.https.window.js.ini": [
@@ -359960,7 +360004,7 @@
       []
      ],
      "shared-worker-blob-fetch.tentative.https.window.js.ini": [
-      "e0c171fb8a4405dea49677b7fac8c334e77b11c8",
+      "c63674bf03e0bc18dc4b09d0bf741ec5a702fa55",
       []
      ],
      "shared-worker-blob-fetch.tentative.window-expected.txt": [
@@ -361557,6 +361601,24 @@
       "780661ba1ca55c7ba73a8dabe0716c066b8cc7ca",
       []
      ],
+     "cjk": {
+      "LICENSE.txt": [
+       "d952d62c065f3f35fb83a173496e90b21525aef3",
+       []
+      ],
+      "NotoSansCJKjp-Regular-subset-chws.otf": [
+       "18859d5e2fe1200da5caef5f88d15864d0477963",
+       []
+      ],
+      "NotoSansCJKjp-Regular-subset-halt.otf": [
+       "773282263e6e0fe11c4b319ee156f403d824bc5e",
+       []
+      ],
+      "README.md": [
+       "8ff42d0f441ab9c9e0af92fc2f8b49d5c54089af",
+       []
+      ]
+     },
      "noto-sans-v8-latin-regular.woff": [
       "4f1dd100c0917b3ea6e0634d6c0fee5a191db63a",
       []
@@ -362861,7 +362923,7 @@
          []
         ],
         "rc-helper.js": [
-         "4458912013fb362386f6dd999123559c9d059f62",
+         "9ecdc91ff147ac785154ae2ab5991ea32f9dacb3",
          []
         ],
         "service-worker.js": [
@@ -368001,11 +368063,11 @@
        },
        "the-offscreen-canvas": {
         "offscreencanvas.getcontext.html.ini": [
-         "bc34b99eda473486ab6ee00f991f345564a1289e",
+         "e49d3e17246ad7e06d92ea4a3a97f451c78542f3",
          []
         ],
         "offscreencanvas.getcontext.worker.js.ini": [
-         "cc58ae8adcef8f39c33ea8ca108ff848573d919a",
+         "6af2eb8f2f5a393c19b0b3da25f9ed37ff472701",
          []
         ],
         "offscreencanvas.resize.html.ini": [
@@ -368013,15 +368075,15 @@
          []
         ],
         "offscreencanvas.transfer.to.imagebitmap.html.ini": [
-         "d0533c545e8644dca9e615cb14c03e6bd8b985c8",
+         "13dd7791894dc8afa54cd6b8e9c7effe3a8165d8",
          []
         ],
         "offscreencanvas.transfer.to.imagebitmap.w.html.ini": [
-         "6ce450a6a6ea6911228f76ba2cb20a086b7ed29f",
+         "4baa7edab967565eba6c920d4d84887e7174fc8f",
          []
         ],
         "offscreencanvas.transferrable.w.html.ini": [
-         "2d0f26215686089474d90daa37cd6154b1670cd2",
+         "fe3dde2bfac362dd63dcc88560c57ae87e3a7eb9",
          []
         ]
        }
@@ -377522,7 +377584,7 @@
         []
        ],
        "sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini": [
-        "f709ae8df274cf6aac6c43588053647e625796f2",
+        "7ddaa277c78d1e7def0405fc874bcda8a33fed13",
         []
        ],
        "sandbox-top-navigation-child.tentative.sub.window.js.ini": [
@@ -378294,7 +378356,7 @@
         []
        ],
        "urlencoded2.window.js.ini": [
-        "5b102b6ae3323473503f3af935bc3f4b5bdf6498",
+        "95abc4721b51f149b929e00c6b1fb2b71d84c064",
         []
        ]
       },
@@ -379505,7 +379567,7 @@
        []
       ],
       "popover-focus-2.html.ini": [
-       "842455dfc643d0da9375b6e16936cf958bc359d0",
+       "d14950bcda02488e9d20a06221dea056a07dda79",
        []
       ],
       "popover-focus.html.ini": [
@@ -379570,7 +379632,7 @@
         []
        ],
        "popover-utils.js": [
-        "bc7643c21ab46d30f61bf5ad5bbffb9b434377bf",
+        "f11291e5c2ff97ee03f0093d55fb33d3e18f8c99",
         []
        ]
       }
@@ -387282,7 +387344,7 @@
       []
      ],
      "largest-contentful-paint-helpers.js": [
-      "3ac3705e8e7ad2403715a0983445a567029dd044",
+      "52f7036466cca5d0c75d1966fe978db35f6237ad",
       []
      ],
      "lcp-sw-from-cache.js": [
@@ -387703,7 +387765,7 @@
        []
       ],
       "utils.js": [
-       "8781252e9411fcb3bf2423347e185e2633ef0140",
+       "574af6d6b8c716ba066f49014adabe4b6e1a537a",
        []
       ]
      }
@@ -392190,7 +392252,7 @@
     },
     "with-first-paint": {
      "first-contentful-canvas-webgl2.html.ini": [
-      "4028fe8f6e4be4da62257119eec11101568ef14e",
+      "7cd9f9aa6ac4b4649237d682086deb8caa834fb3",
       []
      ]
     }
@@ -392652,7 +392714,7 @@
       []
      ],
      "test-helper.js": [
-      "3c10e364093288382d8f181629ae30d0245f7513",
+      "a172546512a0f2f28c986c36cbb06d1ba333af3b",
       []
      ]
     },
@@ -397265,7 +397327,7 @@
      []
     ],
     "testharness.js": [
-     "d06123f8243871dff6a78c3d85fbc6f083df1ea2",
+     "497ae23f0e83ee2790291588ebe33c47b7bb6726",
      []
     ],
     "testharness.js.headers": [
@@ -397893,7 +397955,7 @@
      []
     ],
     "force-load-at-top.html.ini": [
-     "846700d514fe51daed6606b5b303bf5c6213f3a3",
+     "23f66a1717957cf50774f7c658c8b772dba9bf3b",
      []
     ],
     "force-load-at-top.js": [
@@ -408145,11 +408207,11 @@
      []
     ],
     "request-video-frame-callback-before-xr-session.https.html.ini": [
-     "1af1335a4ca33257187fa747eca17e36cb6a808f",
+     "26a1d4727a09bd1b658f5e1467ea20345e233137",
      []
     ],
     "request-video-frame-callback-during-xr-session.https.html.ini": [
-     "8affa31d75f5c6f737891fa10ad6c7c58e73a060",
+     "f5941ab0c1a465d44083f5463454f84d9b81338b",
      []
     ],
     "request-video-frame-callback-webrtc.https.html.ini": [
@@ -410935,7 +410997,7 @@
      []
     ],
     "full-cycle-test.https.any.js.ini": [
-     "2343a9db66c33f29b29cc0a920755a3fb4ce612c",
+     "50541b4972c2ec5336602061c0c1b44f676dd389",
      []
     ],
     "h264.annexb": [
@@ -411219,6 +411281,16 @@
          []
         ]
        },
+       "navigation_started": {
+        "__init__.py": [
+         "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+         []
+        ],
+        "navigation_started.py.ini": [
+         "cb12cf50b3f286d93bb1f227ffde7b1c2620f8ec",
+         []
+        ]
+       },
        "print": {
         "__init__.py": [
          "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
@@ -411514,7 +411586,7 @@
       },
       "script": {
        "__init__.py": [
-        "5635a4bbfb0f02450205d6abb997a692259d43ab",
+        "12dd64a718a4f2bbc0139176f208332a0e563f73",
         []
        ],
        "add_preload_script": {
@@ -411615,6 +411687,12 @@
          []
         ]
        },
+       "realm_created": {
+        "__init__.py": [
+         "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+         []
+        ]
+       },
        "realm_destroyed": {
         "__init__.py": [
          "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
@@ -418604,27 +418682,27 @@
       []
      ],
      "ar_anchor_freefloating_create_move.https.html.ini": [
-      "488fb7385d478aedc136c79a9ebbcdc68c0c43eb",
+      "c7e8abea6d053ace434039701a04738cf749c8cc",
       []
      ],
      "ar_anchor_freefloating_delay_creation.https.html.ini": [
-      "7c6d5c436c410cd5fcce661c81d4369b3eaaed9d",
+      "3551180d00474ab35fb36a55b8b2db5927ffd368",
       []
      ],
      "ar_anchor_freefloating_failure.https.html.ini": [
-      "bdc823ee77df8b7bdf96d220a281db0590f08038",
+      "b37def3e082a31488682f7fd27f9caa9f0314fb1",
       []
      ],
      "ar_anchor_freefloating_pause_resume_stop.https.html.ini": [
-      "a999adb610d8d215c37e7c5e4ea300f1a7f03a13",
+      "f53d912361b280fd2a359b2483417f260e9a9ea2",
       []
      ],
      "ar_anchor_getAnchors.https.html.ini": [
-      "be625d3959fa6496d1e020e658bf3544b359d019",
+      "a9e02b815e7eb2c31c36bda9c42c97cf0615a74f",
       []
      ],
      "ar_anchor_states.https.html.ini": [
-      "1609571b0f22e476f359b324863cc932f2094852",
+      "3cf1160f3ff08cb39a4e6cb91a7b80bcf4c1116e",
       []
      ],
      "idlharness.https.window-expected.txt": [
@@ -418642,44 +418720,44 @@
       []
      ],
      "xrDevice_requestSession_immersive-ar.https.html.ini": [
-      "064e84117430924d9c17a33e00296416d9a18715",
+      "5498ba0da63f3ec042f1068b51c57a56b500a19d",
       []
      ],
      "xrSession_environmentBlendMode.https.html.ini": [
-      "3d3343538c8c2f9e91e44524c3ce5fa49a83d6c0",
+      "9d3181029754e4a26f1f092568bb375a80bbbbd8",
       []
      ],
      "xrSession_interactionMode.https.html.ini": [
-      "7615a6a1274e66230b3c28b39823430dc555928a",
+      "ad282d0677b9665e50125af512caa06b1b5e0624",
       []
      ]
     },
     "camera-access": {
      "xrCamera_resolution.https.html.ini": [
-      "d29460f5e57a39eba936067ecec9ef3b3a3a66b2",
+      "9271f9f75569c1ce51bf93c0322d06a28beff468",
       []
      ]
     },
     "depth-sensing": {
      "cpu": {
       "depth_sensing_cpu_dataUnavailable.https.html.ini": [
-       "32eb9074426ef7b50aa25439648824bf0639a75e",
+       "476288ccde5bef926520dac6a23d7250c1e1fd44",
        []
       ],
       "depth_sensing_cpu_inactiveFrame.https.html.ini": [
-       "088d4ec4813876e3a1609bb10b871c313d8e9e63",
+       "1fab590327a2de9e457fe3628f74119b515e79d5",
        []
       ],
       "depth_sensing_cpu_incorrectUsage.https.html.ini": [
-       "5e9bef5d89be590f2faef8d19ece6325c45c9dd6",
+       "0d7411711d6896de577ee7218920a853f5d6b200",
        []
       ],
       "depth_sensing_cpu_luminance_alpha_dataValid.https.html.ini": [
-       "c31fe7649deb233ffab54ecdbbb773d9e82938f3",
+       "142a752447f18172a81c1fcfe5ad1e81814a2712",
        []
       ],
       "depth_sensing_cpu_staleView.https.html.ini": [
-       "5c3db41d2568b7516dade9e56c37ed6ec73c7b6a",
+       "55e053955fbe62a4176de6b9f0db471442266a4f",
        []
       ]
      },
@@ -418688,7 +418766,7 @@
       []
      ],
      "depth_sensing_notEnabled.https.html.ini": [
-      "df2c30c4e394e4ac2de0b77c811e93a477609826",
+      "e1ea241c378fba020327e999ef01c845afd5bd13",
       []
      ],
      "gpu": {
@@ -418724,48 +418802,48 @@
       []
      ],
      "ar_dom_overlay.https.html.ini": [
-      "24e599454261a1b98f24b935aa435943a62cc9b0",
+      "6c6918321ba407ef23c26d41ae7942c981bc7836",
       []
      ],
      "ar_dom_overlay_hit_test.https.html.ini": [
-      "dd711ce05c41b19e609c7e8e7dfb7d1e12ca2e6d",
+      "d111cedb83ebd3b875344c34df2b704ac66592fd",
       []
      ],
      "nested_fullscreen.https.html.ini": [
-      "f65f465704ff26aee08832954fdc55b602185ec5",
+      "5213f3280a8de11ef5b8f95357bfd92db34a9c0d",
       []
      ]
     },
     "events_input_source_recreation.https.html.ini": [
-     "ad4f4ba945f7701a4745fd7650d0fc9700820eb8",
+     "2c5a601f321065949dd8799b63f8b21e66a678d1",
      []
     ],
     "events_input_sources_change.https.html.ini": [
-     "ede519d5e708d8d3db5705374c283d198da7a304",
+     "6bee0f644b18107e1ae841eb90790beb7b89d9c2",
      []
     ],
     "events_referenceSpace_reset_immersive.https.html.ini": [
-     "0dc7b85e67f4281ab53702adadccb91d29192e25",
+     "c8bbcb0e64739f58502245ab77158c2d90923839",
      []
     ],
     "events_referenceSpace_reset_inline.https.html.ini": [
-     "abf9cd27c69c36a4465dd6e24533da4043d21670",
+     "702bd1968eeaa82f7d6b3c3ce6552ec35e54fcfd",
      []
     ],
     "events_session_select.https.html.ini": [
-     "7c9b1f5df7792c5de5a3a957c47618a26e9c7a68",
+     "0385b191adf9b1aa703af0418992e3f383bae5d5",
      []
     ],
     "events_session_select_subframe.https.html.ini": [
-     "9604fba8a417a4f2fb95aab7f07b851bdda35f12",
+     "cd41f2876f6986f33dec7651ca6125d788504225",
      []
     ],
     "events_session_squeeze.https.html.ini": [
-     "e5999c24870ca25ec1e018cc8d21c046b6af278c",
+     "781e094d283f7d48f92bc5fe9f9eb2d2522fe046",
      []
     ],
     "exclusive_requestFrame_nolayer.https.html.ini": [
-     "c5c698f4c9402f4d93bc45c3ebf4863d633c111c",
+     "8319060df9f36e23cdcde28efefd6fabfbed4a87",
      []
     ],
     "gamepads-module": {
@@ -418774,24 +418852,24 @@
       []
      ],
      "xrInputSource_gamepad_disconnect.https.html.ini": [
-      "6936c08a499c1048d0a1fdc0924fd902a8ae835d",
+      "b0ceaf63b1cbd8e266d5afab7abe9078fd6dd306",
       []
      ],
      "xrInputSource_gamepad_input_registered.https.html.ini": [
-      "9f0ff91a51f7a4111edbeea5bef16b11cebc43ac",
+      "a302af80e06b19ba0e0d708b11c5e7a9898b0717",
       []
      ]
     },
     "getInputPose_handedness.https.html.ini": [
-     "a1195fac5581e0009db5755e6bc57081ab808313",
+     "bcd50f7bb27b4b030c0d927586867c333bfd5879",
      []
     ],
     "getInputPose_pointer.https.html.ini": [
-     "91a596baac3ed84b6da0c2148542728af0e19bc9",
+     "292e22db9b9998d9dd696664dc7408af6bb4f167",
      []
     ],
     "getViewerPose_emulatedPosition.https.html.ini": [
-     "a8c404e66f38831be9ad36e66b0a7c17133fbf26",
+     "61bccdc90b9e46e993cb7f9057768e4febb62b89",
      []
     ],
     "hand-input": {
@@ -418806,31 +418884,31 @@
       []
      ],
      "ar_hittest_source_cancel.https.html.ini": [
-      "b60d168888a05a398f25108c87c6ce700c5e8053",
+      "6f9f8c1aa3166629794051c05015f7896771473b",
       []
      ],
      "ar_hittest_subscription_inputSources.https.html.ini": [
-      "b22f501bd209acc05235072505f58f18ae082a78",
+      "20aaa1037cc70929d18ae0104062067bd3bf3e27",
       []
      ],
      "ar_hittest_subscription_refSpaces.https.html.ini": [
-      "9dbe67d61f3b695987214b25402d03257bb3ebde",
+      "67ff0d044d7d43ecd9cc7c55326abaeeea18948c",
       []
      ],
      "ar_hittest_subscription_states_regular.https.html.ini": [
-      "d4af61d3f684c5e8a02988c302f4d059ddcb4848",
+      "2b451a021ac01fbed1eb52ee200a1dd0d8355e93",
       []
      ],
      "ar_hittest_subscription_states_transient.https.html.ini": [
-      "444feab021f0196bc8fb93d5d3dfacab3e259478",
+      "0e154a766ff1c770a80ba83a996db8ad6cef54d5",
       []
      ],
      "ar_hittest_subscription_transientInputSources.https.html.ini": [
-      "cfb29f5ca84c54dca1128cc0d7b2550fa6dc049d",
+      "a2c214ce2dcb0775a497f767cdedcc4ad24d5c89",
       []
      ],
      "ar_hittest_subscription_unlocalizable.https.html.ini": [
-      "e0cf12bb58e066066d62b95a9a1ed7a09e2b6aca",
+      "f08b3e7109f543459a7e8d303e444f25a3780e86",
       []
      ]
     },
@@ -418839,7 +418917,7 @@
      []
     ],
     "idlharness.https.window.js.ini": [
-     "a55bd8ad89b7238494574c34d900d0737f133397",
+     "58e35503078fd2aa75c7b0d241e2e6be3927b36b",
      []
     ],
     "layers": {
@@ -418848,58 +418926,58 @@
       []
      ],
      "xrSession_updateRenderState.https.html.ini": [
-      "88bb4d7914164472614db43bf974bfe4700e0a5e",
+      "b94d877da1add73f3db6b2940dac5bd5421f71d6",
       []
      ],
      "xrWebGLBinding_constructor.https.html.ini": [
-      "c957c47c66f97a1236151e8ecd94b8811399e26b",
+      "e55aad93a1015f10edfd5f31e273bea7cb582e48",
       []
      ]
     },
     "light-estimation": {
      "xrFrame_getLightEstimate_oldSession.https.html.ini": [
-      "c2ad2ba9af5f337bae952f5e369ad05f50349fde",
+      "1b057eb60d94749b53ba8ae916f2bf0e448e45b7",
       []
      ],
      "xrFrame_getLightEstimate_staleFrame.https.html.ini": [
-      "50016316974e51389b2d206c8f826fcd4ab173ee",
+      "d581b78d0f8866dba8be466489bd981a5060840f",
       []
      ],
      "xrFrame_getLightEstimate_valid.https.html.ini": [
-      "c4a9659a45299434e7068747d166e555a14bf21a",
+      "4216dd1b646be36c8219ecfb50c1ff04c4364dc9",
       []
      ],
      "xrSession_getLightProbe_ended.https.html.ini": [
-      "b8ef5bd55ae8232d670f492e40fbb8edf1d0da72",
+      "44484f703572efd3c7096e069ef3b572c0d91b77",
       []
      ],
      "xrSession_getLightProbe_notEnabled.https.html.ini": [
-      "16f8d164608883fd6ea269fdb44b9a16940a1641",
+      "185f5aaf6096a9b0b7b1096fe04784bdae4a56dd",
       []
      ],
      "xrSession_getLightProbe_valid.https.html.ini": [
-      "b308aa8e216751a3e7a8c0594f0bedc7cdc7e983",
+      "700f75152c9039e00fb2ddd17a04b0c957fbc399",
       []
      ],
      "xrWebGLBinding_getReflectionCubeMap.https.html.ini": [
-      "50bfedbded0c40eb903f1bc9ac81bddade3cdb02",
+      "fae907f9182ad56f5da95f65137a758de219f344",
       []
      ]
     },
     "navigator_xr_sameObject.https.html.ini": [
-     "303844883d1686d3a9f5c6d87edc05dc6aba5b00",
+     "6d8ba9d0292806afcc8f5442d825ca5e50a6d7de",
      []
     ],
     "render_state_update.https.html.ini": [
-     "1ac5bb4e43c8b0b514895ff5cb6c9b002300739a",
+     "7335b9e6813cc8e9e2ba2a4b0078ab2f4ae1dba7",
      []
     ],
     "render_state_vertical_fov_immersive.https.html.ini": [
-     "81cd5b64422afcecf830105e8f93723a91a6632e",
+     "631798cead803981b2a749edaa1ae175e3f17a9d",
      []
     ],
     "render_state_vertical_fov_inline.https.html.ini": [
-     "f12b7195255e7fcdfa5461525bdafb1d6d325af2",
+     "2bd342074694cfb78457c8799f3015c39d5ec45b",
      []
     ],
     "resources": {
@@ -418933,15 +419011,15 @@
      ]
     },
     "webGLCanvasContext_create_xrcompatible.https.html.ini": [
-     "f347e95ba4ef8601272f4fe2939b8b663c5f61bd",
+     "77254db6dd1b72e9ed684ead3c14c472c58ae77e",
      []
     ],
     "webGLCanvasContext_makecompatible_contextlost.https.html.ini": [
-     "029b42fe2c33541386d065a98e75a1beadcdc02b",
+     "999ebad20d82eb07502c64ee0c362a29844b1940",
      []
     ],
     "webGLCanvasContext_makecompatible_reentrant.https.html.ini": [
-     "900b45bb8830f410dc7bce6f49e3397ff22b82f8",
+     "0e3d96d4f1725c73bf4c029cf255a9aeb8804e4a",
      []
     ],
     "webxr_permissions_policy.https.html.headers": [
@@ -418949,215 +419027,215 @@
      []
     ],
     "webxr_permissions_policy.https.html.ini": [
-     "65f44353dbd63595da6c80c4f5227341636eaeaf",
+     "eec7b36d0e71b60f2044d1c0b8a4e8dc56242c12",
      []
     ],
     "xrBoundedReferenceSpace_updates.https.html.ini": [
-     "9db6588933a52abaf66a852ae659bda75abaccfe",
+     "da4b4c74a7195fc1f9cf4f045635455a455121e7",
      []
     ],
     "xrDevice_disconnect_ends.https.html.ini": [
-     "fc2dbabaa278046872c642e9d5d777c10ee81883",
+     "77e2fbfa07eb74c40e4667ccf1934b7da21f9a9f",
      []
     ],
     "xrDevice_requestSession_immersive.https.html.ini": [
-     "b64e56f2897d9e45a633a514bd138655c05fff7a",
+     "838c13a408ff6edf1df531c8654a8d047a7b4a31",
      []
     ],
     "xrDevice_requestSession_optionalFeatures.https.html.ini": [
-     "5648c0a47d83aaa062724f57caa5e921f5d21ef1",
+     "768f6f64a10cad32b94604f9e9255de8da956e3f",
      []
     ],
     "xrFrame_getPose.https.html.ini": [
-     "9070199c7df1cfbb4df92a7bdc79a071aa8a8149",
+     "9a556176adb3aac02ab88e299e6c15434bcfb11d",
      []
     ],
     "xrFrame_getViewerPose_getPose.https.html.ini": [
-     "54ae2a29c1ef256e2dc3ea86580dbb5a2e35f9bf",
+     "cf749793d674009ab116408d9925b10f63444d08",
      []
     ],
     "xrFrame_getViewerPose_getPose_identities.https.html.ini": [
-     "375c7c9186f78acf6637807f89da7da74c2b7bc7",
+     "3f8dcf88276c59c612d5f765200a30e71caedee5",
      []
     ],
     "xrFrame_lifetime.https.html.ini": [
-     "ccb30f87bfc88f25bf36cc94ab12cfd81109b8e7",
+     "5220baf6bd4ec73793dabd293d54793f2cd33181",
      []
     ],
     "xrFrame_session_sameObject.https.html.ini": [
-     "95f42826c7f9cbc1b51717f1812cc807d59ea441",
+     "cfbd9ebb308ef927035f8e0e99062d3a9e9a289a",
      []
     ],
     "xrInputSource_add_remove.https.html.ini": [
-     "7302871186345b710fe69ff144027eb123f17c25",
+     "e371762806533fd963ac8ca6ef1f21b9e8326dda",
      []
     ],
     "xrInputSource_emulatedPosition.https.html.ini": [
-     "78f8a38b0c06aff99ef81306ce57b98e2fb6b57e",
+     "513c621d396bd523b41b6faace3c98c33922727e",
      []
     ],
     "xrInputSource_getPose_targetRay_grip.https.html.ini": [
-     "bc6eec8bca516303c68fad27f7743081ec63f654",
+     "a224c9d9d1b7eaab73f6ae2fe8630f080d404045",
      []
     ],
     "xrInputSource_profiles.https.html.ini": [
-     "e724f5648a2577aa4105a8639e7a388213cb3063",
+     "14377f9563e8749bb873785f14eafecbbc5a34bc",
      []
     ],
     "xrInputSource_sameObject.https.html.ini": [
-     "507870a543a7c881d2ad11180d70bb9a08e9f753",
+     "48db13ccd29a75a37e7d555741ceb7c225ac69a1",
      []
     ],
     "xrPose_transform_sameObject.https.html.ini": [
-     "a8ffd66721645e274bbc57fb1e6dc2a78c336d0b",
+     "d6e84debd56c61954cceac9f1fb16b5f38867518",
      []
     ],
     "xrReferenceSpace_originOffset.https.html.ini": [
-     "9507cd5ad89dd04eaa8334db23f7b1b6d8e9a4d8",
+     "c9095502b8ac3d54101e75cbdf789fc0b2c470b2",
      []
     ],
     "xrReferenceSpace_originOffsetBounded.https.html.ini": [
-     "6477b9e9f4aeb67e2c52aac250e7ce42f1796de0",
+     "5c8b17524dd32fb81e76673ce67c5358284091cd",
      []
     ],
     "xrReferenceSpace_originOffset_viewer.https.html.ini": [
-     "b7d5791641af63861cfd0cee65229b098d5f6c76",
+     "0655b71ea846e48aa55ab46c6317d04dbeb910f2",
      []
     ],
     "xrReferenceSpace_relationships.https.html.ini": [
-     "0eb7585722ebfbe9864f92d0c54818c4a65ebfc4",
+     "23bd6a8f3a41f5fc8e76e41c7474cec066e48a3d",
      []
     ],
     "xrRigidTransform_constructor.https.html.ini": [
-     "acc1b9928dd4ff5011c03472ad20197772cb0515",
+     "66fef7e77b22e1602d6ab9c1ceaf40917d165b58",
      []
     ],
     "xrRigidTransform_inverse.https.html.ini": [
-     "a1e73af9de7d947981fc4117fe3f5b49d6bf00cc",
+     "62f82b5cd8c903b0eed183479d43e02a8b13d421",
      []
     ],
     "xrRigidTransform_sameObject.https.html.ini": [
-     "2a26b319ad0c1215d15caa00e1dfd247491cfc64",
+     "2074a2456be12f8af7ecf8dd736e8bda8039a43c",
      []
     ],
     "xrSession_cancelAnimationFrame.https.html.ini": [
-     "376c78fb6844db7b252302970c5c1670c55cc4df",
+     "22b6764d6349e148fd6f9051f04bdae270139517",
      []
     ],
     "xrSession_cancelAnimationFrame_invalidhandle.https.html.ini": [
-     "0f793a1fc02e92566d82071dc34069b55b0b18a0",
+     "57ad315308d322986b567dc4a442d5d1ba2dbbc5",
      []
     ],
     "xrSession_enabledFeatures.https.html.ini": [
-     "f27edb3f799298fa2438101bf7c6712daa94a7a3",
+     "7b77e9300c2de7ec6339f741da76a6c55a80c051",
      []
     ],
     "xrSession_end.https.html.ini": [
-     "fba913c1e3bc5859dac48c974195e265a11554ea",
+     "d5546036a9f527c1f4eb54cd336afeafbbe4cf48",
      []
     ],
     "xrSession_input_events_end.https.html.ini": [
-     "af0c3b9c884c8beda1d7c40538c8c350759d00fd",
+     "47dbdae6b7cd81e852925a3e46951eb337337c2a",
      []
     ],
     "xrSession_requestAnimationFrame_callback_calls.https.html.ini": [
-     "fe514f5dd21086fd19d17f7ae73d365351233df9",
+     "7811d411da7215f03f589979735d6d613b580bdf",
      []
     ],
     "xrSession_requestAnimationFrame_data_valid.https.html.ini": [
-     "a59fbfd511aac8c7adf66a614873a636eb44afe8",
+     "2dc844f4675a4aa9a5fdcc418948483fe1d4bf71",
      []
     ],
     "xrSession_requestAnimationFrame_getViewerPose.https.html.ini": [
-     "3bbcc4158632aba175f41bd50eee23d1fb3b10ba",
+     "465544ef51f5a9c2e3459073c8606a1a6bffc3b7",
      []
     ],
     "xrSession_requestAnimationFrame_timestamp.https.html.ini": [
-     "786c841a22a940bac71a1d4c6edffc9846369400",
+     "d871fc6f15718c0a1b9766d6ff1520eee48f01bf",
      []
     ],
     "xrSession_requestReferenceSpace.https.html.ini": [
-     "4705cc6572d9d9faf93a72c8a21a3b17bb67785b",
+     "1a0435c60218e5fcbda92181005d46ad84de59cf",
      []
     ],
     "xrSession_requestReferenceSpace_features.https.html.ini": [
-     "9751f3d84a23bf2225d7467053fb335b0a0ab6df",
+     "61c83c11a1f556cb36b2ae1db6ebec4e227c8331",
      []
     ],
     "xrSession_requestSessionDuringEnd.https.html.ini": [
-     "a8d4058546a02d047f3bd65a8032eb96962a6e29",
+     "dd14d683cb7de8a467c50bcb409ad34d5b283013",
      []
     ],
     "xrSession_sameObject.https.html.ini": [
-     "808a21f2f14e001e9407078beabbd75d850c7db8",
+     "d58ebdb651c818604bb2e196de977f3d96976b02",
      []
     ],
     "xrSession_viewer_referenceSpace.https.html.ini": [
-     "104789b2efa5000709bc8c44334514d3548a0efe",
+     "127e15b5630f0d5e639fbeabf0a84fed1829dbdd",
      []
     ],
     "xrSession_visibilityState.https.html.ini": [
-     "22160e17583170c80cf3dbaf39f9c3ca0faaf49e",
+     "31db7db04e634de0400bff8af8cb347694379a66",
      []
     ],
     "xrStationaryReferenceSpace_floorlevel_updates.https.html.ini": [
-     "29681fe09ee7738b8de92aca63e0de595167c8fb",
+     "99e3b359723c5cd9854eae8455b43026e2f8f0c6",
      []
     ],
     "xrView_eyes.https.html.ini": [
-     "0c60b77dd83022b4cefbfc18e438c0aa9bbcef94",
+     "b5a197d26e214a15e7d425456feef879f9dc2716",
      []
     ],
     "xrView_match.https.html.ini": [
-     "c3baeb69a88c4458b036d9a34a3d3aff211325d9",
+     "0505f42c32ccdc9ce60d9091dc4124a0a39b9835",
      []
     ],
     "xrView_oneframeupdate.https.html.ini": [
-     "ba20722d84f8532d9825b05dfbc9d77a7b3e9408",
+     "3b79c591e1df005d994ddef76886e5b0da5e96b5",
      []
     ],
     "xrView_sameObject.https.html.ini": [
-     "069955fbff2b8d1bcf0c9c607e67ad6111af2b45",
+     "40ab9df895b78153da2d48282f5340759dc9d4c6",
      []
     ],
     "xrViewerPose_secondaryViews.https.html.ini": [
-     "7b2beeb21d6964eda65b3f59e3e6371c2e98a856",
+     "3f1d1eb429a2020930762b017b5dd3b186eb7eb5",
      []
     ],
     "xrViewerPose_views_sameObject.https.html.ini": [
-     "c72689e6141e0ada7a84f49420c728440d41da53",
+     "2aa564343315af6609db0c7ebc496feaffd8253b",
      []
     ],
     "xrViewport_valid.https.html.ini": [
-     "4022805aa5c7e0fa8a1b64dda439333131e1312d",
+     "66cccc7db5c028340df577f14067a7f43c4be21c",
      []
     ],
     "xrWebGLLayer_constructor.https.html.ini": [
-     "52f9a21a13b84801e4d432276767df0547e311f3",
+     "7c660ed19d7fdeb59e040c8c3efbf6a2eb39daac",
      []
     ],
     "xrWebGLLayer_framebuffer_draw.https.html.ini": [
-     "bee5ddc033e07136df57ead2df18bc400ff39c91",
+     "4d478f844a7f6101f0678ccd22e101e5823b4303",
      []
     ],
     "xrWebGLLayer_framebuffer_sameObject.https.html.ini": [
-     "827b02adef00526986ae0f8d61a71a1d42e18863",
+     "5a980883291d4f9a8f4cb579cffd63074fc116af",
      []
     ],
     "xrWebGLLayer_framebuffer_scale.https.html.ini": [
-     "d92e419e61d80dd4be175e6c43ec538707f00990",
+     "4d27b9b36c7edbf8ca7eabb110b35888b88cbae9",
      []
     ],
     "xrWebGLLayer_opaque_framebuffer.https.html.ini": [
-     "308b903ce758f1f8a3b399cad3897099e98908b5",
+     "f6639afa7049ee673a7662030efa83dbfad69702",
      []
     ],
     "xrWebGLLayer_opaque_framebuffer_stencil.https.html.ini": [
-     "61d6a446e72ea72c0a0cff56587c005fcbcdbfe0",
+     "5d848bdfb8da6586f31e427daa2a6b341e65a1f6",
      []
     ],
     "xrWebGLLayer_viewports.https.html.ini": [
-     "865f306775a11cf1b390358e8d52dfb2bf9eb461",
+     "0e1f454c893337f053d050dd0e7181708150804d",
      []
     ],
     "xr_viewport_scale.https-expected.txt": [
@@ -419165,7 +419243,7 @@
      []
     ],
     "xr_viewport_scale.https.html.ini": [
-     "cb84b0ee5dc745e9429cafd9d00828a799895ee9",
+     "e0a0aa019bba8d491c1eb41a6d8ae8e8ef802f55",
      []
     ]
    },
@@ -460733,7 +460811,7 @@
       ]
      ],
      "all-prop-revert-layer.html": [
-      "fa29b5106a7bab8bb8f7f5ce5ccc864fbeda312d",
+      "420a3a61cacdcf3743e612302dfa82fdbb775145",
       [
        null,
        {}
@@ -472096,7 +472174,7 @@
        ]
       ],
       "clip-path-valid.html": [
-       "2fb0c6248a227de445d3b55292dc28fd8dbf8539",
+       "84555fd2d1656563da477db2a33c0e210120e44d",
        [
         null,
         {}
@@ -585197,7 +585275,7 @@
          ]
         ],
         "referrer-policy-for-descendants.sub.html": [
-         "cf8a3dce014efb4349d2f3bfcf49ae48b9ac78e8",
+         "4a7005da840b42fe4ffb57a6a173d6dbb49304ca",
          [
           null,
           {}
@@ -596705,7 +596783,7 @@
       ]
      ],
      "loaf-desired-exec-time.html": [
-      "dd350078b6024d41e25e663acbfa6a2b03aea789",
+      "656c58d0c24c7738e9dc3c7fcdfb5c05d2a69506",
       [
        null,
        {
@@ -596724,7 +596802,7 @@
       ]
      ],
      "loaf-first-ui-event.html": [
-      "47a3a51de215e47add78b96047d431b13eb89257",
+      "857ccd0a182ef0f061f9acff3ee42a12e47d89d2",
       [
        null,
        {
@@ -661559,7 +661637,7 @@
        ]
       ],
       "setTargetAtTime-after-event-within-block.html": [
-       "0e6863986ab676e1a6394e83ff4e611c2b028089",
+       "ca02b0db975de7bd80b4b5cd701acdd7e512e0de",
        [
         null,
         {}
@@ -708742,6 +708820,15 @@
          ]
         ]
        },
+       "navigation_started": {
+        "navigation_started.py": [
+         "34f3a6246c8e84d631d111e89f61a446431aa327",
+         [
+          null,
+          {}
+         ]
+        ]
+       },
        "print": {
         "background.py": [
          "5f1f518928a995326b540945118074959a7828ef",
@@ -709522,9 +709609,18 @@
          ]
         ]
        },
+       "realm_created": {
+        "realm_created.py": [
+         "2a86adecb18b7cffff8686f1aac2aae6b4b9e65d",
+         [
+          null,
+          {}
+         ]
+        ]
+       },
        "realm_destroyed": {
         "realm_destroyed.py": [
-         "2253b7128dd3b21f3d87d7074ddc86694e4abbfd",
+         "e3f4dc0af01106f4835098a65fb2bce50dcd7cd3",
          [
           null,
           {}
diff --git a/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-with-transform-and-perspective.html.ini b/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-with-transform-and-perspective.html.ini
index 7fb2a4ba..3aa42fb 100644
--- a/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-with-transform-and-perspective.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-with-transform-and-perspective.html.ini
@@ -1,3 +1,4 @@
 [mix-blend-mode-blended-with-transform-and-perspective.html]
   expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
     if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-repeat/background-repeat-repeat-x.xht.ini b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-repeat/background-repeat-repeat-x.xht.ini
new file mode 100644
index 0000000..de91251
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-repeat/background-repeat-repeat-x.xht.ini
@@ -0,0 +1,3 @@
+[background-repeat-repeat-x.xht]
+  expected:
+    if (product == "content_shell") and (virtual_suite == "threaded") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-size/background-size-cover.xht.ini b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-size/background-size-cover.xht.ini
index 69a24b2cf..a20dce14 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-size/background-size-cover.xht.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-size/background-size-cover.xht.ini
@@ -1,3 +1,4 @@
 [background-size-cover.xht]
   expected:
     if (product == "content_shell") and (virtual_suite == "threaded") and (os == "mac") and (port == "mac11-arm64"): FAIL
+    if (product == "content_shell") and (virtual_suite == "threaded") and (os == "mac") and (port == "mac11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-order-float-in-inline-crash.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-order-float-in-inline-crash.html
new file mode 100644
index 0000000..0a348cf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-order-float-in-inline-crash.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1486411">
+<div style="columns:2; column-fill:auto; height:100px; orphans:1; widows:1;">
+  <br>
+  <span>
+    <div style="float:left; break-inside:avoid; width:100%; height:200px;"></div>
+    x
+  </span>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer-expected.txt
new file mode 100644
index 0000000..34fe75f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer-expected.txt
@@ -0,0 +1,332 @@
+This is a testharness.js-based test.
+Found 328 tests; 327 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS accent-color
+PASS align-content
+PASS align-items
+PASS align-self
+PASS alignment-baseline
+PASS animation-composition
+PASS animation-delay
+PASS animation-direction
+PASS animation-duration
+PASS animation-fill-mode
+PASS animation-iteration-count
+PASS animation-name
+PASS animation-play-state
+PASS animation-range-end
+PASS animation-range-start
+PASS animation-timeline
+PASS animation-timing-function
+PASS app-region
+PASS appearance
+PASS backdrop-filter
+PASS backface-visibility
+PASS background-attachment
+PASS background-blend-mode
+PASS background-clip
+PASS background-color
+PASS background-image
+PASS background-origin
+PASS background-position
+PASS background-repeat
+PASS background-size
+PASS baseline-shift
+FAIL baseline-source assert_equals: Layer 3 should rollback to layer 2. expected "first" but got "auto"
+PASS block-size
+PASS border-block-end-color
+PASS border-block-end-style
+PASS border-block-end-width
+PASS border-block-start-color
+PASS border-block-start-style
+PASS border-block-start-width
+PASS border-bottom-color
+PASS border-bottom-left-radius
+PASS border-bottom-right-radius
+PASS border-bottom-style
+PASS border-bottom-width
+PASS border-collapse
+PASS border-end-end-radius
+PASS border-end-start-radius
+PASS border-image-outset
+PASS border-image-repeat
+PASS border-image-slice
+PASS border-image-source
+PASS border-image-width
+PASS border-inline-end-color
+PASS border-inline-end-style
+PASS border-inline-end-width
+PASS border-inline-start-color
+PASS border-inline-start-style
+PASS border-inline-start-width
+PASS border-left-color
+PASS border-left-style
+PASS border-left-width
+PASS border-right-color
+PASS border-right-style
+PASS border-right-width
+PASS border-start-end-radius
+PASS border-start-start-radius
+PASS border-top-color
+PASS border-top-left-radius
+PASS border-top-right-radius
+PASS border-top-style
+PASS border-top-width
+PASS bottom
+PASS box-shadow
+PASS box-sizing
+PASS break-after
+PASS break-before
+PASS break-inside
+PASS buffered-rendering
+PASS caption-side
+PASS caret-color
+PASS clear
+PASS clip
+PASS clip-path
+PASS clip-rule
+PASS color
+PASS color-interpolation
+PASS color-interpolation-filters
+PASS color-rendering
+PASS column-count
+PASS column-gap
+PASS column-rule-color
+PASS column-rule-style
+PASS column-rule-width
+PASS column-span
+PASS column-width
+PASS contain-intrinsic-block-size
+PASS contain-intrinsic-height
+PASS contain-intrinsic-inline-size
+PASS contain-intrinsic-size
+PASS contain-intrinsic-width
+PASS container-name
+PASS container-type
+PASS content
+PASS cursor
+PASS cx
+PASS cy
+PASS d
+PASS direction
+PASS display
+PASS dominant-baseline
+PASS empty-cells
+PASS fill
+PASS fill-opacity
+PASS fill-rule
+PASS filter
+PASS flex-basis
+PASS flex-direction
+PASS flex-grow
+PASS flex-shrink
+PASS flex-wrap
+PASS float
+PASS flood-color
+PASS flood-opacity
+PASS font-family
+PASS font-kerning
+PASS font-optical-sizing
+PASS font-palette
+PASS font-size
+PASS font-size-adjust
+PASS font-stretch
+PASS font-style
+PASS font-synthesis-small-caps
+PASS font-synthesis-style
+PASS font-synthesis-weight
+PASS font-variant
+PASS font-variant-alternates
+PASS font-variant-caps
+PASS font-variant-east-asian
+PASS font-variant-ligatures
+PASS font-variant-numeric
+PASS font-variant-position
+PASS font-weight
+PASS grid-auto-columns
+PASS grid-auto-flow
+PASS grid-auto-rows
+PASS grid-column-end
+PASS grid-column-start
+PASS grid-row-end
+PASS grid-row-start
+PASS grid-template-areas
+PASS grid-template-columns
+PASS grid-template-rows
+PASS height
+PASS hyphenate-character
+PASS hyphenate-limit-chars
+PASS hyphens
+PASS image-orientation
+PASS image-rendering
+PASS initial-letter
+PASS inline-size
+PASS inset-block-end
+PASS inset-block-start
+PASS inset-inline-end
+PASS inset-inline-start
+PASS isolation
+PASS justify-content
+PASS justify-items
+PASS justify-self
+PASS left
+PASS letter-spacing
+PASS lighting-color
+PASS line-break
+PASS line-height
+PASS list-style-image
+PASS list-style-position
+PASS list-style-type
+PASS margin-block-end
+PASS margin-block-start
+PASS margin-bottom
+PASS margin-inline-end
+PASS margin-inline-start
+PASS margin-left
+PASS margin-right
+PASS margin-top
+PASS marker-end
+PASS marker-mid
+PASS marker-start
+PASS mask-type
+PASS math-depth
+PASS math-shift
+PASS math-style
+PASS max-block-size
+PASS max-height
+PASS max-inline-size
+PASS max-width
+PASS min-block-size
+PASS min-height
+PASS min-inline-size
+PASS min-width
+PASS mix-blend-mode
+PASS object-fit
+PASS object-position
+PASS object-view-box
+PASS offset-anchor
+PASS offset-distance
+PASS offset-path
+PASS offset-position
+PASS offset-rotate
+PASS opacity
+PASS order
+PASS orphans
+PASS outline-color
+PASS outline-offset
+PASS outline-style
+PASS outline-width
+PASS overflow-anchor
+PASS overflow-block
+PASS overflow-clip-margin
+PASS overflow-inline
+PASS overflow-wrap
+PASS overflow-x
+PASS overflow-y
+PASS overscroll-behavior-block
+PASS overscroll-behavior-inline
+PASS padding-block-end
+PASS padding-block-start
+PASS padding-bottom
+PASS padding-inline-end
+PASS padding-inline-start
+PASS padding-left
+PASS padding-right
+PASS padding-top
+PASS paint-order
+PASS perspective
+PASS perspective-origin
+PASS pointer-events
+PASS position
+PASS r
+PASS resize
+PASS right
+PASS rotate
+PASS row-gap
+PASS ruby-position
+PASS rx
+PASS ry
+PASS scale
+PASS scroll-behavior
+PASS scroll-margin-block-end
+PASS scroll-margin-block-start
+PASS scroll-margin-inline-end
+PASS scroll-margin-inline-start
+PASS scroll-padding-block-end
+PASS scroll-padding-block-start
+PASS scroll-padding-inline-end
+PASS scroll-padding-inline-start
+PASS scroll-timeline-axis
+PASS scroll-timeline-name
+PASS scrollbar-color
+PASS scrollbar-gutter
+PASS scrollbar-width
+PASS shape-image-threshold
+PASS shape-margin
+PASS shape-outside
+PASS shape-rendering
+PASS speak
+PASS stop-color
+PASS stop-opacity
+PASS stroke
+PASS stroke-dasharray
+PASS stroke-dashoffset
+PASS stroke-linecap
+PASS stroke-linejoin
+PASS stroke-miterlimit
+PASS stroke-opacity
+PASS stroke-width
+PASS tab-size
+PASS table-layout
+PASS text-align
+PASS text-align-last
+PASS text-anchor
+PASS text-decoration
+PASS text-decoration-color
+PASS text-decoration-line
+PASS text-decoration-skip-ink
+PASS text-decoration-style
+PASS text-emphasis-color
+PASS text-emphasis-position
+PASS text-emphasis-style
+PASS text-indent
+PASS text-overflow
+PASS text-rendering
+PASS text-shadow
+PASS text-size-adjust
+PASS text-transform
+PASS text-underline-position
+PASS text-wrap
+PASS timeline-scope
+PASS top
+PASS touch-action
+PASS transform
+PASS transform-origin
+PASS transform-style
+PASS transition-behavior
+PASS transition-delay
+PASS transition-duration
+PASS transition-property
+PASS transition-timing-function
+PASS translate
+PASS unicode-bidi
+PASS user-select
+PASS vector-effect
+PASS vertical-align
+PASS view-timeline-axis
+PASS view-timeline-inset
+PASS view-timeline-name
+PASS view-transition-name
+PASS visibility
+PASS white-space-collapse
+PASS widows
+PASS width
+PASS will-change
+PASS word-break
+PASS word-spacing
+PASS writing-mode
+PASS x
+PASS y
+PASS z-index
+PASS zoom
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer.html
index fa29b51..420a3a6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer.html
@@ -24,6 +24,7 @@
   animation-iteration-count: 123;
   animation-name: \.;
   animation-play-state: paused;
+  animation-range: 10% 20%;
   animation-timeline: none;
   animation-timing-function: linear;
   app-region: drag;
@@ -41,6 +42,7 @@
   background-repeat: round;
   background-size: 123px;
   baseline-shift: 123px;
+  baseline-source: first;
   block-size: 123px;
   border-block-end: 123px dashed #123;
   border-block-start: 123px dashed #123;
@@ -96,6 +98,7 @@
   container-name: foo;
   container-type: size;
   content: "b";
+  content-visibility: auto;
   counter-increment: add 123;
   counter-reset: add 123;
   counter-set: add 123;
@@ -133,11 +136,13 @@
   font-variant-alternates: historical-forms;
   font-variant-caps: small-caps;
   font-variant-east-asian: full-width;
+  font-variant-emoji: emoji;
   font-variant-ligatures: none;
   font-variant-numeric: tabular-nums;
   font-variant-position: super;
   font-variation-settings: "smcp" 1;
   font-weight: 123;
+  forced-color-adjust: none;
   glyph-orientation-horizontal: 123deg;
   glyph-orientation-vertical: 123deg;
   grid-auto-columns: 123px;
@@ -153,6 +158,7 @@
   hanging-punctuation: first;
   height: 123px;
   hyphenate-character: "e";
+  hyphenate-limit-chars: 5;
   hyphens: auto;
   image-orientation: none;
   image-rendering: pixelated;
@@ -187,6 +193,7 @@
   margin-left: 123px;
   margin-right: 123px;
   margin-top: 123px;
+  margin-trim: block;
   marker-end: url("#ref");
   marker-mid: url("#ref");
   marker-start: url("#ref");
@@ -248,6 +255,7 @@
   padding-left: 123px;
   padding-right: 123px;
   padding-top: 123px;
+  page: page;
   paint-order: fill;
   perspective: 123px;
   perspective-origin: 123px 123%;
@@ -285,6 +293,7 @@
   scroll-snap-align: center;
   scroll-snap-stop: always;
   scroll-snap-type: both;
+  scroll-timeline: --foo inline;
   scrollbar-color: #123 #123;
   scrollbar-gutter: stable;
   scrollbar-width: none;
@@ -329,13 +338,14 @@
   text-transform: lowercase;
   text-underline-offset: 123px;
   text-underline-position: under;
-  text-wrap: nowrap;
+  timeline-scope: --foo;
   top: 123px;
   touch-action: none;
   transform: scale(-1);
   transform-box: fill-box;
   transform-origin: 123px 123px 123px;
   transform-style: preserve-3d;
+  transition-behavior: allow-discrete;
   transition-delay: 123s;
   transition-duration: 123s;
   transition-property: add;
@@ -345,8 +355,10 @@
   user-select: all;
   vector-effect: non-scaling-stroke;
   vertical-align: 123px;
+  view-timeline: --foo inline 10px;
+  view-transition-name: --foo;
   visibility: collapse;
-  white-space-collapse: preserve;
+  white-space: pre;
   white-space-trim: discard-inner;
   widows: 123;
   width: 123px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer.html.ini b/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer.html.ini
new file mode 100644
index 0000000..d958bfb7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/all-prop-revert-layer.html.ini
@@ -0,0 +1,5 @@
+[all-prop-revert-layer.html]
+  [baseline-source]
+    expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): PASS
+      FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-rotated-will-change-transform.html.ini b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-rotated-will-change-transform.html.ini
index 1dc7d22..bc26a958 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-rotated-will-change-transform.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-rotated-will-change-transform.html.ini
@@ -1,3 +1,4 @@
 [clip-path-rotated-will-change-transform.html]
   expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/idlharness-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-masking/idlharness-expected.txt
deleted file mode 100644
index b92a9821..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-masking/idlharness-expected.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS idl_test validation
-PASS SVGElement includes GlobalEventHandlers: member names are unique
-PASS SVGElement includes SVGElementInstance: member names are unique
-PASS SVGElement includes HTMLOrSVGElement: member names are unique
-PASS Element includes ParentNode: member names are unique
-PASS Element includes NonDocumentTypeChildNode: member names are unique
-PASS Element includes ChildNode: member names are unique
-PASS Element includes Slottable: member names are unique
-FAIL SVGClipPathElement interface: existence and properties of interface object assert_equals: prototype of SVGClipPathElement is not SVGElement expected function "function SVGElement() { [native code] }" but got function "function SVGGraphicsElement() { [native code] }"
-PASS SVGClipPathElement interface object length
-PASS SVGClipPathElement interface object name
-FAIL SVGClipPathElement interface: existence and properties of interface prototype object assert_equals: prototype of SVGClipPathElement.prototype is not SVGElement.prototype expected object "[object SVGElement]" but got object "[object SVGGraphicsElement]"
-PASS SVGClipPathElement interface: existence and properties of interface prototype object's "constructor" property
-PASS SVGClipPathElement interface: existence and properties of interface prototype object's @@unscopables property
-PASS SVGClipPathElement interface: attribute clipPathUnits
-FAIL SVGClipPathElement interface: attribute transform assert_own_property: expected property "transform" missing
-PASS SVGClipPathElement must be primary interface of [object SVGClipPathElement]
-PASS Stringification of [object SVGClipPathElement]
-PASS SVGClipPathElement interface: [object SVGClipPathElement] must inherit property "clipPathUnits" with the proper type
-PASS SVGClipPathElement interface: [object SVGClipPathElement] must inherit property "transform" with the proper type
-PASS SVGMaskElement interface: existence and properties of interface object
-PASS SVGMaskElement interface object length
-PASS SVGMaskElement interface object name
-PASS SVGMaskElement interface: existence and properties of interface prototype object
-PASS SVGMaskElement interface: existence and properties of interface prototype object's "constructor" property
-PASS SVGMaskElement interface: existence and properties of interface prototype object's @@unscopables property
-PASS SVGMaskElement interface: attribute maskUnits
-PASS SVGMaskElement interface: attribute maskContentUnits
-PASS SVGMaskElement interface: attribute x
-PASS SVGMaskElement interface: attribute y
-PASS SVGMaskElement interface: attribute width
-PASS SVGMaskElement interface: attribute height
-PASS SVGMaskElement must be primary interface of [object SVGMaskElement]
-PASS Stringification of [object SVGMaskElement]
-PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "maskUnits" with the proper type
-PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "maskContentUnits" with the proper type
-PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "x" with the proper type
-PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "y" with the proper type
-PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "width" with the proper type
-PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "height" with the proper type
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid-expected.txt
new file mode 100644
index 0000000..4d4d15e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid-expected.txt
@@ -0,0 +1,52 @@
+This is a testharness.js-based test.
+PASS e.style['clip-path'] = "none" should set the property value
+PASS e.style['clip-path'] = "inset(100%)" should set the property value
+PASS e.style['clip-path'] = "inset(0 1px)" should set the property value
+PASS e.style['clip-path'] = "inset(0px 1px 2%)" should set the property value
+PASS e.style['clip-path'] = "inset(0px 1px 2% 3em)" should set the property value
+PASS e.style['clip-path'] = "inset(0px round 100%)" should set the property value
+PASS e.style['clip-path'] = "inset(0px round 0 1px)" should set the property value
+PASS e.style['clip-path'] = "inset(0px round 0px 1px 2%)" should set the property value
+PASS e.style['clip-path'] = "inset(0px round 0px 1px 2% 3em)" should set the property value
+PASS e.style['clip-path'] = "inset(10px round 20% / 0px 1px 2% 3em)" should set the property value
+PASS e.style['clip-path'] = "circle()" should set the property value
+PASS e.style['clip-path'] = "circle(1px)" should set the property value
+PASS e.style['clip-path'] = "circle(closest-side)" should set the property value
+PASS e.style['clip-path'] = "circle(at 10% 20%)" should set the property value
+PASS e.style['clip-path'] = "circle(farthest-side at center top)" should set the property value
+PASS e.style['clip-path'] = "circle(4% at top right)" should set the property value
+PASS e.style['clip-path'] = "ellipse()" should set the property value
+PASS e.style['clip-path'] = "ellipse(1px closest-side)" should set the property value
+PASS e.style['clip-path'] = "ellipse(at 10% 20%)" should set the property value
+PASS e.style['clip-path'] = "ellipse(closest-side closest-side at 10% 20%)" should set the property value
+PASS e.style['clip-path'] = "ellipse(farthest-side 4% at bottom left)" should set the property value
+PASS e.style['clip-path'] = "polygon(1% 2%)" should set the property value
+PASS e.style['clip-path'] = "polygon(nonzero, 1px 2px, 3em 4em)" should set the property value
+PASS e.style['clip-path'] = "polygon(evenodd, 1px 2px, 3em 4em, 5pt 6%)" should set the property value
+PASS e.style['clip-path'] = "path(\"m 20 0 h -100\")" should set the property value
+PASS e.style['clip-path'] = "path(evenodd, \"M 20 20 h 60 v 60 h -60 Z M 30 30 h 40 v 40 h -40 Z\")" should set the property value
+PASS e.style['clip-path'] = "path(nonzero, \"M20,20h60 v60 h-60z M30,30 h40 v40 h-40z\")" should set the property value
+PASS e.style['clip-path'] = "xywh(0 1% 2px 3em)" should set the property value
+PASS e.style['clip-path'] = "xywh(0px 1% 2px 3em round 0)" should set the property value
+PASS e.style['clip-path'] = "xywh(0px 1% 2px 3em round 0 1px)" should set the property value
+PASS e.style['clip-path'] = "xywh(0px 1% 2px 3em round 0px 1px 2%)" should set the property value
+PASS e.style['clip-path'] = "xywh(0px 1% 2px 3em round 0px 1px 2% 3em)" should set the property value
+PASS e.style['clip-path'] = "rect(0 100% 200px 4em)" should set the property value
+PASS e.style['clip-path'] = "rect(auto auto auto auto)" should set the property value
+PASS e.style['clip-path'] = "rect(0px 100% auto 4em round 0)" should set the property value
+PASS e.style['clip-path'] = "rect(0px 100% auto 4em round 0 1px)" should set the property value
+PASS e.style['clip-path'] = "rect(0px 100% auto 4em round 0px 1px 2%)" should set the property value
+PASS e.style['clip-path'] = "rect(0px 100% auto 4em round 0px 1px 2% 3em)" should set the property value
+PASS e.style['clip-path'] = "border-box" should set the property value
+PASS e.style['clip-path'] = "padding-box" should set the property value
+PASS e.style['clip-path'] = "content-box" should set the property value
+PASS e.style['clip-path'] = "margin-box" should set the property value
+PASS e.style['clip-path'] = "fill-box" should set the property value
+PASS e.style['clip-path'] = "stroke-box" should set the property value
+PASS e.style['clip-path'] = "view-box" should set the property value
+FAIL e.style['clip-path'] = "circle(7% at 8% 9%) border-box" should set the property value assert_equals: serialization should be canonical expected "circle(7% at 8% 9%)" but got "circle(7% at 8% 9%) border-box"
+FAIL e.style['clip-path'] = "border-box circle(7% at 8% 9%)" should set the property value assert_equals: serialization should be canonical expected "circle(7% at 8% 9%)" but got "circle(7% at 8% 9%) border-box"
+PASS e.style['clip-path'] = "url(https://example.com/)" should set the property value
+PASS e.style['clip-path'] = "url(\"https://example.com/\")" should set the property value
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid.html b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid.html
index 2fb0c62..84555fd 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid.html
@@ -73,10 +73,10 @@
 test_valid_value("clip-path", "view-box");
 
 // <basic-shape> <geometry-box>
-test_valid_value("clip-path", "circle(7% at 8% 9%) border-box");
+test_valid_value("clip-path", "circle(7% at 8% 9%) border-box", "circle(7% at 8% 9%)");
 
 // <geometry-box> <basic-shape>
-test_valid_value("clip-path", "border-box circle(7% at 8% 9%)", ["border-box circle(7% at 8% 9%)", "circle(7% at 8% 9%) border-box"]);
+test_valid_value("clip-path", "border-box circle(7% at 8% 9%)", "circle(7% at 8% 9%)");
 
 // <clip-source>
 test_valid_value("clip-path", "url(https://example.com/)", ["url(https://example.com/)", "url(\"https://example.com/\")"]);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid.html.ini b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid.html.ini
new file mode 100644
index 0000000..88f0aad
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-valid.html.ini
@@ -0,0 +1,10 @@
+[clip-path-valid.html]
+  [e.style['clip-path'\] = "border-box circle(7% at 8% 9%)" should set the property value]
+    expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): PASS
+      FAIL
+
+  [e.style['clip-path'\] = "circle(7% at 8% 9%) border-box" should set the property value]
+    expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): PASS
+      FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-015.html.ini b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-015.html.ini
index 2b81201..2da362c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-015.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-015.html.ini
@@ -1,4 +1,5 @@
 [shape-image-015.html]
   expected:
     if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+    if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
     if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-026.html.ini b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-026.html.ini
index 433b21a..d701cf20 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-026.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-026.html.ini
@@ -1,3 +1,4 @@
 [shape-image-026.html]
   expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-027.html.ini b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-027.html.ini
new file mode 100644
index 0000000..8616b64
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-027.html.ini
@@ -0,0 +1,3 @@
+[shape-image-027.html]
+  expected:
+    if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-001.html.ini
index af185e10..fda94579 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-001.html.ini
@@ -1,7 +1,5 @@
 [text-spacing-trim-001.html]
   expected:
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac13-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac11-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "win"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "linux"): FAIL
+    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac10.15"): PASS
+    if (product == "content_shell") and (virtual_suite == "css-text-autospace"): PASS
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-colon-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-colon-001.html.ini
index cef3413..c0869ec4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-colon-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-colon-001.html.ini
@@ -1,7 +1,5 @@
 [text-spacing-trim-colon-001.html]
   expected:
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac13-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac11-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "win"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "linux"): FAIL
+    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac10.15"): PASS
+    if (product == "content_shell") and (virtual_suite == "css-text-autospace"): PASS
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dot-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dot-001.html.ini
index 3e192c8..f9b8d09 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dot-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-spacing-trim/text-spacing-trim-dot-001.html.ini
@@ -1,7 +1,5 @@
 [text-spacing-trim-dot-001.html]
   expected:
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac13-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac11-arm64"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "win"): FAIL
-    if (product == "content_shell") and (virtual_suite == "") and (os == "linux"): FAIL
+    if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac10.15"): PASS
+    if (product == "content_shell") and (virtual_suite == "css-text-autospace"): PASS
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-005.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-005.html.ini
new file mode 100644
index 0000000..e272f36
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-005.html.ini
@@ -0,0 +1,3 @@
+[text-transform-capitalize-005.html]
+  expected:
+    if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-bottom-right-radius-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-bottom-right-radius-001.html.ini
new file mode 100644
index 0000000..9afaedf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-bottom-right-radius-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-input-search-border-bottom-right-radius-001.html]
+  expected:
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-block-end-style-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-block-end-style-001.html.ini
new file mode 100644
index 0000000..a91edd5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-block-end-style-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-input-submit-border-block-end-style-001.html]
+  expected:
+    if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-top-color-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-top-color-001.html.ini
new file mode 100644
index 0000000..d56785e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-top-color-001.html.ini
@@ -0,0 +1,3 @@
+[kind-of-widget-fallback-input-submit-border-top-color-001.html]
+  expected:
+    if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/new-content-with-overflow-zoomed.html.ini b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/new-content-with-overflow-zoomed.html.ini
new file mode 100644
index 0000000..3689c97
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/new-content-with-overflow-zoomed.html.ini
@@ -0,0 +1,2 @@
+[new-content-with-overflow-zoomed.html]
+  expected: [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-window.html.ini b/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-window.html.ini
index 8ad2826..b794e956 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-window.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-window.html.ini
@@ -17,6 +17,7 @@
     expected:
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing"): FAIL
 
   [Main frame with auto scroll-behavior ; scrollBy() with smooth behavior]
@@ -28,11 +29,12 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11"): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac10.15"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == ""): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
-      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): FAIL
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux"): [FAIL, PASS]
 
   [Main frame with auto scroll-behavior ; scrollTo() with smooth behavior]
     expected:
@@ -43,22 +45,29 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11"): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac10.15"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): FAIL
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux"): FAIL
-      if (product == "content_shell") and (virtual_suite == "") and (os == "linux"): [PASS, FAIL]
 
   [Main frame with smooth scroll-behavior ; scroll() with auto behavior]
     expected:
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): FAIL
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing"): FAIL
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac"): FAIL
 
   [Main frame with smooth scroll-behavior ; scroll() with default behavior]
     expected:
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): FAIL
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing"): FAIL
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac"): FAIL
 
   [Main frame with smooth scroll-behavior ; scroll() with smooth behavior]
     expected:
@@ -69,10 +78,11 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac10.15"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): FAIL
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux"): FAIL
-      if (product == "content_shell") and (virtual_suite == "") and (os == "linux"): [PASS, FAIL]
 
   [Main frame with smooth scroll-behavior ; scrollBy() with auto behavior]
     expected:
@@ -83,11 +93,12 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11"): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac10.15"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == ""): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux"): [FAIL, PASS]
 
   [Main frame with smooth scroll-behavior ; scrollBy() with default behavior]
     expected:
@@ -98,11 +109,12 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11"): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac10.15"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == ""): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
-      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): FAIL
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux"): [FAIL, PASS]
 
   [Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior]
     expected:
@@ -116,8 +128,9 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == ""): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "") and (os == "linux"): [FAIL, PASS]
 
   [Main frame with smooth scroll-behavior ; scrollTo() with auto behavior]
     expected:
@@ -128,11 +141,11 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11"): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac10.15"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): FAIL
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux"): FAIL
 
   [Main frame with smooth scroll-behavior ; scrollTo() with default behavior]
     expected:
@@ -143,11 +156,11 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11"): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac10.15"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): FAIL
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux"): FAIL
 
   [Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior]
     expected:
@@ -158,8 +171,8 @@
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac11"): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "mac") and (port == "mac10.15"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): FAIL
       if (product == "content_shell") and (virtual_suite == "") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if (product == "content_shell") and (virtual_suite == "") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "win"): FAIL
-      if (product == "content_shell") and (virtual_suite == "threaded-prefer-compositing") and (os == "linux"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01a.html b/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01a.html
index e362cd83..f379d14 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01a.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01a.html
@@ -8,7 +8,7 @@
     <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
     <meta name="assert" content="Test checks :dir() basic functions with valid and invalid values.">
     <link rel="match" href="dir-style-01-ref.html">
-    <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-20">
+    <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-30">
     <style>
       div { text-align: left; }
       :dir(ltr) { color: blue }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01a.html.ini b/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01a.html.ini
deleted file mode 100644
index 34e064b..0000000
--- a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01a.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[dir-style-01a.html]
-  expected:
-    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01b.html b/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01b.html
index 109a7bc..37ad940 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01b.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01b.html
@@ -8,7 +8,7 @@
     <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
     <meta name="assert" content="Test checks :dir() basic functions after dynamic directionality change on elements.">
     <link rel="match" href="dir-style-01-ref.html">
-    <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-20">
+    <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-30">
     <style>
       div { text-align: left; }
       :dir(ltr) { color: blue }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01b.html.ini b/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01b.html.ini
deleted file mode 100644
index ce1eda5c..0000000
--- a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-01b.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[dir-style-01b.html]
-  expected:
-    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-04.html b/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-04.html
index d0a458c8..cbfe1307 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-04.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/dir-style-04.html
@@ -8,6 +8,7 @@
     <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
     <meta name="assert" content="Test checks :dir() basic functions on runtime added elements.">
     <link rel="match" href="dir-style-04-ref.html">
+    <meta name="fuzzy" content="maxDifference=0-70; totalPixels=0-180">
     <style>
       :dir(ltr) { color: blue }
       :dir(rtl) { color: lime }
diff --git a/third_party/blink/web_tests/external/wpt/fenced-frame/script-focus.https.html.ini b/third_party/blink/web_tests/external/wpt/fenced-frame/script-focus.https.html.ini
index aa4e5d0..663f4ab 100644
--- a/third_party/blink/web_tests/external/wpt/fenced-frame/script-focus.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/fenced-frame/script-focus.https.html.ini
@@ -1,61 +1,25 @@
 [script-focus.https.html]
-  expected:
-    if (product == "content_shell") and (os == "win"): OK
-    if (product == "content_shell") and (os == "linux"): OK
-    if product == "chrome": OK
-    [TIMEOUT, OK]
+  expected: [TIMEOUT, OK]
   [A fenced frame can pull window.focus() after user activation]
-    expected:
-      if (product == "content_shell") and (os == "win"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      [FAIL, PASS]
+    expected: [FAIL, PASS]
 
   [A fenced frame cannot pull window.focus() without user activation]
-    expected:
-      if (product == "content_shell") and (os == "win"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      [FAIL, PASS]
+    expected: [FAIL, PASS]
 
   [A fenced frame nested in another fenced frame cannot pull focus]
-    expected:
-      if (product == "content_shell") and (os == "win"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      [FAIL, PASS]
+    expected: [FAIL, PASS]
 
   [An embedder can focus out of a fenced frame]
-    expected:
-      if (product == "content_shell") and (os == "win"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      [FAIL, PASS]
+    expected: [FAIL, PASS]
 
   [Another fenced frame cannot pull focus out of a focused fenced frame]
-    expected:
-      if (product == "content_shell") and (os == "win"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      [FAIL, PASS]
+    expected: [FAIL, PASS]
 
   [Fenced frames can't pull script focus until getting user activation]
-    expected:
-      if (product == "content_shell") and (os == "win"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      [FAIL, PASS]
+    expected: [FAIL, PASS]
 
   [Focused fenced frames can move programmatic focus within frame]
-    expected:
-      if (product == "content_shell") and (os == "win"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      [FAIL, PASS]
+    expected: [FAIL, PASS]
 
   [Script focus into a fenced frame consumes user activation]
-    expected:
-      if (product == "content_shell") and (os == "win"): PASS
-      if (product == "content_shell") and (os == "linux"): PASS
-      if product == "chrome": PASS
-      [FAIL, PASS]
+    expected: [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/fenced-frame.tentative.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/fenced-frame.tentative.https.window.js.ini
index 5541b59e..ccd1c6dc 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/fenced-frame.tentative.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/fenced-frame.tentative.https.window.js.ini
@@ -71,12 +71,14 @@
 
   [treat-as-public-address to local: failed preflight.]
     expected:
-      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       FAIL
 
   [treat-as-public-address to local: missing CORS headers.]
     expected:
-      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux"): PASS
+      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux") and (flag_specific == ""): PASS
       FAIL
 
   [treat-as-public-address to local: missing PNA header.]
@@ -93,7 +95,8 @@
 
   [treat-as-public-address to private: failed preflight.]
     expected:
-      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS]
+      if (product == "content_shell") and (virtual_suite == "fenced-frame-mparch") and (os == "linux") and (flag_specific == ""): [FAIL, PASS]
       FAIL
 
   [treat-as-public-address to private: missing CORS headers.]
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-blob-fetch.tentative.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-blob-fetch.tentative.https.window.js.ini
index e0c171f..c63674bf 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-blob-fetch.tentative.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/shared-worker-blob-fetch.tentative.https.window.js.ini
@@ -1,5 +1,6 @@
 [shared-worker-blob-fetch.tentative.https.window.html]
   expected:
+    if (product == "content_shell") and (virtual_suite == "pna-workers-disabled") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [OK, TIMEOUT]
     if (product == "content_shell") and (virtual_suite == "pna-permission") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [OK, TIMEOUT]
     if (product == "content_shell") and (virtual_suite == "keepalive-in-browser-migration") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [OK, TIMEOUT]
     if (product == "content_shell") and (virtual_suite == "plz-dedicated-worker"): [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html.ini
index bc34b99e..e49d3e17 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.html.ini
@@ -1,12 +1,15 @@
 [offscreencanvas.getcontext.html]
   [Test that getContext twice with different context type returns null the second time]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Test that getContext with supported string returns correct results]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Test that webglcontext.canvas should return the original OffscreenCanvas]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js.ini
index cc58ae8..6af2eb8 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.getcontext.worker.js.ini
@@ -1,12 +1,15 @@
 [offscreencanvas.getcontext.worker.html]
   [Test that getContext twice with different context type returns null the second time]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Test that getContext with supported string returns correct results]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Test that webglcontext.canvas should return the original OffscreenCanvas]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.html.ini
index d0533c5..13dd77918 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.html.ini
@@ -1,4 +1,5 @@
 [offscreencanvas.transfer.to.imagebitmap.html]
   [Test that transferToImageBitmap returns an ImageBitmap with correct width and height]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.w.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.w.html.ini
index 6ce450a..4baa7ed 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.w.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.w.html.ini
@@ -1,4 +1,5 @@
 [offscreencanvas.transfer.to.imagebitmap.w.html]
   [Test that transferToImageBitmap returns an ImageBitmap with correct width and height in a worker]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html.ini
index 2d0f262..fe3dde2 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html.ini
@@ -1,4 +1,5 @@
 [offscreencanvas.transferrable.w.html]
   [Test that transfer an OffscreenCanvas that has a webgl context throws exception in a worker.]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
index f709ae8d..7ddaa27 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
@@ -1,6 +1,6 @@
 [sandbox-top-navigation-child-special-cases.tentative.sub.window.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64") and (virtual_suite == "disable-intersection-optimization"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64") and (virtual_suite == "disable-intersection-optimization"): [TIMEOUT, OK]
     if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64") and (virtual_suite == "disable-intersection-optimization"): OK
     if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64") and (virtual_suite == ""): [TIMEOUT, OK]
     if (product == "content_shell") and (os == "win") and (port == "win11"): ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/urlencoded2.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/urlencoded2.window.js.ini
index 5b102b6a..95abc47 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/urlencoded2.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/urlencoded2.window.js.ini
@@ -1,4 +1,5 @@
 [urlencoded2.window.html]
   expected:
+    if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [TIMEOUT, OK]
     if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [OK, TIMEOUT]
     if (product == "content_shell") and (os == "mac"): [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-2.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-2.html.ini
index 842455d..d14950bc 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-2.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-2.html.ini
@@ -1,18 +1,22 @@
 [popover-focus-2.html]
   expected:
-    if (product == "content_shell") and (os == "win"): OK
-    if (product == "content_shell") and (os == "linux"): OK
-    if product == "chrome": OK
-    TIMEOUT
+    if (product == "content_shell") and (os == "mac"): TIMEOUT
+    if product == "chrome": TIMEOUT
   [Circular reference tab navigation]
-    expected: FAIL
+    expected:
+      if product == "chrome": [TIMEOUT, PASS, NOTRUN]
+      FAIL
 
   [Popover focus navigation]
-    expected: FAIL
+    expected:
+      if product == "chrome": [FAIL, TIMEOUT]
+      FAIL
 
   [Popover focus only returns to invoker when focus is within the popover]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": NOTRUN
 
   [Popover focus returns when popover is hidden by invoker]
-    expected: FAIL
+    expected:
+      if product == "chrome": [NOTRUN, TIMEOUT]
+      FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js
index bc7643c..f11291e 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js
@@ -18,7 +18,7 @@
 async function sendTab() {
   await waitForRender();
   const kTab = '\uE004';
-  await new test_driver.send_keys(document.documentElement,kTab);
+  await new test_driver.send_keys(document.activeElement || document.documentElement, kTab);
   await waitForRender();
 }
 async function sendShiftTab() {
@@ -35,12 +35,12 @@
 }
 async function sendEscape() {
   await waitForRender();
-  await new test_driver.send_keys(document.documentElement,'\uE00C'); // Escape
+  await new test_driver.send_keys(document.activeElement || document.documentElement,'\uE00C'); // Escape
   await waitForRender();
 }
 async function sendEnter() {
   await waitForRender();
-  await new test_driver.send_keys(document.documentElement,'\uE007'); // Enter
+  await new test_driver.send_keys(document.activeElement || document.documentElement,'\uE007'); // Enter
   await waitForRender();
 }
 function isElementVisible(el) {
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/referrer-policy-for-descendants.sub.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/referrer-policy-for-descendants.sub.html
index cf8a3dc..4a7005da 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/referrer-policy-for-descendants.sub.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/referrer-policy-for-descendants.sub.html
@@ -23,19 +23,27 @@
 import { referrer as parentWithOrigin} from
     "./resources/import-referrer-checker.sub.js?name=same_remote&pipe=header(Referrer-Policy,origin)";
 
+import { referrer as parentWithSameOrigin} from
+    "./resources/import-referrer-checker.sub.js?name=same_remote_so&pipe=header(Referrer-Policy,same-origin)";
+
 import { referrer as parentWithOriginWhenCrossOriginRemoteDescendant} from
     "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote_owco&pipe=header(Referrer-Policy,origin-when-cross-origin)";
 
 import { referrer as remoteParentWithOriginWhenCrossOriginSameOriginDescendant} from
     "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same&pipe=header(Referrer-Policy,origin-when-cross-origin)";
 
+import { referrer as remoteParentWithSameOriginWhenCrossOriginSameOriginDescendant} from
+    "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same_so&pipe=header(Referrer-Policy,same-origin)";
+
 import { referrer as remoteParentWithOriginWhenCrossOriginRemoteDescendant} from
     "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_remote&pipe=header(Referrer-Policy,origin-when-cross-origin)";
 
+import { referrer as remoteParentWithSameOriginWhenCrossOriginRemoteDescendant} from
+    "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_remote_so&pipe=header(Referrer-Policy,same-origin)";
+
 import { referrer as parentWithInvalidPolicy } from
     "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same_invalid&pipe=header(Referrer-Policy,invalid-policy)";
 
-
 test(t => {
   const expected_url =
       new URL("html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=same_same&pipe=header(Referrer-Policy,no-referrer-when-downgrade)",
@@ -52,6 +60,15 @@
 }, "Parent module delivered with `origin` policy importing a same-origin descendant script.");
 
 test(t => {
+  const expected_url =
+      new URL("html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=same_remote_so&pipe=header(Referrer-Policy,same-origin)",
+              window.origin);
+  assert_equals(
+      parentWithSameOrigin, expected_url.toString(),
+      "Descendant referrer should be the parent's full URL.");
+}, "Parent module delivered with `same-origin` policy importing a same-origin descendant script.");
+
+test(t => {
   assert_equals(
       parentWithOriginWhenCrossOriginRemoteDescendant, window.origin + "/",
       "Remote descendant referrer should be the parent's origin.");
@@ -67,11 +84,25 @@
 }, "Remote parent module delivered with `origin-when-cross-origin` policy importing a same-origin-to-parent-module descendant script.");
 
 test(t => {
+  const expected_url =
+      new URL("/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same_so&pipe=header(Referrer-Policy,same-origin)",
+              "http://{{domains[www1]}}:{{ports[http][0]}}/");
+  assert_equals(
+      remoteParentWithSameOriginWhenCrossOriginSameOriginDescendant, expected_url.toString(),
+      "Same-origin descendant referrer should be the parent's full URL.");
+}, "Remote parent module delivered with `same-origin` policy importing a same-origin-to-parent-module descendant script.");
+
+test(t => {
   assert_equals(
       remoteParentWithOriginWhenCrossOriginRemoteDescendant, "http://{{domains[www1]}}:{{ports[http][0]}}/",
       "Remote-origin descendant referrer should be the parent's origin.");
 }, "Remote parent module delivered with `origin-when-cross-origin` policy importing a cross-origin-to-parent-module descendant script.");
 
+test(t => {
+  assert_equals(
+      remoteParentWithSameOriginWhenCrossOriginRemoteDescendant, "");
+}, "Remote parent module delivered with `same-origin` policy importing a cross-origin-to-parent-module descendant script.");
+
 // This tests the following spec line:
 //
 // "If referrerPolicy is not the empty string, set options's referrer policy to
diff --git a/third_party/blink/web_tests/external/wpt/paint-timing/with-first-paint/first-contentful-canvas-webgl2.html.ini b/third_party/blink/web_tests/external/wpt/paint-timing/with-first-paint/first-contentful-canvas-webgl2.html.ini
index 4028fe8..7cd9f9a 100644
--- a/third_party/blink/web_tests/external/wpt/paint-timing/with-first-paint/first-contentful-canvas-webgl2.html.ini
+++ b/third_party/blink/web_tests/external/wpt/paint-timing/with-first-paint/first-contentful-canvas-webgl2.html.ini
@@ -1,4 +1,5 @@
 [first-contentful-canvas-webgl2.html]
   [First contentful paint fires due to webgl2 canvas render.]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): PRECONDITION_FAILED
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PRECONDITION_FAILED
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): PRECONDITION_FAILED
diff --git a/third_party/blink/web_tests/external/wpt/resources/testharness.js b/third_party/blink/web_tests/external/wpt/resources/testharness.js
index d06123f8..497ae23 100644
--- a/third_party/blink/web_tests/external/wpt/resources/testharness.js
+++ b/third_party/blink/web_tests/external/wpt/resources/testharness.js
@@ -1497,7 +1497,7 @@
     /**
      * Assert that ``actual`` is the same value as ``expected``.
      *
-     * For objects this compares by cobject identity; for primitives
+     * For objects this compares by object identity; for primitives
      * this distinguishes between 0 and -0, and has correct handling
      * of NaN.
      *
diff --git a/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/force-load-at-top.html.ini b/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/force-load-at-top.html.ini
index 846700d..23f66a1 100644
--- a/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/force-load-at-top.html.ini
+++ b/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/force-load-at-top.html.ini
@@ -2,5 +2,6 @@
   expected:
     if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [TIMEOUT, OK]
     if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [TIMEOUT, OK]
+    if (product == "content_shell") and (os == "mac") and (port == "mac12"): TIMEOUT
     if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [TIMEOUT, OK]
     if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/svg/animations/scripted/clear-mapped-animation.svg b/third_party/blink/web_tests/external/wpt/svg/animations/scripted/clear-mapped-animation.svg
new file mode 100644
index 0000000..518fe61
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/animations/scripted/clear-mapped-animation.svg
@@ -0,0 +1,17 @@
+<svg class="reftest-wait" onload="load()" xmlns="http://www.w3.org/2000/svg"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <html:link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1717312"/>
+  <html:script src="/common/reftest-wait.js"/>
+  <html:script src="/common/rendering-utils.js"/>
+  <html:link rel="match" href="../../embedded/reference/green-rect-100x100.svg"/>
+  <rect id="r" width="100" height="50" fill="green">
+    <animate attributeName="height" values="0" dur="20ms"/>
+  </rect>
+  <script>
+    function load() {
+      document.documentElement.setCurrentTime(1);
+      document.getElementById("r").setAttribute("height", 100);
+      waitForAtLeastOneFrame().then(takeScreenshot);
+    }
+  </script>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-before-xr-session.https.html.ini b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-before-xr-session.https.html.ini
index 1af1335..26a1d472 100644
--- a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-before-xr-session.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-before-xr-session.https.html.ini
@@ -4,16 +4,20 @@
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): TIMEOUT
   [Make sure video.rVFC works during a non-immersive session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Make sure video.rVFC works during a non-immersive session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Make sure video.rVFC works during an immersive session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Make sure video.rVFC works during an immersive session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-during-xr-session.https.html.ini b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-during-xr-session.https.html.ini
index 8affa31..f5941ab 100644
--- a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-during-xr-session.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-during-xr-session.https.html.ini
@@ -1,8 +1,10 @@
 [request-video-frame-callback-during-xr-session.https.html]
   [Make sure video.rVFC callbacks started during an immersive session continue after it ends - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Make sure video.rVFC callbacks started during an immersive session continue after it ends - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/setTargetAtTime-after-event-within-block.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/setTargetAtTime-after-event-within-block.html
index 0e68639..ca02b0d 100644
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/setTargetAtTime-after-event-within-block.html
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioparam-interface/setTargetAtTime-after-event-within-block.html
@@ -53,10 +53,12 @@
 }, "setTargetAtTime() after setValueAtTime()");
 
 promise_test(async function() {
-  const bufferSize = 128;
+  const bufferSize = 129;
   const sampleRate = 16384;
   const startSample1 = 125;
   const target1 = Math.fround(-1./Math.expm1(-1.));
+  // Intentionally testing the second curve before and after the
+  // rendering quantum boundary.
   const startSample2 = startSample1 + 1;
   const target2 = 0.;
   const timeConstant = 1./sampleRate;
@@ -88,5 +90,10 @@
     Math.fround(output[startSample2] * Math.exp(-1.)),
     tolerance,
     "scheduled value at startSample2 + 1");
+  assert_approx_equals(
+    output[startSample2 + 2],
+    Math.fround(output[startSample2] * Math.exp(-2.)),
+    tolerance,
+    "scheduled value at startSample2 + 2");
 }, "setTargetAtTime() after setTargetAtTime()");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/full-cycle-test.https.any.js.ini b/third_party/blink/web_tests/external/wpt/webcodecs/full-cycle-test.https.any.js.ini
index 2343a9d..50541b4 100644
--- a/third_party/blink/web_tests/external/wpt/webcodecs/full-cycle-test.https.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/webcodecs/full-cycle-test.https.any.js.ini
@@ -26,7 +26,6 @@
 [full-cycle-test.https.any.html?h264_avc]
   expected:
     if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64") and (virtual_suite == ""): [ERROR, CRASH]
-    if (product == "content_shell") and (os == "mac") and (port == "mac12") and (virtual_suite == ""): OK
     if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): TIMEOUT
     if (product == "content_shell") and (os == "win"): OK
     if (product == "content_shell") and (os == "linux"): OK
@@ -34,19 +33,13 @@
     CRASH
   [Encoding and decoding cycle]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12") and (virtual_suite == ""): PRECONDITION_FAILED
-      if (product == "content_shell") and (os == "win"): PRECONDITION_FAILED
-      if (product == "content_shell") and (os == "linux"): PRECONDITION_FAILED
-      if product == "chrome": PRECONDITION_FAILED
-      FAIL
+      if (product == "content_shell") and (os == "mac"): FAIL
+      PRECONDITION_FAILED
 
   [Encoding and decoding cycle w/ stripped color space]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12") and (virtual_suite == ""): PRECONDITION_FAILED
-      if (product == "content_shell") and (os == "win"): PRECONDITION_FAILED
-      if (product == "content_shell") and (os == "linux"): PRECONDITION_FAILED
-      if product == "chrome": PRECONDITION_FAILED
-      FAIL
+      if (product == "content_shell") and (os == "mac"): FAIL
+      PRECONDITION_FAILED
 
 
 [full-cycle-test.https.any.html?h265_annexb]
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/__init__.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/__init__.py
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/navigation_started.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/navigation_started.py
new file mode 100644
index 0000000..34f3a624
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/navigation_started.py
@@ -0,0 +1,354 @@
+import asyncio
+
+import pytest
+from tests.support.sync import AsyncPoll
+
+from webdriver.error import TimeoutException
+from webdriver.bidi.error import UnknownErrorException
+from webdriver.bidi.modules.script import ContextTarget
+
+from ... import int_interval
+from .. import assert_navigation_info
+
+
+pytestmark = pytest.mark.asyncio
+
+NAVIGATION_STARTED_EVENT = "browsingContext.navigationStarted"
+PAGE_EMPTY = "/webdriver/tests/bidi/browsing_context/support/empty.html"
+
+
+async def test_unsubscribe(bidi_session):
+    await bidi_session.session.subscribe(events=[NAVIGATION_STARTED_EVENT])
+    await bidi_session.session.unsubscribe(events=[NAVIGATION_STARTED_EVENT])
+
+    # Track all received browsingContext.navigationStarted events in the events array
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(
+        NAVIGATION_STARTED_EVENT, on_event
+    )
+
+    await bidi_session.browsing_context.create(type_hint="tab")
+
+    wait = AsyncPoll(bidi_session, timeout=0.5)
+    with pytest.raises(TimeoutException):
+        await wait.until(lambda _: len(events) > 0)
+
+    remove_listener()
+
+
+async def test_subscribe(
+    bidi_session, subscribe_events, inline, new_tab, wait_for_event
+):
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    on_entry = wait_for_event(NAVIGATION_STARTED_EVENT)
+    url = inline("<div>foo</div>")
+    result = await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url
+    )
+    event = await on_entry
+
+    assert_navigation_info(
+        event,
+        {
+            "context": new_tab["context"],
+            "navigation": result["navigation"],
+            "url": url,
+        },
+    )
+
+
+async def test_timestamp(
+    bidi_session, current_time, subscribe_events, inline, new_tab, wait_for_event
+):
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    time_start = await current_time()
+
+    on_entry = wait_for_event(NAVIGATION_STARTED_EVENT)
+    url = inline("<div>foo</div>")
+    result = await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url
+    )
+    event = await on_entry
+
+    time_end = await current_time()
+
+    assert_navigation_info(
+        event,
+        {
+            "context": new_tab["context"],
+            "navigation": result["navigation"],
+            "timestamp": int_interval(time_start, time_end),
+        },
+    )
+
+
+async def test_iframe(
+    bidi_session, subscribe_events, top_context, test_page_same_origin_frame, test_page
+):
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(
+        NAVIGATION_STARTED_EVENT, on_event
+    )
+
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    result = await bidi_session.browsing_context.navigate(
+        context=top_context["context"], url=test_page_same_origin_frame, wait="complete"
+    )
+
+    # Check that 2 navigation-started events were received, one for the top context
+    # and one for the iframe.
+    assert len(events) == 2
+
+    contexts = await bidi_session.browsing_context.get_tree(root=top_context["context"])
+
+    assert len(contexts) == 1
+    root_info = contexts[0]
+    children_info = root_info["children"]
+    assert len(children_info) == 1
+
+    # First navigation-started event comes from the top-level browsing context.
+    assert_navigation_info(
+        events[0],
+        {
+            "context": top_context["context"],
+            "navigation": result["navigation"],
+            "url": test_page_same_origin_frame,
+        },
+    )
+
+    assert_navigation_info(
+        events[1],
+        {
+            "context": children_info[0]["context"],
+            "url": test_page,
+        },
+    )
+    assert events[1]["navigation"] is not None
+    assert events[1]["navigation"] != result["navigation"]
+
+    remove_listener()
+
+
+async def test_nested_iframes(
+    bidi_session,
+    subscribe_events,
+    top_context,
+    test_page_nested_frames,
+    test_page_same_origin_frame,
+    test_page,
+):
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(
+        NAVIGATION_STARTED_EVENT, on_event
+    )
+
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    result = await bidi_session.browsing_context.navigate(
+        context=top_context["context"], url=test_page_nested_frames, wait="complete"
+    )
+
+    # Check that 3 navigation-started events were received, one for the top context
+    # and one for each of the 2 iframes.
+    assert len(events) == 3
+
+    contexts = await bidi_session.browsing_context.get_tree(root=top_context["context"])
+
+    assert len(contexts) == 1
+    root_info = contexts[0]
+    assert len(root_info["children"]) == 1
+    child1_info = root_info["children"][0]
+    assert len(child1_info["children"]) == 1
+    child2_info = child1_info["children"][0]
+
+    assert_navigation_info(
+        events[0],
+        {
+            "context": root_info["context"],
+            "navigation": result["navigation"],
+            "url": test_page_nested_frames,
+        },
+    )
+
+    assert_navigation_info(
+        events[1],
+        {
+            "context": child1_info["context"],
+            "url": test_page_same_origin_frame,
+        },
+    )
+    assert events[1]["navigation"] is not None
+    assert events[1]["navigation"] != result["navigation"]
+
+    assert_navigation_info(
+        events[2],
+        {
+            "context": child2_info["context"],
+            "url": test_page,
+        },
+    )
+    assert events[2]["navigation"] is not None
+    assert events[2]["navigation"] != result["navigation"]
+    assert events[2]["navigation"] != events[1]["navigation"]
+
+    remove_listener()
+
+
+@pytest.mark.parametrize("type_hint", ["tab", "window"])
+async def test_new_context(bidi_session, subscribe_events, wait_for_event, type_hint):
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    on_entry = wait_for_event(NAVIGATION_STARTED_EVENT)
+    top_level_context = await bidi_session.browsing_context.create(type_hint="tab")
+    navigation_info = await on_entry
+    assert_navigation_info(
+        navigation_info,
+        {
+            "context": top_level_context["context"],
+            "url": "about:blank",
+        },
+    )
+
+
+async def test_same_document_navigation(bidi_session, new_tab, url, subscribe_events):
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url(PAGE_EMPTY), wait="complete"
+    )
+
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    # Track all received browsingContext.navigationStarted events in the events array
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(
+        NAVIGATION_STARTED_EVENT, on_event
+    )
+
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url(PAGE_EMPTY + "#foo"), wait="complete"
+    )
+
+    remove_listener()
+
+
+async def test_window_open(bidi_session, subscribe_events, wait_for_event, top_context):
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    on_entry = wait_for_event(NAVIGATION_STARTED_EVENT)
+
+    await bidi_session.script.evaluate(
+        expression="""window.open('about:blank');""",
+        target=ContextTarget(top_context["context"]),
+        await_promise=False,
+    )
+
+    navigation_info = await on_entry
+    assert_navigation_info(
+        navigation_info,
+        {
+            "url": "about:blank",
+        },
+    )
+    assert navigation_info["navigation"] is not None
+
+    # Retrieve all contexts to get the context for the new window.
+    contexts = await bidi_session.browsing_context.get_tree()
+    assert navigation_info["context"] == contexts[-1]["context"]
+
+
+async def test_document_write(bidi_session, subscribe_events, top_context):
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    # Track all received browsingContext.navigationStarted events in the events array
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(
+        NAVIGATION_STARTED_EVENT, on_event
+    )
+
+    await bidi_session.script.evaluate(
+        expression="""document.open(); document.write("<h1>Replaced</h1>"); document.close();""",
+        target=ContextTarget(top_context["context"]),
+        await_promise=False,
+    )
+
+    wait = AsyncPoll(bidi_session, timeout=0.5)
+    with pytest.raises(TimeoutException):
+        await wait.until(lambda _: len(events) > 0)
+
+    remove_listener()
+
+
+async def test_page_with_base_tag(
+    bidi_session, subscribe_events, inline, new_tab, wait_for_event
+):
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    on_entry = wait_for_event(NAVIGATION_STARTED_EVENT)
+    url = inline("""<base href="/relative-path">""")
+    result = await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url
+    )
+    event = await on_entry
+
+    assert_navigation_info(
+        event,
+        {"context": new_tab["context"], "navigation": result["navigation"], "url": url},
+    )
+
+
+@pytest.mark.parametrize(
+    "url",
+    [
+        "thisprotocoldoesnotexist://",
+        "https://doesnotexist.localhost/",
+    ],
+    ids=[
+        "protocol",
+        "host",
+    ],
+)
+async def test_invalid_navigation(
+    bidi_session, new_tab, subscribe_events, wait_for_event, url
+):
+    await subscribe_events(events=[NAVIGATION_STARTED_EVENT])
+
+    on_entry = wait_for_event(NAVIGATION_STARTED_EVENT)
+
+    with pytest.raises(UnknownErrorException):
+        await bidi_session.browsing_context.navigate(
+            context=new_tab["context"], url=url, wait="complete"
+        )
+
+    navigation_info = await on_entry
+    assert_navigation_info(
+        navigation_info,
+        {
+            "context": new_tab["context"],
+            "url": url,
+        },
+    )
+    assert navigation_info["navigation"] is not None
+
+    await bidi_session.session.unsubscribe(events=[NAVIGATION_STARTED_EVENT])
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/navigation_started.py.ini b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/navigation_started.py.ini
new file mode 100644
index 0000000..cb12cf5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/navigation_started/navigation_started.py.ini
@@ -0,0 +1,2 @@
+[navigation_started.py]
+  expected: TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/__init__.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/__init__.py
index 5635a4b..12dd64a 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/__init__.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/__init__.py
@@ -1,5 +1,7 @@
 from __future__ import annotations
 from typing import Any, Callable, Mapping
+from webdriver.bidi.modules.script import ContextTarget
+
 from .. import any_int, any_string, recursive_compare
 
 
@@ -211,3 +213,24 @@
     ("window", {"type": "window", },),
     ("new URL('https://example.com')", {"type": "object", },),
 ]
+
+
+async def create_sandbox(bidi_session, context, sandbox_name="Test", method="evaluate"):
+    if method == "evaluate":
+        result = await bidi_session.script.evaluate(
+            raw_result=True,
+            expression="1 + 2",
+            await_promise=False,
+            target=ContextTarget(context, sandbox=sandbox_name),
+        )
+    elif method == "call_function":
+        result = await bidi_session.script.call_function(
+            raw_result=True,
+            function_declaration="() => 1 + 2",
+            await_promise=False,
+            target=ContextTarget(context, sandbox=sandbox_name),
+        )
+    else:
+        raise Exception(f"Unsupported method to create a sandbox: {method}")
+
+    return result["realm"]
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_created/__init__.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_created/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_created/__init__.py
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_created/realm_created.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_created/realm_created.py
new file mode 100644
index 0000000..2a86adec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_created/realm_created.py
@@ -0,0 +1,222 @@
+import pytest
+from tests.support.sync import AsyncPoll
+
+from webdriver.bidi.modules.script import RealmTarget
+from webdriver.error import TimeoutException
+from .. import create_sandbox
+
+
+pytestmark = pytest.mark.asyncio
+
+REALM_CREATED_EVENT = "script.realmCreated"
+
+
+async def test_unsubscribe(bidi_session):
+    await bidi_session.session.subscribe(events=[REALM_CREATED_EVENT])
+    await bidi_session.session.unsubscribe(events=[REALM_CREATED_EVENT])
+
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(REALM_CREATED_EVENT, on_event)
+
+    await bidi_session.browsing_context.create(type_hint="tab")
+
+    assert len(events) == 0
+
+    remove_listener()
+
+
+@pytest.mark.parametrize("type_hint", ["window", "tab"])
+async def test_create_context(bidi_session, subscribe_events, type_hint):
+    await subscribe_events(events=[REALM_CREATED_EVENT])
+
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(REALM_CREATED_EVENT, on_event)
+
+    new_context = await bidi_session.browsing_context.create(type_hint=type_hint)
+
+    wait = AsyncPoll(bidi_session, message="Didn't receive realm created events")
+    await wait.until(lambda _: len(events) >= 1)
+
+    result = await bidi_session.script.get_realms(context=new_context["context"])
+
+    assert events[-1] == result[0]
+
+    remove_listener()
+
+
+async def test_navigate(bidi_session, subscribe_events, inline, new_tab):
+    await subscribe_events(events=[REALM_CREATED_EVENT])
+
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(REALM_CREATED_EVENT, on_event)
+
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=inline("<div>foo</div>"), wait="complete"
+    )
+
+    result = await bidi_session.script.get_realms(context=new_tab["context"])
+
+    assert events[-1] == result[0]
+
+    remove_listener()
+
+
+async def test_reload(bidi_session, subscribe_events, new_tab, inline):
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=inline("<div>foo</div>"), wait="complete"
+    )
+
+    await subscribe_events(events=[REALM_CREATED_EVENT])
+
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(REALM_CREATED_EVENT, on_event)
+
+    await bidi_session.browsing_context.reload(
+        context=new_tab["context"], wait="complete"
+    )
+
+    result = await bidi_session.script.get_realms(context=new_tab["context"])
+
+    assert events[-1] == result[0]
+
+    remove_listener()
+
+
+@pytest.mark.parametrize("method", ["evaluate", "call_function"])
+async def test_sandbox(
+    bidi_session, subscribe_events, new_tab, wait_for_event, test_origin, method
+):
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=test_origin, wait="complete"
+    )
+    await subscribe_events(events=[REALM_CREATED_EVENT])
+
+    on_realm_created = wait_for_event(REALM_CREATED_EVENT)
+
+    sandbox_name = "Test"
+    sandbox_realm = await create_sandbox(
+        bidi_session, new_tab["context"], sandbox_name, method
+    )
+
+    event = await on_realm_created
+
+    assert event == {
+        "context": new_tab["context"],
+        "origin": test_origin,
+        "realm": sandbox_realm,
+        "sandbox": sandbox_name,
+        "type": "window",
+    }
+
+
+@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"])
+async def test_iframe(bidi_session, subscribe_events, top_context, inline, domain):
+    await subscribe_events(events=[REALM_CREATED_EVENT])
+
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(REALM_CREATED_EVENT, on_event)
+
+    frame_url = inline("<div>foo</div>")
+    url = inline(f"<iframe src='{frame_url}'></iframe>", domain=domain)
+    await bidi_session.browsing_context.navigate(
+        url=url, context=top_context["context"], wait="complete"
+    )
+
+    realms = await bidi_session.script.get_realms()
+
+    for realm in realms:
+        # Find the relevant event for the specific realm
+        event = [item for item in events if item["realm"] == realm["realm"]]
+        assert event[0] == realm
+
+    remove_listener()
+
+
+async def test_subscribe_to_one_context(
+    bidi_session, subscribe_events, new_tab, inline, top_context
+):
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=inline("<div>foo</div>"), wait="complete"
+    )
+
+    # Subscribe to a specific context
+    await subscribe_events(events=[REALM_CREATED_EVENT], contexts=[new_tab["context"]])
+
+    events = []
+
+    async def on_event(method, data):
+        events.append(data)
+
+    remove_listener = bidi_session.add_event_listener(REALM_CREATED_EVENT, on_event)
+
+    await bidi_session.browsing_context.navigate(
+        context=top_context["context"], url=inline("<div>foo</div>"), wait="complete"
+    )
+
+    # Make sure we didn't receive the event for the top context
+    wait = AsyncPoll(bidi_session, timeout=0.5)
+    with pytest.raises(TimeoutException):
+        await wait.until(lambda _: len(events) > 0)
+
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=inline("<div>foo</div>"), wait="complete"
+    )
+
+    result = await bidi_session.script.get_realms(context=new_tab["context"])
+
+    assert events[-1] == result[0]
+
+    remove_listener()
+
+
+@pytest.mark.parametrize("method", ["evaluate", "call_function"])
+async def test_script_when_realm_is_created(
+    bidi_session, subscribe_events, new_tab, wait_for_event, inline, method
+):
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=inline("<div>foo</div>"), wait="complete"
+    )
+    await subscribe_events(events=[REALM_CREATED_EVENT])
+
+    on_realm_created = wait_for_event(REALM_CREATED_EVENT)
+
+    await bidi_session.browsing_context.reload(context=new_tab["context"])
+
+    realm_info = await on_realm_created
+
+    # Validate that it's possible to execute the script
+    # as soon as a realm is created.
+    if method == "evaluate":
+        result = await bidi_session.script.evaluate(
+            expression="1 + 2",
+            await_promise=False,
+            target=RealmTarget(realm_info["realm"]),
+        )
+    else:
+        result = await bidi_session.script.call_function(
+            function_declaration="() => 1 + 2",
+            await_promise=False,
+            target=RealmTarget(realm_info["realm"]),
+        )
+
+    assert result == {"type": "number", "value": 3}
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_destroyed/realm_destroyed.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_destroyed/realm_destroyed.py
index 2253b71..e3f4dc0a 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_destroyed/realm_destroyed.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/script/realm_destroyed/realm_destroyed.py
@@ -1,26 +1,15 @@
 import pytest
 from tests.support.sync import AsyncPoll
-
-from webdriver.bidi.modules.script import ContextTarget
 from webdriver.error import TimeoutException
 
+from .. import create_sandbox
+
 
 pytestmark = pytest.mark.asyncio
 
 REALM_DESTROYED_EVENT = "script.realmDestroyed"
 
 
-async def create_sandbox(bidi_session, context):
-    result = await bidi_session.script.evaluate(
-        raw_result=True,
-        expression="1 + 2",
-        await_promise=False,
-        target=ContextTarget(context, sandbox="test"),
-    )
-
-    return result["realm"]
-
-
 async def test_unsubscribe(bidi_session):
     new_context = await bidi_session.browsing_context.create(type_hint="tab")
     await bidi_session.session.subscribe(events=[REALM_DESTROYED_EVENT])
@@ -90,7 +79,8 @@
     assert event == {"realm": result[0]["realm"]}
 
 
-async def test_sandbox(bidi_session, subscribe_events, new_tab):
+@pytest.mark.parametrize("method", ["evaluate", "call_function"])
+async def test_sandbox(bidi_session, subscribe_events, new_tab, method):
     await subscribe_events(events=[REALM_DESTROYED_EVENT])
 
     # Track all received script.realmDestroyed events in the destroyed_realm_ids array
@@ -101,7 +91,9 @@
 
     remove_listener = bidi_session.add_event_listener(REALM_DESTROYED_EVENT, on_event)
 
-    sandbox_realm = await create_sandbox(bidi_session, new_tab["context"])
+    sandbox_realm = await create_sandbox(
+        bidi_session, new_tab["context"], "test", method
+    )
 
     await bidi_session.browsing_context.close(context=new_tab["context"])
 
diff --git a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_create_move.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_create_move.https.html.ini
index 488fb73..c7e8abe 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_create_move.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_create_move.https.html.ini
@@ -1,8 +1,10 @@
 [ar_anchor_freefloating_create_move.https.html]
   [Ensures free-floating anchor move gets propagated to anchor poses - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures free-floating anchor move gets propagated to anchor poses - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_delay_creation.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_delay_creation.https.html.ini
index 7c6d5c4..3551180 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_delay_creation.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_delay_creation.https.html.ini
@@ -1,16 +1,20 @@
 [ar_anchor_freefloating_delay_creation.https.html]
   [Ensures free-floating anchor creation with delayed failure is handled correctly - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures free-floating anchor creation with delayed failure is handled correctly - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures free-floating anchor creation with delayed success is handled correctly - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures free-floating anchor creation with delayed success is handled correctly - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_failure.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_failure.https.html.ini
index bdc823e..b37def3 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_failure.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_failure.https.html.ini
@@ -1,8 +1,10 @@
 [ar_anchor_freefloating_failure.https.html]
   [Ensures free-floating anchor creation failure is handled correctly - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures free-floating anchor creation failure is handled correctly - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_pause_resume_stop.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_pause_resume_stop.https.html.ini
index a999adb..f53d912 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_pause_resume_stop.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_freefloating_pause_resume_stop.https.html.ini
@@ -1,8 +1,10 @@
 [ar_anchor_freefloating_pause_resume_stop.https.html]
   [Ensures free-floating anchor state changes get propagated - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures free-floating anchor state changes get propagated - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_getAnchors.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_getAnchors.https.html.ini
index be625d3..a9e02b8 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_getAnchors.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_getAnchors.https.html.ini
@@ -1,16 +1,20 @@
 [ar_anchor_getAnchors.https.html]
   [XRFrame's trackedAnchors is empty when the feature was not requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame's trackedAnchors is empty when the feature was not requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame's trackedAnchors is empty when the feature was requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame's trackedAnchors is empty when the feature was requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_states.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_states.https.html.ini
index 1609571b..3cf1160 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_states.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/anchors/ar_anchor_states.https.html.ini
@@ -1,24 +1,30 @@
 [ar_anchor_states.https.html]
   [Anchor creation fails if the feature was not requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Anchor creation fails if the feature was not requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Anchor creation fails if the feature was requested but the session already ended - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Anchor creation fails if the feature was requested but the session already ended - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Anchor creation succeeds if the feature was requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Anchor creation succeeds if the feature was requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrDevice_requestSession_immersive-ar.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrDevice_requestSession_immersive-ar.https.html.ini
index 064e841..5498ba0 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrDevice_requestSession_immersive-ar.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrDevice_requestSession_immersive-ar.https.html.ini
@@ -1,8 +1,10 @@
 [xrDevice_requestSession_immersive-ar.https.html]
   [Tests requestSession accepts immersive-ar mode - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession accepts immersive-ar mode - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_environmentBlendMode.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_environmentBlendMode.https.html.ini
index 3d33435..9d318102 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_environmentBlendMode.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_environmentBlendMode.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_environmentBlendMode.https.html]
   [Tests environmentBlendMode for a VR device - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests environmentBlendMode for a VR device - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests environmentBlendMode for an AR device - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests environmentBlendMode for an AR device - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_interactionMode.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_interactionMode.https.html.ini
index 7615a6a1..ad282d0 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_interactionMode.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_interactionMode.https.html.ini
@@ -1,40 +1,50 @@
 [xrSession_interactionMode.https.html]
   [Tests interactionMode for a INLINE_SCREEN_DEVICE - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for a INLINE_SCREEN_DEVICE - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for an AR_HMD_DEVICE - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for an AR_HMD_DEVICE - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for an AR_SCREEN_DEVICE - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for an AR_SCREEN_DEVICE - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for an VR_HMD_DEVICE - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for an VR_HMD_DEVICE - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for an VR_SCREEN_DEVICE - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests interactionMode for an VR_SCREEN_DEVICE - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/camera-access/xrCamera_resolution.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/camera-access/xrCamera_resolution.https.html.ini
index d29460f5..9271f9f 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/camera-access/xrCamera_resolution.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/camera-access/xrCamera_resolution.https.html.ini
@@ -1,8 +1,10 @@
 [xrCamera_resolution.https.html]
   [XRCamera object is present and carries expected dimensions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRCamera object is present and carries expected dimensions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_dataUnavailable.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_dataUnavailable.https.html.ini
index 32eb9074..476288c 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_dataUnavailable.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_dataUnavailable.https.html.ini
@@ -1,8 +1,10 @@
 [depth_sensing_cpu_dataUnavailable.https.html]
   [Ensures depth data is not available when cleared in the controller, `cpu-optimized` - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures depth data is not available when cleared in the controller, `cpu-optimized` - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_inactiveFrame.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_inactiveFrame.https.html.ini
index 088d4ec4..1fab590 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_inactiveFrame.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_inactiveFrame.https.html.ini
@@ -1,8 +1,10 @@
 [depth_sensing_cpu_inactiveFrame.https.html]
   [Ensures getDepthInformation() throws when not run in an active frame, `cpu-optimized` - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures getDepthInformation() throws when not run in an active frame, `cpu-optimized` - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_incorrectUsage.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_incorrectUsage.https.html.ini
index 5e9bef5d..0d741171 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_incorrectUsage.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_incorrectUsage.https.html.ini
@@ -1,8 +1,10 @@
 [depth_sensing_cpu_incorrectUsage.https.html]
   [Ensures XRWebGLDepthInformation is not obtainable in `cpu-optimized` usage mode - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures XRWebGLDepthInformation is not obtainable in `cpu-optimized` usage mode - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_luminance_alpha_dataValid.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_luminance_alpha_dataValid.https.html.ini
index c31fe76..142a752 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_luminance_alpha_dataValid.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_luminance_alpha_dataValid.https.html.ini
@@ -1,8 +1,10 @@
 [depth_sensing_cpu_luminance_alpha_dataValid.https.html]
   [Ensures depth data is returned and values match expectation, cpu-optimized, luminance-alpha. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures depth data is returned and values match expectation, cpu-optimized, luminance-alpha. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_staleView.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_staleView.https.html.ini
index 5c3db41..55e05395 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_staleView.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/cpu/depth_sensing_cpu_staleView.https.html.ini
@@ -1,8 +1,10 @@
 [depth_sensing_cpu_staleView.https.html]
   [Ensures getDepthInformation() throws when run with stale XRView, `cpu-optimized` - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures getDepthInformation() throws when run with stale XRView, `cpu-optimized` - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/depth_sensing_notEnabled.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/depth_sensing_notEnabled.https.html.ini
index df2c30c..e1ea241 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/depth_sensing_notEnabled.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/depth-sensing/depth_sensing_notEnabled.https.html.ini
@@ -1,16 +1,20 @@
 [depth_sensing_notEnabled.https.html]
   [XRFrame.getDepthInformation() rejects if depth sensing is not enabled on a session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame.getDepthInformation() rejects if depth sensing is not enabled on a session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLBinding.getDepthInformation() rejects if depth sensing is not enabled on a session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLBinding.getDepthInformation() rejects if depth sensing is not enabled on a session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html.ini
index 24e59945..6c69183 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html.ini
@@ -4,37 +4,43 @@
     if product == "chrome": TIMEOUT
   [Ensures DOM Overlay Fullscreen API doesn't change DOM overlay - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
       if product == "chrome": NOTRUN
 
   [Ensures DOM Overlay Fullscreen API doesn't change DOM overlay - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
       if product == "chrome": NOTRUN
 
   [Ensures DOM Overlay feature works for immersive-ar, body element - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, TIMEOUT]
       if product == "chrome": TIMEOUT
 
   [Ensures DOM Overlay feature works for immersive-ar, body element - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
       if product == "chrome": NOTRUN
 
   [Ensures DOM Overlay feature works for immersive-ar, div element - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
       if product == "chrome": NOTRUN
 
   [Ensures DOM Overlay feature works for immersive-ar, div element - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
       if product == "chrome": NOTRUN
 
diff --git a/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay_hit_test.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay_hit_test.https.html.ini
index dd711ce..d111ced 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay_hit_test.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay_hit_test.https.html.ini
@@ -1,13 +1,16 @@
 [ar_dom_overlay_hit_test.https.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): OK
     TIMEOUT
   [Ensures DOM Overlay interactions on cross origin iframe do not cause hit test results to come up - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       TIMEOUT
 
   [Ensures DOM Overlay interactions on cross origin iframe do not cause hit test results to come up - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       NOTRUN
diff --git a/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/nested_fullscreen.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/nested_fullscreen.https.html.ini
index f65f4657..5213f32 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/nested_fullscreen.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/nested_fullscreen.https.html.ini
@@ -1,16 +1,20 @@
 [nested_fullscreen.https.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): OK
     TIMEOUT
   [Check XR session from fullscreen - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Check XR session from fullscreen - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [fullscreen setup]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): PASS
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): PASS
       TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/webxr/events_input_source_recreation.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/events_input_source_recreation.https.html.ini
index ad4f4ba..2c5a601 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/events_input_source_recreation.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/events_input_source_recreation.https.html.ini
@@ -1,8 +1,10 @@
 [events_input_source_recreation.https.html]
   [Input sources are re-created when handedness or target ray mode changes - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Input sources are re-created when handedness or target ray mode changes - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/events_input_sources_change.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/events_input_sources_change.https.html.ini
index ede519d..6bee0f6 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/events_input_sources_change.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/events_input_sources_change.https.html.ini
@@ -1,8 +1,10 @@
 [events_input_sources_change.https.html]
   [Transient input sources fire events in the right order - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Transient input sources fire events in the right order - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_immersive.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_immersive.https.html.ini
index 0dc7b85e..c8bbcb0 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_immersive.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_immersive.https.html.ini
@@ -1,8 +1,10 @@
 [events_referenceSpace_reset_immersive.https.html]
   [XRSession resetpose from a device properly fires off the right events for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession resetpose from a device properly fires off the right events for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_inline.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_inline.https.html.ini
index abf9cd2..702bd19 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_inline.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_inline.https.html.ini
@@ -1,15 +1,18 @@
 [events_referenceSpace_reset_inline.https.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): OK
     TIMEOUT
   [XRSession resetpose from a device properly fires off the right events for non-immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if product == "chrome": [PASS, TIMEOUT]
       TIMEOUT
 
   [XRSession resetpose from a device properly fires off the right events for non-immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if product == "chrome": [TIMEOUT, NOTRUN]
       NOTRUN
diff --git a/third_party/blink/web_tests/external/wpt/webxr/events_session_select.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/events_session_select.https.html.ini
index 7c9b1f5..0385b191 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/events_session_select.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/events_session_select.https.html.ini
@@ -1,8 +1,10 @@
 [events_session_select.https.html]
   [XRInputSources primary input presses properly fires off the right events - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRInputSources primary input presses properly fires off the right events - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/events_session_select_subframe.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/events_session_select_subframe.https.html.ini
index 9604fba..cd41f28 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/events_session_select_subframe.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/events_session_select_subframe.https.html.ini
@@ -1,8 +1,10 @@
 [events_session_select_subframe.https.html]
   [Ensures that an XRInputSources primary input being pressed and released in the space of a single frame properly fires off the right events - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures that an XRInputSources primary input being pressed and released in the space of a single frame properly fires off the right events - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/events_session_squeeze.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/events_session_squeeze.https.html.ini
index e5999c24..781e094 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/events_session_squeeze.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/events_session_squeeze.https.html.ini
@@ -1,8 +1,10 @@
 [events_session_squeeze.https.html]
   [XRInputSources primary input presses properly fires off the right events - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRInputSources primary input presses properly fires off the right events - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/exclusive_requestFrame_nolayer.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/exclusive_requestFrame_nolayer.https.html.ini
index c5c698f4..8319060 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/exclusive_requestFrame_nolayer.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/exclusive_requestFrame_nolayer.https.html.ini
@@ -1,16 +1,20 @@
 [exclusive_requestFrame_nolayer.https.html]
   [XRSession requestAnimationFrame must fail if the session has no baseLayer for immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame must fail if the session has no baseLayer for immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame must fail if the session has no baseLayer for non immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame must fail if the session has no baseLayer for non immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html.ini
index 6936c08a4..b0ceaf63 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html.ini
@@ -1,8 +1,10 @@
 [xrInputSource_gamepad_disconnect.https.html]
   [WebXR InputSource's gamepad gets disconnected when the input source is removed - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [WebXR InputSource's gamepad gets disconnected when the input source is removed - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html.ini
index 9f0ff91a..a302af80 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html.ini
@@ -1,8 +1,10 @@
 [xrInputSource_gamepad_input_registered.https.html]
   [WebXR InputSource's gamepad properly registers input - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [WebXR InputSource's gamepad properly registers input - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/getInputPose_handedness.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/getInputPose_handedness.https.html.ini
index a1195fa..bcd50f7 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/getInputPose_handedness.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/getInputPose_handedness.https.html.ini
@@ -1,8 +1,10 @@
 [getInputPose_handedness.https.html]
   [XRInputSources properly communicate their handedness - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRInputSources properly communicate their handedness - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/getInputPose_pointer.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/getInputPose_pointer.https.html.ini
index 91a596b..292e22d 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/getInputPose_pointer.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/getInputPose_pointer.https.html.ini
@@ -1,8 +1,10 @@
 [getInputPose_pointer.https.html]
   [XRInputSources with a target ray mode of 'tracked-pointer' properly communicate their poses - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRInputSources with a target ray mode of 'tracked-pointer' properly communicate their poses - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/getViewerPose_emulatedPosition.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/getViewerPose_emulatedPosition.https.html.ini
index a8c404e..61bccdc 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/getViewerPose_emulatedPosition.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/getViewerPose_emulatedPosition.https.html.ini
@@ -1,8 +1,10 @@
 [getViewerPose_emulatedPosition.https.html]
   [XRFrame getViewerPose has emulatedPosition set properly. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame getViewerPose has emulatedPosition set properly. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_source_cancel.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_source_cancel.https.html.ini
index b60d1688..6f9f8c1 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_source_cancel.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_source_cancel.https.html.ini
@@ -1,32 +1,40 @@
 [ar_hittest_source_cancel.https.html]
   [Ensures hit test source cancellation works when the session has ended - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures hit test source cancellation works when the session has ended - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures hit test source cancellation works when the session has not ended. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures hit test source cancellation works when the session has not ended. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures transient input hit test source cancellation works when the session has ended - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures transient input hit test source cancellation works when the session has ended - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures transient input hit test source cancellation works when the session has not ended. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures transient input hit test source cancellation works when the session has not ended. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_inputSources.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_inputSources.https.html.ini
index b22f501b..20aaa103 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_inputSources.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_inputSources.https.html.ini
@@ -1,24 +1,30 @@
 [ar_hittest_subscription_inputSources.https.html]
   [Ensures subscription to hit test works with an XRSpace from input source - after move - 1 result - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with an XRSpace from input source - after move - 1 result - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with an XRSpace from input source - after move - no results - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with an XRSpace from input source - after move - no results - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with an XRSpace from input source - no move - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with an XRSpace from input source - no move - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html.ini
index 9dbe67d..67ff0d0 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html.ini
@@ -1,32 +1,40 @@
 [ar_hittest_subscription_refSpaces.https.html]
   [Ensures subscription to hit test works with local space - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with local space - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with local-floor space - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with local-floor space - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with viewer space - straight ahead - plane - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with viewer space - straight ahead - plane - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with viewer space - straight up - no results - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to hit test works with viewer space - straight up - no results - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_states_regular.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_states_regular.https.html.ini
index d4af61d3..2b451a0 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_states_regular.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_states_regular.https.html.ini
@@ -1,24 +1,30 @@
 [ar_hittest_subscription_states_regular.https.html]
   [Hit test subscription fails if the feature was not requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Hit test subscription fails if the feature was not requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Hit test subscription fails if the feature was requested but the session already ended - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Hit test subscription fails if the feature was requested but the session already ended - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Hit test subscription succeeds if the feature was requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Hit test subscription succeeds if the feature was requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_states_transient.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_states_transient.https.html.ini
index 444feab..0e154a7 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_states_transient.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_states_transient.https.html.ini
@@ -1,24 +1,30 @@
 [ar_hittest_subscription_states_transient.https.html]
   [Transient hit test subscription fails if the feature was not requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Transient hit test subscription fails if the feature was not requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Transient hit test subscription succeeds if the feature was requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Transient hit test subscription succeeds if the feature was requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Transient test subscription fails if the feature was requested but the session already ended - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Transient test subscription fails if the feature was requested but the session already ended - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html.ini
index cfb29f5..a2c214c 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html.ini
@@ -1,24 +1,30 @@
 [ar_hittest_subscription_transientInputSources.https.html]
   [Ensures subscription to transient hit test works with an XRSpace from input source - after move - 1 result - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to transient hit test works with an XRSpace from input source - after move - 1 result - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to transient hit test works with an XRSpace from input source - after move - no results - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to transient hit test works with an XRSpace from input source - after move - no results - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to transient hit test works with an XRSpace from input source - no move - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures subscription to transient hit test works with an XRSpace from input source - no move - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_unlocalizable.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_unlocalizable.https.html.ini
index e0cf12bb..f08b3e7 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_unlocalizable.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/hit-test/ar_hittest_subscription_unlocalizable.https.html.ini
@@ -1,8 +1,10 @@
 [ar_hittest_subscription_unlocalizable.https.html]
   [Ensures hit test result returns null pose w/unlocalizable space - viewer space - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures hit test result returns null pose w/unlocalizable space - viewer space - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window.js.ini b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window.js.ini
index a55bd8a..58e35503 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window.js.ini
@@ -1,14 +1,16 @@
 [idlharness.https.window.html]
   [Stringification of xrWebGLLayer]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [WebGLRenderingContext includes WebGLRenderingContextOverloads: member names are unique]
     expected: FAIL
 
   [WebGLRenderingContextBase interface: webGLRenderingContextBase must inherit property "makeXRCompatible()" with the proper type]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame interface: attribute predictedDisplayTime]
     expected: FAIL
@@ -45,47 +47,58 @@
 
   [XRWebGLLayer interface: calling getNativeFramebufferScaleFactor(XRSession) on xrWebGLLayer with too few arguments must throw TypeError]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer interface: calling getViewport(XRView) on xrWebGLLayer with too few arguments must throw TypeError]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer interface: xrWebGLLayer must inherit property "antialias" with the proper type]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer interface: xrWebGLLayer must inherit property "fixedFoveation" with the proper type]
     expected: FAIL
 
   [XRWebGLLayer interface: xrWebGLLayer must inherit property "framebuffer" with the proper type]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer interface: xrWebGLLayer must inherit property "framebufferHeight" with the proper type]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer interface: xrWebGLLayer must inherit property "framebufferWidth" with the proper type]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer interface: xrWebGLLayer must inherit property "getNativeFramebufferScaleFactor(XRSession)" with the proper type]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer interface: xrWebGLLayer must inherit property "getViewport(XRView)" with the proper type]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer interface: xrWebGLLayer must inherit property "ignoreDepthValues" with the proper type]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer must be primary interface of xrWebGLLayer]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [idl_test setup]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/layers/xrSession_updateRenderState.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/layers/xrSession_updateRenderState.https.html.ini
index 88bb4d7..b94d877 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/layers/xrSession_updateRenderState.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/layers/xrSession_updateRenderState.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_updateRenderState.https.html]
   [Ensure XRSession throws appropriate errors when updating render state with layers feature enabled - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure XRSession throws appropriate errors when updating render state with layers feature enabled - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure XRSession throws appropriate errors when updating render state without layers feature enabled - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure XRSession throws appropriate errors when updating render state without layers feature enabled - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/layers/xrWebGLBinding_constructor.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/layers/xrWebGLBinding_constructor.https.html.ini
index c957c47c6..e55aad9 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/layers/xrWebGLBinding_constructor.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/layers/xrWebGLBinding_constructor.https.html.ini
@@ -1,8 +1,10 @@
 [xrWebGLBinding_constructor.https.html]
   [Ensure that XRWebGLBinding's constructor throws appropriate errors using webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure that XRWebGLBinding's constructor throws appropriate errors using webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_oldSession.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_oldSession.https.html.ini
index c2ad2ba..1b057eb 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_oldSession.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_oldSession.https.html.ini
@@ -1,8 +1,10 @@
 [xrFrame_getLightEstimate_oldSession.https.html]
   [getLightEstimate rejects if probe is from wrong session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [getLightEstimate rejects if probe is from wrong session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_staleFrame.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_staleFrame.https.html.ini
index 5001631..d581b78 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_staleFrame.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_staleFrame.https.html.ini
@@ -1,8 +1,10 @@
 [xrFrame_getLightEstimate_staleFrame.https.html]
   [Cannot get XrLightEstimate from stale frame - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Cannot get XrLightEstimate from stale frame - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_valid.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_valid.https.html.ini
index c4a9659..4216dd1 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_valid.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrFrame_getLightEstimate_valid.https.html.ini
@@ -1,8 +1,10 @@
 [xrFrame_getLightEstimate_valid.https.html]
   [Can get XRLightEstimates during frame - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Can get XRLightEstimates during frame - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_ended.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_ended.https.html.ini
index b8ef5bd5..44484f7 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_ended.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_ended.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_getLightProbe_ended.https.html]
   [getLightProbe rejects on an ended session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [getLightProbe rejects on an ended session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_notEnabled.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_notEnabled.https.html.ini
index 16f8d164..185f5aa 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_notEnabled.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_notEnabled.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_getLightProbe_notEnabled.https.html]
   [getLightProbe rejects if not enabled on session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [getLightProbe rejects if not enabled on session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_valid.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_valid.https.html.ini
index b308aa8..700f751 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_valid.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrSession_getLightProbe_valid.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_getLightProbe_valid.https.html]
   [Can create valid XRLightProbe objects - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Can create valid XRLightProbe objects - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrWebGLBinding_getReflectionCubeMap.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrWebGLBinding_getReflectionCubeMap.https.html.ini
index 50bfedb..fae907f 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrWebGLBinding_getReflectionCubeMap.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/light-estimation/xrWebGLBinding_getReflectionCubeMap.https.html.ini
@@ -1,8 +1,10 @@
 [xrWebGLBinding_getReflectionCubeMap.https.html]
   [Test that getReflectionCubeMap returns or throws appropriately without a reflection map. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Test that getReflectionCubeMap returns or throws appropriately without a reflection map. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_sameObject.https.html.ini
index 3038448..6d8ba9d 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [navigator_xr_sameObject.https.html]
   [Navigator.xr meets [SameObject\] requirement - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Navigator.xr meets [SameObject\] requirement - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/render_state_update.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/render_state_update.https.html.ini
index 1ac5bb4..7335b9e68 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/render_state_update.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/render_state_update.https.html.ini
@@ -1,40 +1,50 @@
 [render_state_update.https.html]
   [updateRenderState handles appropriately XRRenderStateInit params - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately XRRenderStateInit params - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately XRRenderStateInit with no params - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately XRRenderStateInit with no params - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately baseLayers created with different sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately baseLayers created with different sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately ended sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately ended sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately immersive sessions with specified inlineVerticalFieldOfView - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [updateRenderState handles appropriately immersive sessions with specified inlineVerticalFieldOfView - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/render_state_vertical_fov_immersive.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/render_state_vertical_fov_immersive.https.html.ini
index 81cd5b64..631798ce 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/render_state_vertical_fov_immersive.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/render_state_vertical_fov_immersive.https.html.ini
@@ -1,8 +1,10 @@
 [render_state_vertical_fov_immersive.https.html]
   [inlineVerticalFieldOfView is set appropriately on immersively sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [inlineVerticalFieldOfView is set appropriately on immersively sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/render_state_vertical_fov_inline.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/render_state_vertical_fov_inline.https.html.ini
index f12b719..2bd3420 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/render_state_vertical_fov_inline.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/render_state_vertical_fov_inline.https.html.ini
@@ -1,8 +1,10 @@
 [render_state_vertical_fov_inline.https.html]
   [inlineVerticalFieldOfView is set appropriately on inline sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [inlineVerticalFieldOfView is set appropriately on inline sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_create_xrcompatible.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_create_xrcompatible.https.html.ini
index f347e95..77254db6 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_create_xrcompatible.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_create_xrcompatible.https.html.ini
@@ -1,16 +1,20 @@
 [webGLCanvasContext_create_xrcompatible.https.html]
   [An XR-compatible webgl context can be created]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [An XR-compatible webgl2 context can be created]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Creating a webgl context with no device]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Creating a webgl2 context with no device]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_makecompatible_contextlost.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_makecompatible_contextlost.https.html.ini
index 029b42f..999ebad2 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_makecompatible_contextlost.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_makecompatible_contextlost.https.html.ini
@@ -1,8 +1,10 @@
 [webGLCanvasContext_makecompatible_contextlost.https.html]
   [A lost webgl context should not be able to set xr compatibility]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [A lost webgl2 context should not be able to set xr compatibility]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_makecompatible_reentrant.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_makecompatible_reentrant.https.html.ini
index 900b45b..0e3d96d 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_makecompatible_reentrant.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/webGLCanvasContext_makecompatible_reentrant.https.html.ini
@@ -1,16 +1,20 @@
 [webGLCanvasContext_makecompatible_reentrant.https.html]
   [Verify promise from a non-reentrant call to makeXRCompatible() is resolved for webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Verify promise from a non-reentrant call to makeXRCompatible() is resolved for webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Verify promises from reentrant calls to makeXRCompatible() are resolved for webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Verify promises from reentrant calls to makeXRCompatible() are resolved for webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/webxr_permissions_policy.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/webxr_permissions_policy.https.html.ini
index 65f4435..eec7b36d 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/webxr_permissions_policy.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/webxr_permissions_policy.https.html.ini
@@ -1,4 +1,5 @@
 [webxr_permissions_policy.https.html]
   [Validate xr compatibility requests without xr-spatial-tracking policy]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrBoundedReferenceSpace_updates.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrBoundedReferenceSpace_updates.https.html.ini
index 9db6588..da4b4c7 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrBoundedReferenceSpace_updates.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrBoundedReferenceSpace_updates.https.html.ini
@@ -1,8 +1,10 @@
 [xrBoundedReferenceSpace_updates.https.html]
   ['XRBoundedReferenceSpace updates properly when the changes are applied - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   ['XRBoundedReferenceSpace updates properly when the changes are applied - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_disconnect_ends.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_disconnect_ends.https.html.ini
index fc2dbaba..77e2fbf 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_disconnect_ends.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_disconnect_ends.https.html.ini
@@ -1,8 +1,10 @@
 [xrDevice_disconnect_ends.https.html]
   [Immersive session ends when device is disconnected - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Immersive session ends when device is disconnected - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html.ini
index b64e56f..838c13a 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html.ini
@@ -1,24 +1,30 @@
 [xrDevice_requestSession_immersive.https.html]
   [Tests requestSession accepts XRSessionInit dictionary - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession accepts XRSessionInit dictionary - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession ignores unknown optionalFeatures - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession ignores unknown optionalFeatures - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession resolves when supported - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession resolves when supported - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_optionalFeatures.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_optionalFeatures.https.html.ini
index 5648c0a..768f6f6 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_optionalFeatures.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_optionalFeatures.https.html.ini
@@ -1,32 +1,40 @@
 [xrDevice_requestSession_optionalFeatures.https.html]
   [Tests requestSession accepts XRSessionInit dictionary - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession accepts XRSessionInit dictionary - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession accepts XRSessionInit dictionary with empty feature lists - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession accepts XRSessionInit dictionary with empty feature lists - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession ignores unknown objects in optionalFeatures - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession ignores unknown objects in optionalFeatures - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession ignores unknown strings in optionalFeatures - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Tests requestSession ignores unknown strings in optionalFeatures - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html.ini
index 9070199..9a55617 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html.ini
@@ -1,16 +1,20 @@
 [xrFrame_getPose.https.html]
   [XRFrame.getPose works for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame.getPose works for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame.getPose works for non-immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame.getPose works for non-immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getViewerPose_getPose.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getViewerPose_getPose.https.html.ini
index 54ae2a29..cf749793 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getViewerPose_getPose.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getViewerPose_getPose.https.html.ini
@@ -1,8 +1,10 @@
 [xrFrame_getViewerPose_getPose.https.html]
   [XRFrame getViewerPose(refSpace) matches getPose(viewer, refSpace). - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame getViewerPose(refSpace) matches getPose(viewer, refSpace). - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getViewerPose_getPose_identities.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getViewerPose_getPose_identities.https.html.ini
index 375c7c9..3f8dcf8 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getViewerPose_getPose_identities.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getViewerPose_getPose_identities.https.html.ini
@@ -1,8 +1,10 @@
 [xrFrame_getViewerPose_getPose_identities.https.html]
   [XRFrame getViewerPose(viewerSpace) & getPose(space, space) return identity even during tracking loss - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame getViewerPose(viewerSpace) & getPose(space, space) return identity even during tracking loss - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html.ini
index ccb30f87..5220baf6 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_lifetime.https.html.ini
@@ -1,16 +1,20 @@
 [xrFrame_lifetime.https.html]
   [XRFrame methods throw exceptions outside of the requestAnimationFrame callback for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame methods throw exceptions outside of the requestAnimationFrame callback for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame methods throw exceptions outside of the requestAnimationFrame callback for non-immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame methods throw exceptions outside of the requestAnimationFrame callback for non-immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_session_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_session_sameObject.https.html.ini
index 95f42826c..cfbd9eb 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_session_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_session_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [xrFrame_session_sameObject.https.html]
   [XRFrame.session meets [SameObject\] requirement - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame.session meets [SameObject\] requirement - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_add_remove.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_add_remove.https.html.ini
index 7302871..e371762 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_add_remove.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_add_remove.https.html.ini
@@ -1,8 +1,10 @@
 [xrInputSource_add_remove.https.html]
   [XRInputSources can be properly added and removed from the session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRInputSources can be properly added and removed from the session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_emulatedPosition.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_emulatedPosition.https.html.ini
index 78f8a38..513c621d 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_emulatedPosition.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_emulatedPosition.https.html.ini
@@ -1,8 +1,10 @@
 [xrInputSource_emulatedPosition.https.html]
   [Poses from XRInputSource.gripSpace have emulatedPosition set properly - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Poses from XRInputSource.gripSpace have emulatedPosition set properly - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_getPose_targetRay_grip.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_getPose_targetRay_grip.https.html.ini
index bc6eec8..a224c9d 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_getPose_targetRay_grip.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_getPose_targetRay_grip.https.html.ini
@@ -1,8 +1,10 @@
 [xrInputSource_getPose_targetRay_grip.https.html]
   [Poses between targetRaySpace and gripSpace can be obtained and behave correctly - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Poses between targetRaySpace and gripSpace can be obtained and behave correctly - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_profiles.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_profiles.https.html.ini
index e724f564..14377f9 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_profiles.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_profiles.https.html.ini
@@ -1,8 +1,10 @@
 [xrInputSource_profiles.https.html]
   [WebXR InputSource's profiles list can be set - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [WebXR InputSource's profiles list can be set - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_sameObject.https.html.ini
index 507870a54..48db13cc 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrInputSource_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [xrInputSource_sameObject.https.html]
   [XRInputSource attributes meet [SameObject\] requirement - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRInputSource attributes meet [SameObject\] requirement - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrPose_transform_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrPose_transform_sameObject.https.html.ini
index a8ffd667..d6e84deb 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrPose_transform_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrPose_transform_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [xrPose_transform_sameObject.https.html]
   [XRPose.transform meets [SameObject\] requirement - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRPose.transform meets [SameObject\] requirement - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset.https.html.ini
index 9507cd5..c909550 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset.https.html.ini
@@ -1,8 +1,10 @@
 [xrReferenceSpace_originOffset.https.html]
   [Updating XRReferenceSpace origin offset updates view and input matrices. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Updating XRReferenceSpace origin offset updates view and input matrices. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffsetBounded.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffsetBounded.https.html.ini
index 6477b9e..5c8b175 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffsetBounded.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffsetBounded.https.html.ini
@@ -1,8 +1,10 @@
 [xrReferenceSpace_originOffsetBounded.https.html]
   [Updating XRBoundedReferenceSpace origin offset updates view, input matrices, and bounds geometry. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Updating XRBoundedReferenceSpace origin offset updates view, input matrices, and bounds geometry. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset_viewer.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset_viewer.https.html.ini
index b7d57916..0655b71 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset_viewer.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset_viewer.https.html.ini
@@ -1,8 +1,10 @@
 [xrReferenceSpace_originOffset_viewer.https.html]
   [Creating XRReferenceSpace origin offset off of `viewer` space works. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Creating XRReferenceSpace origin offset off of `viewer` space works. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_relationships.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_relationships.https.html.ini
index 0eb7585..23bd6a8f 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_relationships.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_relationships.https.html.ini
@@ -1,8 +1,10 @@
 [xrReferenceSpace_relationships.https.html]
   [Bounded space, viewer space, local and local-floor space have correct poses w.r.t. each other - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Bounded space, viewer space, local and local-floor space have correct poses w.r.t. each other - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https.html.ini
index acc1b992..66fef7e77 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_constructor.https.html.ini
@@ -1,8 +1,10 @@
 [xrRigidTransform_constructor.https.html]
   [XRRigidTransform constructor works - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRRigidTransform constructor works - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html.ini
index a1e73af9..62f82b5 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html.ini
@@ -1,8 +1,10 @@
 [xrRigidTransform_inverse.https.html]
   [XRRigidTransform inverse works - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRRigidTransform inverse works - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_sameObject.https.html.ini
index 2a26b31..2074a24 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [xrRigidTransform_sameObject.https.html]
   [XRRigidTransform position and orientation meet [SameObject\] requirements - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRRigidTransform position and orientation meet [SameObject\] requirements - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html.ini
index 376c78f..22b6764 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_cancelAnimationFrame.https.html]
   [XRSession requestAnimationFrame callbacks can be unregistered with cancelAnimationFrame for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame callbacks can be unregistered with cancelAnimationFrame for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame callbacks can be unregistered with cancelAnimationFrame for non-immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame callbacks can be unregistered with cancelAnimationFrame for non-immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html.ini
index 0f793a1f..57ad315 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_cancelAnimationFrame_invalidhandle.https.html]
   [XRSession cancelAnimationFrame does not have unexpected behavior when given invalid handles on immersive testSession - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession cancelAnimationFrame does not have unexpected behavior when given invalid handles on immersive testSession - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession cancelAnimationFrame does not have unexpected behavior when given invalid handles on non-immersive testSession - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession cancelAnimationFrame does not have unexpected behavior when given invalid handles on non-immersive testSession - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_enabledFeatures.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_enabledFeatures.https.html.ini
index f27edb3f..7b77e93 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_enabledFeatures.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_enabledFeatures.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_enabledFeatures.https.html]
   [Validate enabledFeatures on XRSession - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Validate enabledFeatures on XRSession - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html.ini
index fba913c..d554603 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_end.https.html]
   [end event fires when immersive session ends - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [end event fires when immersive session ends - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [end event fires when non-immersive session ends - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [end event fires when non-immersive session ends - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_input_events_end.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_input_events_end.https.html.ini
index af0c3b9..47dbdae 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_input_events_end.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_input_events_end.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_input_events_end.https.html]
   [Calling end during an input callback stops processing at the right time - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Calling end during an input callback stops processing at the right time - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html.ini
index fe514f5d..7811d411 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_requestAnimationFrame_callback_calls.https.html]
   [XRSession requestAnimationFrame calls the provided callback a non-immersive session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame calls the provided callback a non-immersive session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame calls the provided callback for an immersive session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession requestAnimationFrame calls the provided callback for an immersive session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html.ini
index a59fbfd..2dc844f4 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_requestAnimationFrame_data_valid.https.html]
   [RequestAnimationFrame resolves with good data - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [RequestAnimationFrame resolves with good data - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html.ini
index 3bbcc415..465544e 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html.ini
@@ -1,15 +1,18 @@
 [xrSession_requestAnimationFrame_getViewerPose.https.html]
   [XRFrame getViewerPose updates on the next frame for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame getViewerPose updates on the next frame for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame getViewerPose updates on the next frame for non-immersive sessions - webgl]
     expected: FAIL
 
   [XRFrame getViewerPose updates on the next frame for non-immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_timestamp.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_timestamp.https.html.ini
index 786c841a..d871fc6f 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_timestamp.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_timestamp.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_requestAnimationFrame_timestamp.https.html]
   [XRFrame getViewerPose updates on the next frame for immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame getViewerPose updates on the next frame for immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame getViewerPose updates on the next frame for non-immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame getViewerPose updates on the next frame for non-immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html.ini
index 4705cc6..1a0435c60 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_requestReferenceSpace.https.html]
   [Immersive XRSession requestReferenceSpace returns expected objects - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Immersive XRSession requestReferenceSpace returns expected objects - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Non-immersive XRSession requestReferenceSpace returns expected objects - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Non-immersive XRSession requestReferenceSpace returns expected objects - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html.ini
index 9751f3d..61c83c11 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html.ini
@@ -3,117 +3,141 @@
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): TIMEOUT
   [Immersive session rejects local-floor space if not requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Immersive session rejects local-floor space if not requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Immersive session supports local space by default - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Immersive session supports local space by default - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Immersive session supports local-floor space when optional - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Immersive session supports local-floor space when optional - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Immersive session supports local-floor space when required - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Immersive session supports local-floor space when required - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Immersive session supports viewer space by default - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Immersive session supports viewer space by default - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session rejects bounded-floor space even when requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session rejects bounded-floor space even when requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session rejects local space if not requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session rejects local space if not requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session rejects unbounded space even when requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session rejects unbounded space even when requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session supports local space when optional - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session supports local space when optional - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session supports local space when required - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session supports local space when required - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session supports local-floor space when required - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session supports local-floor space when required - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session supports viewer space by default - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
 
   [Non-immersive session supports viewer space by default - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): [FAIL, PASS]
       [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestSessionDuringEnd.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestSessionDuringEnd.https.html.ini
index a8d4058..dd14d683c 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestSessionDuringEnd.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestSessionDuringEnd.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_requestSessionDuringEnd.https.html]
   [Create mew session in end promise - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Create mew session in end promise - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Create new session in OnSessionEnded event - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Create new session in OnSessionEnded event - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_sameObject.https.html.ini
index 808a21f..d58ebdb 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_sameObject.https.html]
   [XRSession attributes meet [SameObject\] requirement - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRSession attributes meet [SameObject\] requirement - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_viewer_referenceSpace.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_viewer_referenceSpace.https.html.ini
index 104789b..127e15b 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_viewer_referenceSpace.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_viewer_referenceSpace.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_viewer_referenceSpace.https.html]
   [Identity reference space provides correct poses for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Identity reference space provides correct poses for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Identity reference space provides correct poses for inline sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Identity reference space provides correct poses for inline sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_visibilityState.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_visibilityState.https.html.ini
index 22160e1..31db7db 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_visibilityState.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_visibilityState.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_visibilityState.https.html]
   [Ensures that the XRSession's visibilityState is correctly reported and that the associated visibilitychange event fires. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures that the XRSession's visibilityState is correctly reported and that the associated visibilitychange event fires. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html.ini
index 29681fe0..99e3b35 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html.ini
@@ -1,16 +1,20 @@
 [xrStationaryReferenceSpace_floorlevel_updates.https.html]
   ['floor-level' XRStationaryReferenceSpace updates properly when the transform changes for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   ['floor-level' XRStationaryReferenceSpace updates properly when the transform changes for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   ['floor-level' XRStationaryReferenceSpace updates properly when the transform changes for non-immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   ['floor-level' XRStationaryReferenceSpace updates properly when the transform changes for non-immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrView_eyes.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrView_eyes.https.html.ini
index 0c60b77d..b5a197d 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrView_eyes.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrView_eyes.https.html.ini
@@ -1,16 +1,20 @@
 [xrView_eyes.https.html]
   [XRView.eye is correct for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRView.eye is correct for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRView.eye is correct for non-immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRView.eye is correct for non-immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrView_match.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrView_match.https.html.ini
index c3baeb69..0505f42c 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrView_match.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrView_match.https.html.ini
@@ -1,8 +1,10 @@
 [xrView_match.https.html]
   [XRFrame contains the expected views - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame contains the expected views - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrView_oneframeupdate.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrView_oneframeupdate.https.html.ini
index ba20722..3b79c59 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrView_oneframeupdate.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrView_oneframeupdate.https.html.ini
@@ -1,8 +1,10 @@
 [xrView_oneframeupdate.https.html]
   [XRView projection matrices update near and far depths on the next frame - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRView projection matrices update near and far depths on the next frame - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrView_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrView_sameObject.https.html.ini
index 069955f..40ab9df8 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrView_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrView_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [xrView_sameObject.https.html]
   [XRView attributes meet [SameObject\] requirement - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRView attributes meet [SameObject\] requirement - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrViewerPose_secondaryViews.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrViewerPose_secondaryViews.https.html.ini
index 7b2beeb..3f1d1eb 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrViewerPose_secondaryViews.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrViewerPose_secondaryViews.https.html.ini
@@ -1,32 +1,40 @@
 [xrViewerPose_secondaryViews.https.html]
   [Only primary views are returned if secondary views are not requested for immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Only primary views are returned if secondary views are not requested for immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Only primary views are returned if secondary views are not requested for non-immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Only primary views are returned if secondary views are not requested for non-immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Requesting secondary views only returns primary views for non-immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Requesting secondary views only returns primary views for non-immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Requesting secondary views returns both primary and secondary views for immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Requesting secondary views returns both primary and secondary views for immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrViewerPose_views_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrViewerPose_views_sameObject.https.html.ini
index c72689e..2aa5643 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrViewerPose_views_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrViewerPose_views_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [xrViewerPose_views_sameObject.https.html]
   [XRViewerPose.views meets [SameObject\] requirement - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRViewerPose.views meets [SameObject\] requirement - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrViewport_valid.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrViewport_valid.https.html.ini
index 4022805aa..66cccc7 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrViewport_valid.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrViewport_valid.https.html.ini
@@ -1,16 +1,20 @@
 [xrViewport_valid.https.html]
   [XRViewport attributes are valid - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRViewport attributes are valid - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRViewport attributes are valid with secondary views requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRViewport attributes are valid with secondary views requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_constructor.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_constructor.https.html.ini
index 52f9a21a..7c660ed 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_constructor.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_constructor.https.html.ini
@@ -1,8 +1,10 @@
 [xrWebGLLayer_constructor.https.html]
   [Ensure that XRWebGLLayer's constructor throws appropriate errors using webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure that XRWebGLLayer's constructor throws appropriate errors using webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_draw.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_draw.https.html.ini
index bee5ddc..4d478f8 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_draw.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_draw.https.html.ini
@@ -1,8 +1,10 @@
 [xrWebGLLayer_framebuffer_draw.https.html]
   [Ensure a WebGL layer's framebuffer can only be drawn to inside a XR frame - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure a WebGL layer's framebuffer can only be drawn to inside a XR frame - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_sameObject.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_sameObject.https.html.ini
index 827b02ad..5a98088 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_sameObject.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_sameObject.https.html.ini
@@ -1,8 +1,10 @@
 [xrWebGLLayer_framebuffer_sameObject.https.html]
   [XRWebGLLayer.framebuffer meets [SameObject\] requirement - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer.framebuffer meets [SameObject\] requirement - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_scale.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_scale.https.html.ini
index d92e419e..4d27b9b3 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_scale.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_framebuffer_scale.https.html.ini
@@ -1,8 +1,10 @@
 [xrWebGLLayer_framebuffer_scale.https.html]
   [Ensure framebuffer scaling works as expected. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure framebuffer scaling works as expected. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_opaque_framebuffer.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_opaque_framebuffer.https.html.ini
index 308b903..f6639afa 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_opaque_framebuffer.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_opaque_framebuffer.https.html.ini
@@ -1,16 +1,20 @@
 [xrWebGLLayer_opaque_framebuffer.https.html]
   [Ensure that the framebuffer given by the WebGL layer is opaque for immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure that the framebuffer given by the WebGL layer is opaque for immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure that the framebuffer given by the WebGL layer is opaque for non-immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure that the framebuffer given by the WebGL layer is opaque for non-immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html.ini
index 61d6a44..5d848bd 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html.ini
@@ -1,8 +1,10 @@
 [xrWebGLLayer_opaque_framebuffer_stencil.https.html]
   [Ensure that the framebuffer given by the WebGL layer works with stencil for immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure that the framebuffer given by the WebGL layer works with stencil for immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_viewports.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_viewports.https.html.ini
index 865f306..0e1f454 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_viewports.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrWebGLLayer_viewports.https.html.ini
@@ -1,32 +1,40 @@
 [xrWebGLLayer_viewports.https.html]
   [XRWebGLLayer reports a valid viewports for immersive sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer reports a valid viewports for immersive sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer reports a valid viewports for immersive sessions with secondary views requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer reports a valid viewports for immersive sessions with secondary views requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer reports a valid viewports for inline sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer reports a valid viewports for inline sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer reports a valid viewports for inline sessions with secondary views requested - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRWebGLLayer reports a valid viewports for inline sessions with secondary views requested - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xr_viewport_scale.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xr_viewport_scale.https.html.ini
index cb84b0ee5d..e0a0aa0 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xr_viewport_scale.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xr_viewport_scale.https.html.ini
@@ -1,142 +1,167 @@
 [xr_viewport_scale.https.html]
   expected:
-    if (product == "content_shell") and (os == "win") and (port == "win11"): OK
     if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [OK, TIMEOUT]
     if (product == "content_shell") and (os == "mac") and (port == "mac13"): TIMEOUT
-    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac12"): [TIMEOUT, OK]
+    if (product == "content_shell") and (os == "mac") and (port == "mac11"): [TIMEOUT, OK]
+    if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): [TIMEOUT, OK]
     if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [OK, TIMEOUT]
-    if (product == "content_shell") and (os == "linux") and (flag_specific == ""): OK
-    [TIMEOUT, OK]
+    if product == "chrome": [TIMEOUT, OK]
   [recommendedViewportScale for immersive-vr session - webgl]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [NOTRUN, TIMEOUT, PRECONDITION_FAILED]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if product == "chrome": [NOTRUN, TIMEOUT, PRECONDITION_FAILED]
       PRECONDITION_FAILED
 
   [recommendedViewportScale for immersive-vr session - webgl2]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [TIMEOUT, PRECONDITION_FAILED, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if product == "chrome": [TIMEOUT, NOTRUN, PRECONDITION_FAILED]
       PRECONDITION_FAILED
 
   [recommendedViewportScale for inline session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       PRECONDITION_FAILED
 
   [recommendedViewportScale for inline session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       PRECONDITION_FAILED
 
   [requestViewportScale applied next frame for immersive-vr session - webgl]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if product == "chrome": [PASS, NOTRUN]
 
   [requestViewportScale applied next frame for immersive-vr session - webgl2]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, TIMEOUT, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if product == "chrome": [PASS, TIMEOUT, NOTRUN]
 
   [requestViewportScale applied next frame for inline session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       PRECONDITION_FAILED
 
   [requestViewportScale applied next frame for inline session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       PRECONDITION_FAILED
 
   [requestViewportScale same frame for immersive-vr session - webgl]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if product == "chrome": [PASS, NOTRUN]
 
   [requestViewportScale same frame for immersive-vr session - webgl2]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if product == "chrome": [PASS, NOTRUN]
 
   [requestViewportScale same frame for inline session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       PRECONDITION_FAILED
 
   [requestViewportScale same frame for inline session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       PRECONDITION_FAILED
 
   [requestViewportScale valid viewport for immersive-vr session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport for immersive-vr session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport for inline session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport for inline session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport w/ null scale for immersive-vr session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport w/ null scale for immersive-vr session - webgl2]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, TIMEOUT]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): [PASS, TIMEOUT]
       if product == "chrome": [PASS, TIMEOUT]
 
   [requestViewportScale valid viewport w/ null scale for inline session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport w/ null scale for inline session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport w/ undefined scale for immersive-vr session - webgl]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): [PASS, NOTRUN]
       if product == "chrome": [PASS, NOTRUN]
 
   [requestViewportScale valid viewport w/ undefined scale for immersive-vr session - webgl2]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): [PASS, NOTRUN]
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
       if product == "chrome": [PASS, NOTRUN]
 
   [requestViewportScale valid viewport w/ undefined scale for inline session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport w/ undefined scale for inline session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport w/ very small scale for immersive-vr session - webgl]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): [PASS, NOTRUN]
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
       if product == "chrome": [PASS, NOTRUN]
@@ -144,15 +169,18 @@
   [requestViewportScale valid viewport w/ very small scale for immersive-vr session - webgl2]
     expected:
       if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, NOTRUN]
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): [PASS, NOTRUN]
       if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
       if product == "chrome": [PASS, NOTRUN]
 
   [requestViewportScale valid viewport w/ very small scale for inline session - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [requestViewportScale valid viewport w/ very small scale for inline session - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/fast/dom/Range/surround-contents-font-face-crash-expected.txt b/third_party/blink/web_tests/fast/dom/Range/surround-contents-font-face-crash-expected.txt
index a8d3008..e7355db 100644
--- a/third_party/blink/web_tests/fast/dom/Range/surround-contents-font-face-crash-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Range/surround-contents-font-face-crash-expected.txt
@@ -1,5 +1,5 @@
 ALERT: PASS. WebKit didn't crash.
 This page contains the following errors:
-error on line 20 at column 10: Extra content at the end of the document
+error on line 21 at column 1: Premature end of data in tag font line 2
 
 Below is a rendering of the page up to the first error.
diff --git a/third_party/blink/web_tests/fast/dom/adopt-attribute-crash-expected.txt b/third_party/blink/web_tests/fast/dom/adopt-attribute-crash-expected.txt
index 99a7940..694fb92 100644
--- a/third_party/blink/web_tests/fast/dom/adopt-attribute-crash-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/adopt-attribute-crash-expected.txt
@@ -1,5 +1,5 @@
 This page contains the following errors:
 error on line 3 at column 66: Namespaced Attribute href in 'http://www.w3.org/1999/xlink' redefined
-error on line 18 at column 1: Extra content at the end of the document
+error on line 18 at column 1: Premature end of data in tag html line 1
 
 Below is a rendering of the page up to the first error.
diff --git a/third_party/blink/web_tests/fast/encoding/invalid-xml-expected.txt b/third_party/blink/web_tests/fast/encoding/invalid-xml-expected.txt
index a4c0b0e..92a7593 100644
--- a/third_party/blink/web_tests/fast/encoding/invalid-xml-expected.txt
+++ b/third_party/blink/web_tests/fast/encoding/invalid-xml-expected.txt
@@ -8,7 +8,7 @@
 PASS iframe.contentDocument.documentElement.tagName is "root"
 PASS iframe.contentDocument.documentElement.getElementsByTagName('test').length < 1 is true
 Testing: invalid-xml-x-mac-thai.xml
-FAIL iframe.contentDocument.documentElement.tagName should be root. Was html.
+PASS iframe.contentDocument.documentElement.tagName is "root"
 PASS iframe.contentDocument.documentElement.getElementsByTagName('test').length < 1 is true
 PASS successfullyParsed is true
 
diff --git a/third_party/blink/web_tests/fast/xsl/xslt-mismatched-tags-in-xslt-expected.txt b/third_party/blink/web_tests/fast/xsl/xslt-mismatched-tags-in-xslt-expected.txt
index 709e50c..89444318 100644
--- a/third_party/blink/web_tests/fast/xsl/xslt-mismatched-tags-in-xslt-expected.txt
+++ b/third_party/blink/web_tests/fast/xsl/xslt-mismatched-tags-in-xslt-expected.txt
@@ -6,5 +6,3 @@
 
 CONSOLE ERROR: Opening and ending tag mismatch: template line 4 and stylesheet
 
-CONSOLE ERROR: Premature end of data in tag stylesheet line 2
-
diff --git a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-worklets.html b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-worklets.html
index 4c4ba36..c7a74eb 100644
--- a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-worklets.html
+++ b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-worklets.html
@@ -9,7 +9,7 @@
   function getAllPropertyNames(obj) {
     let props = Object.getOwnPropertyNames(obj);
     let proto = Object.getPrototypeOf(obj);
-    if (proto === Object.prototype) {
+    if (proto === Object.prototype || proto === null) {
       return props;
     }
     return [...props, ...getAllPropertyNames(proto)];
diff --git a/third_party/blink/web_tests/platform/linux/fast/invalid/junk-data-expected.png b/third_party/blink/web_tests/platform/linux/fast/invalid/junk-data-expected.png
index a8ebf61..7500c06 100644
--- a/third_party/blink/web_tests/platform/linux/fast/invalid/junk-data-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/invalid/junk-data-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/custom/bug45331-expected.png b/third_party/blink/web_tests/platform/linux/svg/custom/bug45331-expected.png
index f99c79d..543505b 100644
--- a/third_party/blink/web_tests/platform/linux/svg/custom/bug45331-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/custom/bug45331-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/custom/use-font-face-crash-expected.png b/third_party/blink/web_tests/platform/linux/svg/custom/use-font-face-crash-expected.png
index c0c7ce2d..e5f76887 100644
--- a/third_party/blink/web_tests/platform/linux/svg/custom/use-font-face-crash-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/custom/use-font-face-crash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-cascade/all-prop-revert-layer-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-cascade/all-prop-revert-layer-expected.txt
new file mode 100644
index 0000000..5b37deb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-cascade/all-prop-revert-layer-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+All subtests passed and are omitted for brevity.
+See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-masking/parsing/clip-path-valid-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-masking/parsing/clip-path-valid-expected.txt
new file mode 100644
index 0000000..5b37deb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-masking/parsing/clip-path-valid-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+All subtests passed and are omitted for brevity.
+See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details.
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/fast/invalid/junk-data-expected.png b/third_party/blink/web_tests/platform/mac/fast/invalid/junk-data-expected.png
index 40547ec..2b7dd97 100644
--- a/third_party/blink/web_tests/platform/mac/fast/invalid/junk-data-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/invalid/junk-data-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/custom/bug45331-expected.png b/third_party/blink/web_tests/platform/mac/svg/custom/bug45331-expected.png
index 49d120b6..52bce04 100644
--- a/third_party/blink/web_tests/platform/mac/svg/custom/bug45331-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/custom/bug45331-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/custom/use-font-face-crash-expected.png b/third_party/blink/web_tests/platform/mac/svg/custom/use-font-face-crash-expected.png
index f6e47f5..bc27d465 100644
--- a/third_party/blink/web_tests/platform/mac/svg/custom/use-font-face-crash-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/custom/use-font-face-crash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/invalid/junk-data-expected.png b/third_party/blink/web_tests/platform/win/fast/invalid/junk-data-expected.png
index da5bcb07..f228521 100644
--- a/third_party/blink/web_tests/platform/win/fast/invalid/junk-data-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/invalid/junk-data-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/custom/bug45331-expected.png b/third_party/blink/web_tests/platform/win/svg/custom/bug45331-expected.png
index 29aa7f6..b25a86a 100644
--- a/third_party/blink/web_tests/platform/win/svg/custom/bug45331-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/custom/bug45331-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/custom/use-font-face-crash-expected.png b/third_party/blink/web_tests/platform/win/svg/custom/use-font-face-crash-expected.png
index c458866..ebf3906 100644
--- a/third_party/blink/web_tests/platform/win/svg/custom/use-font-face-crash-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/custom/use-font-face-crash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/custom/bug78807-expected.txt b/third_party/blink/web_tests/svg/custom/bug78807-expected.txt
index 011869ae..e0b30c3f 100644
--- a/third_party/blink/web_tests/svg/custom/bug78807-expected.txt
+++ b/third_party/blink/web_tests/svg/custom/bug78807-expected.txt
@@ -1,4 +1,4 @@
 This page contains the following errors:
-error on line 11 at column 24: Extra content at the end of the document
+error on line 12 at column 1: Premature end of data in tag use line 11
 
 Below is a rendering of the page up to the first error.
diff --git a/third_party/blink/web_tests/svg/custom/use-invalid-html-expected.txt b/third_party/blink/web_tests/svg/custom/use-invalid-html-expected.txt
index 123bbb8..8b7db31 100644
--- a/third_party/blink/web_tests/svg/custom/use-invalid-html-expected.txt
+++ b/third_party/blink/web_tests/svg/custom/use-invalid-html-expected.txt
@@ -1,5 +1,5 @@
 This page contains the following errors:
-error on line 18 at column 9: Extra content at the end of the document
+error on line 19 at column 1: Premature end of data in tag html line 1
 
 Below is a rendering of the page up to the first error.
 This test passes if a malformed html document triggers an error, not crash. 
diff --git a/third_party/blink/web_tests/svg/custom/use-referencing-style-crash-expected.txt b/third_party/blink/web_tests/svg/custom/use-referencing-style-crash-expected.txt
index 017bb10..424e31713 100644
--- a/third_party/blink/web_tests/svg/custom/use-referencing-style-crash-expected.txt
+++ b/third_party/blink/web_tests/svg/custom/use-referencing-style-crash-expected.txt
@@ -1,4 +1,4 @@
 This page contains the following errors:
-error on line 9 at column 12: Extra content at the end of the document
+error on line 10 at column 1: Premature end of data in tag style line 9
 
 Below is a rendering of the page up to the first error.
diff --git a/third_party/blink/web_tests/svg/dom/svg2-inheritance-expected.txt b/third_party/blink/web_tests/svg/dom/svg2-inheritance-expected.txt
index c5a40e77..3a5ce22 100644
--- a/third_party/blink/web_tests/svg/dom/svg2-inheritance-expected.txt
+++ b/third_party/blink/web_tests/svg/dom/svg2-inheritance-expected.txt
@@ -24,7 +24,7 @@
 PASS SVGAnimationElement inherits SVGElement
 FAIL SVGCSSRule is not defined
 PASS SVGCircleElement inherits SVGGeometryElement
-FAIL SVGClipPathElement should inherit SVGElement but got SVGGraphicsElement instead
+PASS SVGClipPathElement inherits SVGElement
 FAIL SVGColorProfileElement is not defined
 FAIL SVGColorProfileRule is not defined
 FAIL SVGCursorElement is not defined
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
index 191a65b..34031ee 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -1580,13 +1580,6 @@
     property transform
 svg element clipPath
     property clipPathUnits
-    property farthestViewportElement
-    property getBBox
-    property getCTM
-    property getScreenCTM
-    property nearestViewportElement
-    property requiredExtensions
-    property systemLanguage
     property transform
 svg element defs
     property farthestViewportElement
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
index d5443fd2..e2480c6c 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -7008,9 +7008,10 @@
     getter cy
     getter r
     method constructor
-interface SVGClipPathElement : SVGGraphicsElement
+interface SVGClipPathElement : SVGElement
     attribute @@toStringTag
     getter clipPathUnits
+    getter transform
     method constructor
 interface SVGComponentTransferFunctionElement : SVGElement
     attribute @@toStringTag
diff --git a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
index 33d93c9..922ebdb 100644
--- a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
@@ -1654,13 +1654,6 @@
     property transform
 svg element clipPath
     property clipPathUnits
-    property farthestViewportElement
-    property getBBox
-    property getCTM
-    property getScreenCTM
-    property nearestViewportElement
-    property requiredExtensions
-    property systemLanguage
     property transform
 svg element defs
     property farthestViewportElement
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index bf3bb67..f9b8656e 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -7919,9 +7919,10 @@
     getter cy
     getter r
     method constructor
-interface SVGClipPathElement : SVGGraphicsElement
+interface SVGClipPathElement : SVGElement
     attribute @@toStringTag
     getter clipPathUnits
+    getter transform
     method constructor
 interface SVGComponentTransferFunctionElement : SVGElement
     attribute @@toStringTag
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_anchor_getAnchors_null.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_anchor_getAnchors_null.https.html.ini
index 63cc723..30386f9 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_anchor_getAnchors_null.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_anchor_getAnchors_null.https.html.ini
@@ -1,8 +1,10 @@
 [ar_anchor_getAnchors_null.https.html]
   [XRFrame's trackedAnchors is empty when the feature was requested & device returned null anchorsData - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame's trackedAnchors is empty when the feature was requested & device returned null anchorsData - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_hittestsource_lifetimes.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_hittestsource_lifetimes.https.html.ini
index b0b4a415..c122607 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_hittestsource_lifetimes.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_hittestsource_lifetimes.https.html.ini
@@ -1,32 +1,40 @@
 [ar_hittestsource_lifetimes.https.html]
   [Ensures hit test source cancellation propagates to the device when manually cancelled. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures hit test source cancellation propagates to the device when manually cancelled. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures hit test source cancellation propagates to the device when relying on GC - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures hit test source cancellation propagates to the device when relying on GC - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures transient input hit test source cancellation propagates to the device when manually cancelled. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures transient input hit test source cancellation propagates to the device when manually cancelled. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures transient input hit test source cancellation propagates to the device when relying on GC - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures transient input hit test source cancellation propagates to the device when relying on GC - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_light_estimation.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_light_estimation.https.html.ini
index 9b356c64..6199eab 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_light_estimation.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_light_estimation.https.html.ini
@@ -1,16 +1,20 @@
 [ar_light_estimation.https.html]
   [Ensure lighting estimation feature does not work when not explicitly enabled - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensure lighting estimation feature does not work when not explicitly enabled - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures lighting estimation feature works when enabled - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Ensures lighting estimation feature works when enabled - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/render_state_vertical_fov_inline.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/render_state_vertical_fov_inline.https.html.ini
index f12b719..2bd3420 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/render_state_vertical_fov_inline.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/render_state_vertical_fov_inline.https.html.ini
@@ -1,8 +1,10 @@
 [render_state_vertical_fov_inline.https.html]
   [inlineVerticalFieldOfView is set appropriately on inline sessions - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [inlineVerticalFieldOfView is set appropriately on inline sessions - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/xrFrame_getPose.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/xrFrame_getPose.https.html.ini
index b143d70..a492b8a 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/xrFrame_getPose.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/xrFrame_getPose.https.html.ini
@@ -1,8 +1,10 @@
 [xrFrame_getPose.https.html]
   [XRFrame.getPose works between eye-level and floor-level spaces - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [XRFrame.getPose works between eye-level and floor-level spaces - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_dataProviderDisconnect_immersive.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_dataProviderDisconnect_immersive.https.html.ini
index 2d429417..2d5baf2 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_dataProviderDisconnect_immersive.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_dataProviderDisconnect_immersive.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_dataProviderDisconnect_immersive.https.html]
   [Immersive session ends if data provider disconnects. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Immersive session ends if data provider disconnects. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_dataProviderDisconnect_inline.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_dataProviderDisconnect_inline.https.html.ini
index 7b7cdc6c..d0c75dd8 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_dataProviderDisconnect_inline.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_dataProviderDisconnect_inline.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_dataProviderDisconnect_inline.https.html]
   [Inline session ends if magic window data provider disconnects. - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Inline session ends if magic window data provider disconnects. - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_environmentBlendMode.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_environmentBlendMode.https.html.ini
index 47888a8a..741ba83 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_environmentBlendMode.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_environmentBlendMode.https.html.ini
@@ -1,16 +1,20 @@
 [xrSession_environmentBlendMode.https.html]
   [environmentBlendMode is correct for a VR device in immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [environmentBlendMode is correct for a VR device in immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [environmentBlendMode is correct for a VR device in non-immersive - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [environmentBlendMode is correct for a VR device in non-immersive - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_environmentProviderDisconnect.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_environmentProviderDisconnect.https.html.ini
index b18772ff3..963c10c 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_environmentProviderDisconnect.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_environmentProviderDisconnect.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_environmentProviderDisconnect.https.html]
   [Outstanding promises get rejected if environmentProvider disconnects - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Outstanding promises get rejected if environmentProvider disconnects - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_framesThrottled.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_framesThrottled.https.html.ini
index 4bdcce6..88acdae 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/xrSession_framesThrottled.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/xrSession_framesThrottled.https.html.ini
@@ -1,8 +1,10 @@
 [xrSession_framesThrottled.https.html]
   [Blink appropriately reports when frames are throttled - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [Blink appropriately reports when frames are throttled - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/xrWebGLLayer_dirty_framebuffer.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/xrWebGLLayer_dirty_framebuffer.https.html.ini
index b88971a7..5bf238c2 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/xrWebGLLayer_dirty_framebuffer.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/xrWebGLLayer_dirty_framebuffer.https.html.ini
@@ -1,8 +1,10 @@
 [xrWebGLLayer_dirty_framebuffer.https.html]
   [A frame should be submitted if the base layer was written to during requestAnimationFrame - webgl]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
 
   [A frame should be submitted if the base layer was written to during requestAnimationFrame - webgl2]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/xr_view_projection_detached.https.html.ini b/third_party/blink/web_tests/wpt_internal/webxr/xr_view_projection_detached.https.html.ini
index 9fc18187..0490121 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/xr_view_projection_detached.https.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/webxr/xr_view_projection_detached.https.html.ini
@@ -1,4 +1,5 @@
 [xr_view_projection_detached.https.html]
   [Test that xrview.projection being detached doesn't cause a crash.]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11-arm64"): FAIL
diff --git a/third_party/chromite b/third_party/chromite
index 494c618..4eda446 160000
--- a/third_party/chromite
+++ b/third_party/chromite
@@ -1 +1 @@
-Subproject commit 494c618cbb635ccc6f925e6cf7590c0a64d89687
+Subproject commit 4eda4462cb2fea1ff99bfb477545f36b282b8db4
diff --git a/third_party/depot_tools b/third_party/depot_tools
index c550588..f936d54 160000
--- a/third_party/depot_tools
+++ b/third_party/depot_tools
@@ -1 +1 @@
-Subproject commit c5505889cf38b44fd841b161d4d2e2776b65f943
+Subproject commit f936d540e1811967bd3cc819089b498b98b1e1be
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal
index c3526d6..e0aad9e 160000
--- a/third_party/devtools-frontend-internal
+++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@
-Subproject commit c3526d66491c1c30fbb2b257ce94fbbb91474323
+Subproject commit e0aad9e4d829ac0dd9f1ee4a2e67c10650a7d266
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 087d06b9..a2fe80d 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 087d06b98e6fdd264fde7d16895a1c3cec4d0766
+Subproject commit a2fe80db51e2111d5043181671e2ae52b8b2d79d
diff --git a/third_party/leveldatabase/env_chromium.h b/third_party/leveldatabase/env_chromium.h
index e650aa5..0b29dcc17 100644
--- a/third_party/leveldatabase/env_chromium.h
+++ b/third_party/leveldatabase/env_chromium.h
@@ -144,6 +144,10 @@
   // Constructs a ChromiumEnv instance with a custom FilesystemProxy instance.
   explicit ChromiumEnv(std::unique_ptr<storage::FilesystemProxy> filesystem);
 
+  // Constructs a ChromiumEnv instance with a local unrestricted FilesystemProxy
+  // instance that performs direct filesystem access.
+  explicit ChromiumEnv(const std::string& name);
+
   ~ChromiumEnv() override;
 
   bool FileExists(const std::string& fname) override;
@@ -178,10 +182,6 @@
   void SetReadOnlyFileLimitForTesting(int max_open_files);
 
  protected:
-  // Constructs a ChromiumEnv instance with a local unrestricted FilesystemProxy
-  // instance that performs direct filesystem access.
-  explicit ChromiumEnv(const std::string& name);
-
   // Constructs a ChromiumEnv instance with a custom FilesystemProxy instance.
   ChromiumEnv(const std::string& name,
               std::unique_ptr<storage::FilesystemProxy> filesystem);
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
index f3e3119..a20cae87 100644
--- a/third_party/libxml/README.chromium
+++ b/third_party/libxml/README.chromium
@@ -1,6 +1,6 @@
 Name: libxml
 URL: http://xmlsoft.org
-Version: 884474477284474e0151280aaa275a18e3d7a036
+Version: fc26934eb0b8f66dab262465226ec14eac7cb3e8
 CPEPrefix: cpe:/a:xmlsoft:libxml2:2.11.0
 License: MIT
 License File: src/Copyright
diff --git a/third_party/libxml/chromium/libxml2-2.9.4-security-xpath-nodetab-uaf.patch b/third_party/libxml/chromium/libxml2-2.9.4-security-xpath-nodetab-uaf.patch
index 92151ad..0d9263b 100644
--- a/third_party/libxml/chromium/libxml2-2.9.4-security-xpath-nodetab-uaf.patch
+++ b/third_party/libxml/chromium/libxml2-2.9.4-security-xpath-nodetab-uaf.patch
@@ -12,4 +12,4 @@
 +    ret->boolval = 0;
      ret->user = (void *) val;
      ret->nodesetval = xmlXPathNodeSetCreate(val);
- #ifdef XP_DEBUG_OBJ_USAGE
+     return(ret);
diff --git a/third_party/libxml/linux/config.h b/third_party/libxml/linux/config.h
index 775c5b5..c064071 100644
--- a/third_party/libxml/linux/config.h
+++ b/third_party/libxml/linux/config.h
@@ -69,9 +69,6 @@
 /* Define to 1 if you have the <pthread.h> header file. */
 #define HAVE_PTHREAD_H /**/
 
-/* Define to 1 if you have the `rand_r' function. */
-
-
 /* Have shl_load based dso */
 /* #undef HAVE_SHLLOAD */
 
@@ -173,6 +170,9 @@
 /* Determine what socket length (socklen_t) data type is */
 /* #undef XML_SOCKLEN_T */
 
+/* TLS specifier */
+#define XML_THREAD_LOCAL _Thread_local
+
 /* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
    <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
    #define below would cause a syntax error. */
diff --git a/third_party/libxml/linux/include/libxml/xmlversion.h b/third_party/libxml/linux/include/libxml/xmlversion.h
index 9cf8e39..4d40bb1 100644
--- a/third_party/libxml/linux/include/libxml/xmlversion.h
+++ b/third_party/libxml/linux/include/libxml/xmlversion.h
@@ -524,6 +524,18 @@
 #endif
 #endif /* __GNUC__ */
 
+/** DOC_DISABLE */
+#define XML_EMPTY
+
+#ifdef LIBXML_THREAD_ENABLED
+#define XML_DECLARE_GLOBAL(name, type, attrs) \
+  attrs XMLPUBFUN type* __##name(void);
+#define XML_GLOBAL_MACRO(name) (*__##name())
+#else
+#define XML_DECLARE_GLOBAL(name, type, attrs) attrs XMLPUBVAR type name;
+#endif
+/** DOC_ENABLE */
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/third_party/libxml/linux/xml2-config b/third_party/libxml/linux/xml2-config
index a25ec4b..906d62b 100755
--- a/third_party/libxml/linux/xml2-config
+++ b/third_party/libxml/linux/xml2-config
@@ -84,9 +84,9 @@
     --libs)
         if [ "$2" = "--dynamic" ]; then
             shift
-            libs="-lxml2"
+            libs="-lxml2 "
         else
-            libs="-lxml2     -licui18n -licuuc -licudata -lm   "
+            libs="-lxml2  -licui18n -licuuc -licudata    -lm   "
         fi
 
         if [ "-L${libdir}" != "-L/usr/lib" -a "-L${libdir}" != "-L/usr/lib64" ]; then
diff --git a/third_party/libxml/mac/config.h b/third_party/libxml/mac/config.h
index 775c5b5..c064071 100644
--- a/third_party/libxml/mac/config.h
+++ b/third_party/libxml/mac/config.h
@@ -69,9 +69,6 @@
 /* Define to 1 if you have the <pthread.h> header file. */
 #define HAVE_PTHREAD_H /**/
 
-/* Define to 1 if you have the `rand_r' function. */
-
-
 /* Have shl_load based dso */
 /* #undef HAVE_SHLLOAD */
 
@@ -173,6 +170,9 @@
 /* Determine what socket length (socklen_t) data type is */
 /* #undef XML_SOCKLEN_T */
 
+/* TLS specifier */
+#define XML_THREAD_LOCAL _Thread_local
+
 /* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
    <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
    #define below would cause a syntax error. */
diff --git a/third_party/libxml/mac/include/libxml/xmlversion.h b/third_party/libxml/mac/include/libxml/xmlversion.h
index 9cf8e39..4d40bb1 100644
--- a/third_party/libxml/mac/include/libxml/xmlversion.h
+++ b/third_party/libxml/mac/include/libxml/xmlversion.h
@@ -524,6 +524,18 @@
 #endif
 #endif /* __GNUC__ */
 
+/** DOC_DISABLE */
+#define XML_EMPTY
+
+#ifdef LIBXML_THREAD_ENABLED
+#define XML_DECLARE_GLOBAL(name, type, attrs) \
+  attrs XMLPUBFUN type* __##name(void);
+#define XML_GLOBAL_MACRO(name) (*__##name())
+#else
+#define XML_DECLARE_GLOBAL(name, type, attrs) attrs XMLPUBVAR type name;
+#endif
+/** DOC_ENABLE */
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/third_party/libxml/src/HTMLparser.c b/third_party/libxml/src/HTMLparser.c
index a3c47f6..1af0190 100644
--- a/third_party/libxml/src/HTMLparser.c
+++ b/third_party/libxml/src/HTMLparser.c
@@ -14,24 +14,23 @@
 #include <ctype.h>
 #include <stdlib.h>
 
+#include <libxml/HTMLparser.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/xmlerror.h>
-#include <libxml/HTMLparser.h>
 #include <libxml/HTMLtree.h>
 #include <libxml/entities.h>
 #include <libxml/encoding.h>
-#include <libxml/valid.h>
 #include <libxml/xmlIO.h>
-#include <libxml/globals.h>
 #include <libxml/uri.h>
 
 #include "private/buf.h"
 #include "private/enc.h"
 #include "private/error.h"
 #include "private/html.h"
+#include "private/io.h"
 #include "private/parser.h"
 #include "private/tree.h"
 
@@ -39,9 +38,6 @@
 #define HTML_PARSER_BIG_BUFFER_SIZE 1000
 #define HTML_PARSER_BUFFER_SIZE 100
 
-/* #define DEBUG */
-/* #define DEBUG_PUSH */
-
 static int htmlOmittedDefaultValue = 1;
 
 xmlChar * htmlDecodeEntities(htmlParserCtxtPtr ctxt, int len,
@@ -350,8 +346,7 @@
     const xmlChar *start, *cur, *end;
 
     if ((ctxt == NULL) || (ctxt->input == NULL) ||
-        (ctxt->input->encoding != NULL) || (ctxt->input->buf == NULL) ||
-        (ctxt->input->buf->encoder != NULL))
+        (ctxt->input->flags & XML_INPUT_HAS_ENCODING))
         return(NULL);
     if ((ctxt->input->cur == NULL) || (ctxt->input->end == NULL))
         return(NULL);
@@ -417,7 +412,7 @@
             return(0);
     }
 
-    if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
+    if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) {
         xmlChar * guess;
         xmlCharEncodingHandlerPtr handler;
 
@@ -444,9 +439,6 @@
         if (guess == NULL) {
             xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
         } else {
-            if (ctxt->input->encoding != NULL)
-                xmlFree((xmlChar *) ctxt->input->encoding);
-            ctxt->input->encoding = guess;
             handler = xmlFindCharEncodingHandler((const char *) guess);
             if (handler != NULL) {
                 /*
@@ -459,8 +451,9 @@
                 htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
                              "Unsupported encoding %s", guess, NULL);
             }
+            xmlFree(guess);
         }
-        ctxt->charset = XML_CHAR_ENCODING_UTF8;
+        ctxt->input->flags |= XML_INPUT_HAS_ENCODING;
     }
 
     /*
@@ -537,13 +530,6 @@
     }
 
 encoding_error:
-    /*
-     * If we detect an UTF8 error that probably mean that the
-     * input encoding didn't get properly advertised in the
-     * declaration header. Report the error and switch the encoding
-     * to ISO-Latin-1 (if you don't like this policy, just declare the
-     * encoding !)
-     */
     {
         char buffer[150];
 
@@ -559,15 +545,7 @@
 		     BAD_CAST buffer, NULL);
     }
 
-    /*
-     * Don't switch encodings twice. Note that if there's an encoder, we
-     * shouldn't receive invalid UTF-8 anyway.
-     *
-     * Note that if ctxt->input->buf == NULL, switching encodings is
-     * impossible, see Gitlab issue #34.
-     */
-    if ((ctxt->input->buf != NULL) &&
-        (ctxt->input->buf->encoder == NULL))
+    if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0)
         xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
     *len = 1;
     return(*ctxt->input->cur);
@@ -1555,20 +1533,11 @@
 static void
 htmlAutoClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag)
 {
-    while ((newtag != NULL) && (ctxt->name != NULL) &&
-           (htmlCheckAutoClose(newtag, ctxt->name))) {
-        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
-            ctxt->sax->endElement(ctxt->userData, ctxt->name);
-	htmlnamePop(ctxt);
-    }
-    if (newtag == NULL) {
-        htmlAutoCloseOnEnd(ctxt);
+    if (newtag == NULL)
         return;
-    }
-    while ((newtag == NULL) && (ctxt->name != NULL) &&
-           ((xmlStrEqual(ctxt->name, BAD_CAST "head")) ||
-            (xmlStrEqual(ctxt->name, BAD_CAST "body")) ||
-            (xmlStrEqual(ctxt->name, BAD_CAST "html")))) {
+
+    while ((ctxt->name != NULL) &&
+           (htmlCheckAutoClose(newtag, ctxt->name))) {
         if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
             ctxt->sax->endElement(ctxt->userData, ctxt->name);
 	htmlnamePop(ctxt);
@@ -3782,94 +3751,6 @@
 }
 
 /**
- * htmlCheckEncodingDirect:
- * @ctxt:  an HTML parser context
- * @attvalue: the attribute value
- *
- * Checks an attribute value to detect
- * the encoding
- * If a new encoding is detected the parser is switched to decode
- * it and pass UTF8
- */
-static void
-htmlCheckEncodingDirect(htmlParserCtxtPtr ctxt, const xmlChar *encoding) {
-
-    if ((ctxt == NULL) || (encoding == NULL) ||
-        (ctxt->options & HTML_PARSE_IGNORE_ENC))
-	return;
-
-    /* do not change encoding */
-    if (ctxt->input->encoding != NULL)
-        return;
-
-    if (encoding != NULL) {
-	xmlCharEncoding enc;
-	xmlCharEncodingHandlerPtr handler;
-
-	while ((*encoding == ' ') || (*encoding == '\t')) encoding++;
-
-	if (ctxt->input->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->input->encoding);
-	ctxt->input->encoding = xmlStrdup(encoding);
-
-	enc = xmlParseCharEncoding((const char *) encoding);
-	/*
-	 * registered set of known encodings
-	 */
-	if (enc != XML_CHAR_ENCODING_ERROR) {
-	    if (((enc == XML_CHAR_ENCODING_UTF16LE) ||
-	         (enc == XML_CHAR_ENCODING_UTF16BE) ||
-		 (enc == XML_CHAR_ENCODING_UCS4LE) ||
-		 (enc == XML_CHAR_ENCODING_UCS4BE)) &&
-		(ctxt->input->buf != NULL) &&
-		(ctxt->input->buf->encoder == NULL)) {
-		htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
-		             "htmlCheckEncoding: wrong encoding meta\n",
-			     NULL, NULL);
-	    } else {
-		xmlSwitchEncoding(ctxt, enc);
-	    }
-	    ctxt->charset = XML_CHAR_ENCODING_UTF8;
-	} else {
-	    /*
-	     * fallback for unknown encodings
-	     */
-	    handler = xmlFindCharEncodingHandler((const char *) encoding);
-	    if (handler != NULL) {
-		xmlSwitchToEncoding(ctxt, handler);
-		ctxt->charset = XML_CHAR_ENCODING_UTF8;
-	    } else {
-		htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-		             "htmlCheckEncoding: unknown encoding %s\n",
-			     encoding, NULL);
-	    }
-	}
-
-	if ((ctxt->input->buf != NULL) &&
-	    (ctxt->input->buf->encoder != NULL) &&
-	    (ctxt->input->buf->raw != NULL) &&
-	    (ctxt->input->buf->buffer != NULL)) {
-	    int nbchars;
-	    size_t processed;
-
-	    /*
-	     * convert as much as possible to the parser reading buffer.
-	     */
-	    processed = ctxt->input->cur - ctxt->input->base;
-	    xmlBufShrink(ctxt->input->buf->buffer, processed);
-	    nbchars = xmlCharEncInput(ctxt->input->buf, 1);
-            xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
-	    if (nbchars < 0) {
-		htmlParseErr(ctxt, ctxt->input->buf->error,
-		             "htmlCheckEncoding: encoder error\n",
-			     NULL, NULL);
-                xmlHaltParser(ctxt);
-	    }
-	}
-    }
-}
-
-/**
  * htmlCheckEncoding:
  * @ctxt:  an HTML parser context
  * @attvalue: the attribute value
@@ -3897,7 +3778,7 @@
 	encoding = xmlStrcasestr(attvalue, BAD_CAST"=");
     if (encoding && *encoding == '=') {
 	encoding ++;
-	htmlCheckEncodingDirect(ctxt, encoding);
+	xmlSetDeclaredEncoding(ctxt, xmlStrdup(encoding));
     }
 }
 
@@ -3926,7 +3807,7 @@
 	 && (!xmlStrcasecmp(value, BAD_CAST"Content-Type")))
 	    http = 1;
 	else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"charset")))
-	    htmlCheckEncodingDirect(ctxt, value);
+	    xmlSetDeclaredEncoding(ctxt, xmlStrdup(value));
 	else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"content")))
 	    content = value;
 	att = atts[i++];
@@ -4953,8 +4834,6 @@
 
 int
 htmlParseDocument(htmlParserCtxtPtr ctxt) {
-    xmlChar start[4];
-    xmlCharEncoding enc;
     xmlDtdPtr dtd;
 
     xmlInitParser();
@@ -4964,29 +4843,14 @@
 		     "htmlParseDocument: context error\n", NULL, NULL);
 	return(XML_ERR_INTERNAL_ERROR);
     }
-    GROW;
+
     /*
      * SAX: beginning of the document processing.
      */
     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
-    if ((ctxt->encoding == (const xmlChar *)XML_CHAR_ENCODING_NONE) &&
-        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
-	/*
-	 * Get the 4 first bytes and decode the charset
-	 * if enc != XML_CHAR_ENCODING_NONE
-	 * plug some encoding conversion routines.
-	 */
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(&start[0], 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-    }
+    xmlDetectEncoding(ctxt);
 
     /*
      * Wipe out everything which is before the first '<'
@@ -5292,7 +5156,7 @@
 
 /**
  * htmlCreateDocParserCtxt:
- * @cur:  a pointer to an array of xmlChar
+ * @str:  a pointer to an array of xmlChar
  * @encoding:  a free form C string describing the HTML document encoding, or NULL
  *
  * Create a parser context for an HTML document.
@@ -5302,25 +5166,41 @@
  * Returns the new parser context or NULL
  */
 static htmlParserCtxtPtr
-htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) {
-    int len;
-    htmlParserCtxtPtr ctxt;
+htmlCreateDocParserCtxt(const xmlChar *str, const char *encoding) {
+    xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+    xmlParserInputBufferPtr buf;
 
-    if (cur == NULL)
+    if (str == NULL)
 	return(NULL);
-    len = xmlStrlen(cur);
-    ctxt = htmlCreateMemoryParserCtxt((char *)cur, len);
+
+    ctxt = htmlNewParserCtxt();
     if (ctxt == NULL)
 	return(NULL);
 
+    buf = xmlParserInputBufferCreateString(str);
+    if (buf == NULL) {
+	xmlFreeParserCtxt(ctxt);
+        return(NULL);
+    }
+
+    input = xmlNewInputStream(ctxt);
+    if (input == NULL) {
+	xmlFreeParserInputBuffer(buf);
+	xmlFreeParserCtxt(ctxt);
+	return(NULL);
+    }
+
+    input->filename = NULL;
+    input->buf = buf;
+    xmlBufResetInput(buf->buffer, input);
+
+    inputPush(ctxt, input);
+
     if (encoding != NULL) {
 	xmlCharEncoding enc;
 	xmlCharEncodingHandlerPtr handler;
 
-	if (ctxt->input->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->input->encoding);
-	ctxt->input->encoding = xmlStrdup((const xmlChar *) encoding);
-
 	enc = xmlParseCharEncoding(encoding);
 	/*
 	 * registered set of known encodings
@@ -5346,6 +5226,7 @@
 	    }
 	}
     }
+
     return(ctxt);
 }
 
@@ -5430,18 +5311,6 @@
     }
     ctxt->checkIndex = base;
     ctxt->endCheckState = quote;
-#ifdef DEBUG_PUSH
-    if (next == 0)
-        xmlGenericError(xmlGenericErrorContext,
-                        "HPP: lookup '%c' failed\n", first);
-    else if (third == 0)
-        xmlGenericError(xmlGenericErrorContext,
-                        "HPP: lookup '%c%c' failed\n", first, next);
-    else
-        xmlGenericError(xmlGenericErrorContext,
-                        "HPP: lookup '%c%c%c' failed\n", first, next,
-                        third);
-#endif
     return (-1);
 }
 
@@ -5503,59 +5372,6 @@
 
     htmlParserNodeInfo node_info;
 
-#ifdef DEBUG_PUSH
-    switch (ctxt->instate) {
-	case XML_PARSER_EOF:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try EOF\n"); break;
-	case XML_PARSER_START:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try START\n"); break;
-	case XML_PARSER_MISC:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try MISC\n");break;
-	case XML_PARSER_COMMENT:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try COMMENT\n");break;
-	case XML_PARSER_PROLOG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try PROLOG\n");break;
-	case XML_PARSER_START_TAG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try START_TAG\n");break;
-	case XML_PARSER_CONTENT:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try CONTENT\n");break;
-	case XML_PARSER_CDATA_SECTION:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try CDATA_SECTION\n");break;
-	case XML_PARSER_END_TAG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try END_TAG\n");break;
-	case XML_PARSER_ENTITY_DECL:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try ENTITY_DECL\n");break;
-	case XML_PARSER_ENTITY_VALUE:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try ENTITY_VALUE\n");break;
-	case XML_PARSER_ATTRIBUTE_VALUE:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try ATTRIBUTE_VALUE\n");break;
-	case XML_PARSER_DTD:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try DTD\n");break;
-	case XML_PARSER_EPILOG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try EPILOG\n");break;
-	case XML_PARSER_PI:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try PI\n");break;
-	case XML_PARSER_SYSTEM_LITERAL:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "HPP: try SYSTEM_LITERAL\n");break;
-    }
-#endif
-
     while (1) {
 
 	in = ctxt->input;
@@ -5607,6 +5423,8 @@
 		if ((ctxt->sax) && (ctxt->sax->startDocument) &&
 	            (!ctxt->disableSAX))
 		    ctxt->sax->startDocument(ctxt->userData);
+                if (ctxt->instate == XML_PARSER_EOF)
+                    goto done;
 
 		cur = in->cur[0];
 		next = in->cur[1];
@@ -5618,22 +5436,12 @@
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing internal subset\n");
-#endif
 		    htmlParseDocTypeDecl(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_PROLOG;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering PROLOG\n");
-#endif
                 } else {
 		    ctxt->instate = XML_PARSER_MISC;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering MISC\n");
-#endif
 		}
 		break;
             case XML_PARSER_MISC:
@@ -5660,21 +5468,17 @@
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing Comment\n");
-#endif
 		    htmlParseComment(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_MISC;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing PI\n");
-#endif
 		    htmlParsePI(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_MISC;
 		} else if ((cur == '<') && (next == '!') &&
 		    (UPP(2) == 'D') && (UPP(3) == 'O') &&
@@ -5684,25 +5488,15 @@
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing internal subset\n");
-#endif
 		    htmlParseDocTypeDecl(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_PROLOG;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering PROLOG\n");
-#endif
 		} else if ((cur == '<') && (next == '!') &&
 		           (avail < 9)) {
 		    goto done;
 		} else {
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering START_TAG\n");
-#endif
 		}
 		break;
             case XML_PARSER_PROLOG:
@@ -5716,31 +5510,23 @@
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing Comment\n");
-#endif
 		    htmlParseComment(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_PROLOG;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing PI\n");
-#endif
 		    htmlParsePI(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_PROLOG;
 		} else if ((cur == '<') && (next == '!') &&
 		           (avail < 4)) {
 		    goto done;
 		} else {
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering START_TAG\n");
-#endif
 		}
 		break;
             case XML_PARSER_EPILOG:
@@ -5759,21 +5545,17 @@
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing Comment\n");
-#endif
 		    htmlParseComment(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_EPILOG;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
 		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: Parsing PI\n");
-#endif
 		    htmlParsePI(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_EPILOG;
 		} else if ((cur == '<') && (next == '!') &&
 		           (avail < 4)) {
@@ -5782,10 +5564,6 @@
 		    ctxt->errNo = XML_ERR_DOCUMENT_END;
 		    ctxt->wellFormed = 0;
 		    ctxt->instate = XML_PARSER_EOF;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering EOF\n");
-#endif
 		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 			ctxt->sax->endDocument(ctxt->userData);
 		    goto done;
@@ -5815,19 +5593,11 @@
 		cur = in->cur[0];
 	        if (cur != '<') {
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering CONTENT\n");
-#endif
 		    break;
 		}
 		if (next == '/') {
 		    ctxt->instate = XML_PARSER_END_TAG;
 		    ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering END_TAG\n");
-#endif
 		    break;
 		}
 		if ((!terminate) &&
@@ -5868,11 +5638,9 @@
 		    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
 			ctxt->sax->endElement(ctxt->userData, name);
 		    htmlnamePop(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering CONTENT\n");
-#endif
 		    break;
 		}
 
@@ -5894,11 +5662,9 @@
 		    if (ctxt->record_info)
 		        htmlNodeInfoPush(ctxt, &node_info);
 
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "HPP: entering CONTENT\n");
-#endif
 		    break;
 		}
 
@@ -5914,11 +5680,9 @@
                 if (ctxt->record_info)
 	            htmlNodeInfoPush(ctxt, &node_info);
 
+                if (ctxt->instate == XML_PARSER_EOF)
+                    goto done;
 		ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
                 break;
 	    }
             case XML_PARSER_CONTENT: {
@@ -5990,13 +5754,11 @@
                         }
 		    }
 		    htmlParseScript(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
 		    if ((cur == '<') && (next == '/')) {
 			ctxt->instate = XML_PARSER_END_TAG;
 			ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"HPP: entering END_TAG\n");
-#endif
 			break;
 		    }
 		} else if ((cur == '<') && (next == '!')) {
@@ -6020,11 +5782,9 @@
                         if ((!terminate) &&
                             (htmlParseLookupCommentEnd(ctxt) < 0))
                             goto done;
-#ifdef DEBUG_PUSH
-                        xmlGenericError(xmlGenericErrorContext,
-                                "HPP: Parsing Comment\n");
-#endif
                         htmlParseComment(ctxt);
+                        if (ctxt->instate == XML_PARSER_EOF)
+                            goto done;
                         ctxt->instate = XML_PARSER_CONTENT;
                     } else {
                         if ((!terminate) &&
@@ -6036,29 +5796,19 @@
                     if ((!terminate) &&
                         (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
                         goto done;
-#ifdef DEBUG_PUSH
-                    xmlGenericError(xmlGenericErrorContext,
-                            "HPP: Parsing PI\n");
-#endif
                     htmlParsePI(ctxt);
+                    if (ctxt->instate == XML_PARSER_EOF)
+                        goto done;
                     ctxt->instate = XML_PARSER_CONTENT;
                 } else if ((cur == '<') && (next == '/')) {
                     ctxt->instate = XML_PARSER_END_TAG;
                     ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-                    xmlGenericError(xmlGenericErrorContext,
-                            "HPP: entering END_TAG\n");
-#endif
                     break;
                 } else if ((cur == '<') && IS_ASCII_LETTER(next)) {
                     if ((!terminate) && (next == 0))
                         goto done;
                     ctxt->instate = XML_PARSER_START_TAG;
                     ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-                    xmlGenericError(xmlGenericErrorContext,
-                            "HPP: entering START_TAG\n");
-#endif
                     break;
                 } else if (cur == '<') {
                     if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
@@ -6077,10 +5827,6 @@
                         (htmlParseLookupSequence(ctxt, '<', 0, 0, 0) < 0))
                         goto done;
                     ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-                    xmlGenericError(xmlGenericErrorContext,
-                            "HPP: Parsing char data\n");
-#endif
                     while ((ctxt->instate != XML_PARSER_EOF) &&
                            (cur != '<') && (in->cur < in->end)) {
                         if (cur == '&') {
@@ -6101,128 +5847,20 @@
 		    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 		    goto done;
 		htmlParseEndTag(ctxt);
+                if (ctxt->instate == XML_PARSER_EOF)
+                    goto done;
 		if (ctxt->nameNr == 0) {
 		    ctxt->instate = XML_PARSER_EPILOG;
 		} else {
 		    ctxt->instate = XML_PARSER_CONTENT;
 		}
 		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
 	        break;
-            case XML_PARSER_CDATA_SECTION:
+	    default:
 		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == CDATA\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
+			     "HPP: internal error\n", NULL, NULL);
+		ctxt->instate = XML_PARSER_EOF;
 		break;
-            case XML_PARSER_DTD:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == DTD\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_COMMENT:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == COMMENT\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_PI:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == PI\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_ENTITY_DECL:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == ENTITY_DECL\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_ENTITY_VALUE:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == ENTITY_VALUE\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering DTD\n");
-#endif
-		break;
-            case XML_PARSER_ATTRIBUTE_VALUE:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == ATTRIBUTE_VALUE\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_START_TAG;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering START_TAG\n");
-#endif
-		break;
-	    case XML_PARSER_SYSTEM_LITERAL:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		    "HPP: internal error, state == XML_PARSER_SYSTEM_LITERAL\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-	    case XML_PARSER_IGNORE:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == XML_PARSER_IGNORE\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-	    case XML_PARSER_PUBLIC_LITERAL:
-		htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			"HPP: internal error, state == XML_PARSER_LITERAL\n",
-			     NULL, NULL);
-		ctxt->instate = XML_PARSER_CONTENT;
-		ctxt->checkIndex = 0;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"HPP: entering CONTENT\n");
-#endif
-		break;
-
 	}
     }
 done:
@@ -6248,9 +5886,6 @@
 		    BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN",
 		    BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd");
     }
-#ifdef DEBUG_PUSH
-    xmlGenericError(xmlGenericErrorContext, "HPP: done %d\n", ret);
-#endif
     return(ret);
 }
 
@@ -6275,45 +5910,17 @@
     }
     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
         (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-	size_t cur = ctxt->input->cur - ctxt->input->base;
+	size_t pos = ctxt->input->cur - ctxt->input->base;
 	int res;
 
 	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
 	if (res < 0) {
             htmlParseErr(ctxt, ctxt->input->buf->error,
                          "xmlParserInputBufferPush failed", NULL, NULL);
             xmlHaltParser(ctxt);
 	    return (ctxt->errNo);
 	}
-#ifdef DEBUG_PUSH
-	xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
-#endif
-
-#if 0
-	if ((terminate) || (ctxt->input->buf->buffer->use > 80))
-	    htmlParseTryOrFinish(ctxt, terminate);
-#endif
-    } else if (ctxt->instate != XML_PARSER_EOF) {
-	if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
-	    xmlParserInputBufferPtr in = ctxt->input->buf;
-	    if ((in->encoder != NULL) && (in->buffer != NULL) &&
-		    (in->raw != NULL)) {
-		int nbchars;
-		size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
-		size_t current = ctxt->input->cur - ctxt->input->base;
-
-		nbchars = xmlCharEncInput(in, terminate);
-		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
-		if (nbchars < 0) {
-		    htmlParseErr(ctxt, in->error,
-			         "encoder error\n", NULL, NULL);
-                    xmlHaltParser(ctxt);
-		    return(XML_ERR_INVALID_ENCODING);
-		}
-	    }
-	}
     }
     htmlParseTryOrFinish(ctxt, terminate);
     if (terminate) {
@@ -6371,8 +5978,6 @@
 	xmlFreeParserInputBuffer(buf);
 	return(NULL);
     }
-    if(enc==XML_CHAR_ENCODING_UTF8 || buf->encoder)
-	ctxt->charset=XML_CHAR_ENCODING_UTF8;
     if (filename == NULL) {
 	ctxt->directory = NULL;
     } else {
@@ -6398,20 +6003,16 @@
 
     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
         (ctxt->input->buf != NULL))  {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-	size_t cur = ctxt->input->cur - ctxt->input->base;
+	size_t pos = ctxt->input->cur - ctxt->input->base;
         int res;
 
 	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
         if (res < 0) {
             htmlParseErr(ctxt, ctxt->input->buf->error,
                          "xmlParserInputBufferPush failed\n", NULL, NULL);
             xmlHaltParser(ctxt);
         }
-#ifdef DEBUG_PUSH
-	xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
-#endif
     }
     ctxt->progressive = 1;
 
@@ -6499,8 +6100,6 @@
     htmlParserCtxtPtr ctxt;
     htmlParserInputPtr inputStream;
     char *canonicFilename;
-    /* htmlCharEncoding enc; */
-    xmlChar *content, *content_line = (xmlChar *) "charset=";
 
     if (filename == NULL)
         return(NULL);
@@ -6526,17 +6125,12 @@
 
     /* set encoding */
     if (encoding) {
-        size_t l = strlen(encoding);
+        xmlCharEncodingHandlerPtr hdlr;
 
-	if (l < 1000) {
-	    content = xmlMallocAtomic (xmlStrlen(content_line) + l + 1);
-	    if (content) {
-		strcpy ((char *)content, (char *)content_line);
-		strcat ((char *)content, (char *)encoding);
-		htmlCheckEncoding (ctxt, content);
-		xmlFree (content);
-	    }
-	}
+        hdlr = xmlFindCharEncodingHandler(encoding);
+        if (hdlr != NULL) {
+            xmlSwitchToEncoding(ctxt, hdlr);
+        }
     }
 
     return(ctxt);
@@ -6828,7 +6422,6 @@
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
     ctxt->depth = 0;
-    ctxt->charset = XML_CHAR_ENCODING_NONE;
     ctxt->catalogs = NULL;
     xmlInitNodeInfoSeq(&ctxt->node_seq);
 
@@ -6945,9 +6538,6 @@
 	hdlr = xmlFindCharEncodingHandler(encoding);
 	if (hdlr != NULL) {
 	    xmlSwitchToEncoding(ctxt, hdlr);
-	    if (ctxt->input->encoding != NULL)
-	      xmlFree((xmlChar *) ctxt->input->encoding);
-            ctxt->input->encoding = xmlStrdup((xmlChar *)encoding);
         }
     }
     if ((URL != NULL) && (ctxt->input != NULL) &&
@@ -7131,7 +6721,7 @@
 /**
  * htmlCtxtReadDoc:
  * @ctxt:  an HTML parser context
- * @cur:  a pointer to a zero terminated string
+ * @str:  a pointer to a zero terminated string
  * @URL:  the base URL to use for the document
  * @encoding:  the document encoding, or NULL
  * @options:  a combination of htmlParserOption(s)
@@ -7142,13 +6732,33 @@
  * Returns the resulting document tree
  */
 htmlDocPtr
-htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar * cur,
+htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar *str,
                const char *URL, const char *encoding, int options)
 {
-    if (cur == NULL)
+    xmlParserInputBufferPtr input;
+    xmlParserInputPtr stream;
+
+    if (ctxt == NULL)
         return (NULL);
-    return (htmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL,
-                               encoding, options));
+    if (str == NULL)
+        return (NULL);
+    xmlInitParser();
+
+    htmlCtxtReset(ctxt);
+
+    input = xmlParserInputBufferCreateString(str);
+    if (input == NULL) {
+	return(NULL);
+    }
+
+    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
+    if (stream == NULL) {
+	xmlFreeParserInputBuffer(input);
+	return(NULL);
+    }
+
+    inputPush(ctxt, stream);
+    return (htmlDoRead(ctxt, URL, encoding, options, 1));
 }
 
 /**
diff --git a/third_party/libxml/src/HTMLtree.c b/third_party/libxml/src/HTMLtree.c
index fa3a0ed..8698f53e8 100644
--- a/third_party/libxml/src/HTMLtree.c
+++ b/third_party/libxml/src/HTMLtree.c
@@ -19,10 +19,8 @@
 #include <libxml/HTMLparser.h>
 #include <libxml/HTMLtree.h>
 #include <libxml/entities.h>
-#include <libxml/valid.h>
 #include <libxml/xmlerror.h>
 #include <libxml/parserInternals.h>
-#include <libxml/globals.h>
 #include <libxml/uri.h>
 
 #include "private/buf.h"
diff --git a/third_party/libxml/src/README.md b/third_party/libxml/src/README.md
index f8c6aacf..e9a5c78 100644
--- a/third_party/libxml/src/README.md
+++ b/third_party/libxml/src/README.md
@@ -29,23 +29,58 @@
 If you build from a Git tree, you have to install Autotools and start
 by generating the configuration files with:
 
-    ./autogen.sh
+    ./autogen.sh [configuration options]
 
 If you build from a source tarball, extract the archive with:
 
     tar xf libxml2-xxx.tar.gz
     cd libxml2-xxx
 
-To see a list of build options:
+Then you can configure and build the library:
 
-    ./configure --help
-
-Also see the INSTALL file for additional instructions. Then you can
-configure and build the library:
-
-    ./configure [possible options]
+    ./configure [configuration options]
     make
 
+The following options disable or enable code modules and relevant symbols:
+
+    --with-c14n             Canonical XML 1.0 support (on)
+    --with-catalog          XML Catalogs support (on)
+    --with-debug            debugging module and shell (on)
+    --with-history          history support for shell (off)
+    --with-readline[=DIR]   use readline in DIR (for shell history)
+    --with-html             HTML parser (on)
+    --with-http             HTTP support (on)
+    --with-iconv[=DIR]      iconv support (on)
+    --with-icu              ICU support (off)
+    --with-iso8859x         ISO-8859-X support if no iconv (on)
+    --with-lzma[=DIR]       use liblzma in DIR (on)
+    --with-mem-debug        memory debugging module (off)
+    --with-modules          dynamic modules support (on)
+    --with-output           serialization support (on)
+    --with-pattern          xmlPattern selection interface (on)
+    --with-push             push parser interfaces (on)
+    --with-python           Python bindings (on)
+    --with-reader           xmlReader parsing interface (on)
+    --with-regexps          regular expressions support (on)
+    --with-run-debug        runtime debugging module (off)
+    --with-sax1             older SAX1 interface (on)
+    --with-schemas          XML Schemas 1.0 and RELAX NG support (on)
+    --with-schematron       Schematron support (on)
+    --with-threads          multithreading support (on)
+    --with-thread-alloc     per-thread malloc hooks (off)
+    --with-tree             DOM like tree manipulation APIs (on)
+    --with-valid            DTD validation support (on)
+    --with-writer           xmlWriter serialization interface (on)
+    --with-xinclude         XInclude 1.0 support (on)
+    --with-xpath            XPath 1.0 support (on)
+    --with-xptr             XPointer support (on)
+    --with-zlib[=DIR]       use libz in DIR (on)
+
+Other options:
+
+    --with-minimum          build a minimally sized library (off)
+    --with-legacy           maximum ABI compatibility (off)
+
 Note that by default, no optimization options are used. You have to
 enable them manually, for example with:
 
diff --git a/third_party/libxml/src/SAX2.c b/third_party/libxml/src/SAX2.c
index 474ea37..e9cd21b 100644
--- a/third_party/libxml/src/SAX2.c
+++ b/third_party/libxml/src/SAX2.c
@@ -13,6 +13,7 @@
 #include <string.h>
 #include <limits.h>
 #include <stddef.h>
+#include <libxml/SAX2.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
 #include <libxml/parser.h>
@@ -22,19 +23,14 @@
 #include <libxml/xmlerror.h>
 #include <libxml/debugXML.h>
 #include <libxml/xmlIO.h>
-#include <libxml/SAX.h>
 #include <libxml/uri.h>
 #include <libxml/valid.h>
 #include <libxml/HTMLtree.h>
-#include <libxml/globals.h>
 
 #include "private/error.h"
 #include "private/parser.h"
 #include "private/tree.h"
 
-/* #define DEBUG_SAX2 */
-/* #define DEBUG_SAX2_TREE */
-
 /**
  * TODO:
  *
@@ -331,11 +327,6 @@
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlDtdPtr dtd;
     if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
-            name, ExternalID, SystemID);
-#endif
 
     if (ctxt->myDoc == NULL)
 	return;
@@ -368,11 +359,6 @@
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
-            name, ExternalID, SystemID);
-#endif
     if (((ExternalID != NULL) || (SystemID != NULL)) &&
         (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
 	 (ctxt->wellFormed && ctxt->myDoc))) {
@@ -384,8 +370,6 @@
 	int oldinputMax;
 	xmlParserInputPtr *oldinputTab;
 	xmlParserInputPtr input = NULL;
-	xmlCharEncoding enc;
-	int oldcharset;
 	const xmlChar *oldencoding;
 	int oldprogressive;
         unsigned long consumed;
@@ -410,7 +394,6 @@
 	oldinputNr = ctxt->inputNr;
 	oldinputMax = ctxt->inputMax;
 	oldinputTab = ctxt->inputTab;
-	oldcharset = ctxt->charset;
 	oldencoding = ctxt->encoding;
         oldprogressive = ctxt->progressive;
 	ctxt->encoding = NULL;
@@ -425,7 +408,6 @@
 	    ctxt->inputNr = oldinputNr;
 	    ctxt->inputMax = oldinputMax;
 	    ctxt->inputTab = oldinputTab;
-	    ctxt->charset = oldcharset;
 	    ctxt->encoding = oldencoding;
             ctxt->progressive = oldprogressive;
 	    return;
@@ -435,14 +417,6 @@
 	ctxt->input = NULL;
 	xmlPushInput(ctxt, input);
 
-	/*
-	 * On the fly encoding conversion if needed
-	 */
-	if (ctxt->input->length >= 4) {
-	    enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-
 	if (input->filename == NULL)
 	    input->filename = (char *) xmlCanonicPath(SystemID);
 	input->line = 1;
@@ -484,7 +458,6 @@
 	ctxt->inputNr = oldinputNr;
 	ctxt->inputMax = oldinputMax;
 	ctxt->inputTab = oldinputTab;
-	ctxt->charset = oldcharset;
 	if ((ctxt->encoding != NULL) &&
 	    ((ctxt->dict == NULL) ||
 	     (!xmlDictOwns(ctxt->dict, ctxt->encoding))))
@@ -525,11 +498,6 @@
 
     URI = xmlBuildURI(systemId, (const xmlChar *) base);
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
-#endif
-
     ret = xmlLoadExternalEntity((const char *) URI,
 				(const char *) publicId, ctxt);
     if (URI != NULL)
@@ -553,10 +521,6 @@
     xmlEntityPtr ret = NULL;
 
     if (ctx == NULL) return(NULL);
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2GetEntity(%s)\n", name);
-#endif
 
     if (ctxt->inSubset == 0) {
 	ret = xmlGetPredefinedEntity(name);
@@ -603,10 +567,6 @@
     xmlEntityPtr ret;
 
     if (ctx == NULL) return(NULL);
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
-#endif
 
     ret = xmlGetParameterEntity(ctxt->myDoc, name);
     return(ret);
@@ -632,11 +592,6 @@
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 
     if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
-            name, type, publicId, systemId, content);
-#endif
     if (ctxt->inSubset == 1) {
 	ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
 		              systemId, content);
@@ -709,11 +664,6 @@
     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
         return;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
-            elem, fullname, type, def, defaultValue);
-#endif
     if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
         (type != XML_ATTRIBUTE_ID)) {
 	/*
@@ -779,11 +729,6 @@
     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
         return;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-                    "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
-#endif
-
     if (ctxt->inSubset == 1)
         elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
                                  name, (xmlElementTypeVal) type, content);
@@ -828,11 +773,6 @@
     if ((ctxt == NULL) || (ctxt->myDoc == NULL))
         return;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
-#endif
-
     if ((publicId == NULL) && (systemId == NULL)) {
 	xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
 	     "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
@@ -877,11 +817,6 @@
     xmlEntityPtr ent;
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
-            name, publicId, systemId, notationName);
-#endif
     if (ctxt->inSubset == 1) {
 	ent = xmlAddDocEntity(ctxt->myDoc, name,
 			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
@@ -940,11 +875,6 @@
 void
 xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
 {
-    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2SetDocumentLocator()\n");
-#endif
 }
 
 /**
@@ -961,10 +891,6 @@
 
     if (ctx == NULL) return;
 
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2StartDocument()\n");
-#endif
     if (ctxt->html) {
 #ifdef LIBXML_HTML_ENABLED
 	if (ctxt->myDoc == NULL)
@@ -990,10 +916,6 @@
 	    if (ctxt->options & XML_PARSE_OLD10)
 	        doc->properties |= XML_DOC_OLD10;
 	    doc->parseFlags = ctxt->options;
-	    if (ctxt->encoding != NULL)
-		doc->encoding = xmlStrdup(ctxt->encoding);
-	    else
-		doc->encoding = NULL;
 	    doc->standalone = ctxt->standalone;
 	} else {
 	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
@@ -1022,10 +944,8 @@
 xmlSAX2EndDocument(void *ctx)
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2EndDocument()\n");
-#endif
+    xmlDocPtr doc;
+
     if (ctx == NULL) return;
 #ifdef LIBXML_VALID_ENABLED
     if (ctxt->validate && ctxt->wellFormed &&
@@ -1033,23 +953,25 @@
 	ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
 #endif /* LIBXML_VALID_ENABLED */
 
-    /*
-     * Grab the encoding if it was added on-the-fly
-     */
-    if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->encoding == NULL)) {
-	ctxt->myDoc->encoding = ctxt->encoding;
-	ctxt->encoding = NULL;
-    }
-    if ((ctxt->inputTab != NULL) &&
-        (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
-        (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->encoding == NULL)) {
-	ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
-    }
-    if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
-	ctxt->myDoc->charset = ctxt->charset;
+    doc = ctxt->myDoc;
+    if ((doc != NULL) && (doc->encoding == NULL)) {
+        const xmlChar *encoding = NULL;
+
+        if ((ctxt->input->flags & XML_INPUT_USES_ENC_DECL) ||
+            (ctxt->input->flags & XML_INPUT_AUTO_ENCODING)) {
+            /* Preserve encoding exactly */
+            encoding = ctxt->encoding;
+        } else if ((ctxt->input->buf) && (ctxt->input->buf->encoder)) {
+            encoding = BAD_CAST ctxt->input->buf->encoder->name;
+        } else if (ctxt->input->flags & XML_INPUT_HAS_ENCODING) {
+            encoding = BAD_CAST "UTF-8";
+        }
+
+        if (encoding != NULL) {
+            doc->encoding = xmlStrdup(encoding);
+            if (doc->encoding == NULL)
+                xmlSAX2ErrMemory(ctxt, "xmlSAX2EndDocument");
+        }
     }
 }
 
@@ -1612,11 +1534,6 @@
     int i;
 
     if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
-    parent = ctxt->node;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2StartElement(%s)\n", fullname);
-#endif
 
     /*
      * First check on validity:
@@ -1654,14 +1571,6 @@
 	xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
         return;
     }
-    if (ctxt->myDoc->children == NULL) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
-#endif
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-    } else if (parent == NULL) {
-        parent = ctxt->myDoc->children;
-    }
     ctxt->nodemem = -1;
     if (ctxt->linenumbers) {
 	if (ctxt->input != NULL) {
@@ -1672,12 +1581,14 @@
 	}
     }
 
+    /* Initialize parent before pushing node */
+    parent = ctxt->node;
+    if (parent == NULL)
+        parent = (xmlNodePtr) ctxt->myDoc;
+
     /*
      * We are parsing a new node.
      */
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
-#endif
     if (nodePush(ctxt, ret) < 0) {
         xmlUnlinkNode(ret);
         xmlFreeNode(ret);
@@ -1689,22 +1600,7 @@
     /*
      * Link the child element
      */
-    if (parent != NULL) {
-        if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "adding child %s to %s\n", name, parent->name);
-#endif
-	    xmlAddChild(parent, ret);
-	} else {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "adding sibling %s to ", name);
-	    xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
-	    xmlAddSibling(parent, ret);
-	}
-    }
+    xmlAddChild(parent, ret);
 
     if (!ctxt->html) {
         /*
@@ -1819,16 +1715,8 @@
 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
 {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr cur;
 
     if (ctx == NULL) return;
-    cur = ctxt->node;
-#ifdef DEBUG_SAX
-    if (name == NULL)
-        xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
-    else
-	xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
-#endif
 
     ctxt->nodemem = -1;
 
@@ -1836,16 +1724,13 @@
     if (ctxt->validate && ctxt->wellFormed &&
         ctxt->myDoc && ctxt->myDoc->intSubset)
         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
-					     cur);
+					     ctxt->node);
 #endif /* LIBXML_VALID_ENABLED */
 
 
     /*
      * end of parsing of this node.
      */
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
-#endif
     nodePop(ctxt);
 }
 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */
@@ -1921,18 +1806,6 @@
     } else
 	ret->content = (xmlChar *) intern;
 
-    if (ctxt->linenumbers) {
-	if (ctxt->input != NULL) {
-	    if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
-		ret->line = ctxt->input->line;
-	    else {
-	        ret->line = USHRT_MAX;
-		if (ctxt->options & XML_PARSE_BIG_LINES)
-		    ret->psvi = (void *) (ptrdiff_t) ctxt->input->line;
-	    }
-	}
-    }
-
     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
 	xmlRegisterNodeDefaultValue(ret);
     return(ret);
@@ -2227,7 +2100,6 @@
     int i, j;
 
     if (ctx == NULL) return;
-    parent = ctxt->node;
     /*
      * First check on validity:
      */
@@ -2305,9 +2177,6 @@
 	}
     }
 
-    if (parent == NULL) {
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-    }
     /*
      * Build the namespace list
      */
@@ -2342,6 +2211,11 @@
     }
     ctxt->nodemem = -1;
 
+    /* Initialize parent before pushing node */
+    parent = ctxt->node;
+    if (parent == NULL)
+        parent = (xmlNodePtr) ctxt->myDoc;
+
     /*
      * We are parsing a new node.
      */
@@ -2354,13 +2228,7 @@
     /*
      * Link the child element
      */
-    if (parent != NULL) {
-        if (parent->type == XML_ELEMENT_NODE) {
-	    xmlAddChild(parent, ret);
-	} else {
-	    xmlAddSibling(parent, ret);
-	}
-    }
+    xmlAddChild(parent, ret);
 
     /*
      * Insert the defaulted attributes from the DTD only if requested:
@@ -2499,18 +2367,7 @@
     xmlNodePtr ret;
 
     if (ctx == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2Reference(%s)\n", name);
-#endif
-    if (name[0] == '#')
-	ret = xmlNewCharRef(ctxt->myDoc, name);
-    else
-	ret = xmlNewReference(ctxt->myDoc, name);
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
-#endif
+    ret = xmlNewReference(ctxt->myDoc, name);
     if (xmlAddChild(ctxt->node, ret) == NULL) {
         xmlFreeNode(ret);
     }
@@ -2532,10 +2389,6 @@
     xmlNodePtr lastChild;
 
     if (ctxt == NULL) return;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
-#endif
     /*
      * Handle the data if any. If there is no child
      * add it as content, otherwise if the last child is text,
@@ -2543,17 +2396,9 @@
      */
 
     if (ctxt->node == NULL) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"add chars: ctxt->node == NULL !\n");
-#endif
         return;
     }
     lastChild = ctxt->node->last;
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "add chars to %s \n", ctxt->node->name);
-#endif
 
     /*
      * Here we needed an accelerator mechanism in case of very large
@@ -2652,6 +2497,19 @@
 	    }
 	}
     }
+
+    if ((lastChild != NULL) &&
+        (type == XML_TEXT_NODE) &&
+        (ctxt->linenumbers) &&
+        (ctxt->input != NULL)) {
+        if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
+            lastChild->line = ctxt->input->line;
+        else {
+            lastChild->line = USHRT_MAX;
+            if (ctxt->options & XML_PARSE_BIG_LINES)
+                lastChild->psvi = (void *) (ptrdiff_t) ctxt->input->line;
+        }
+    }
 }
 
 /**
@@ -2680,11 +2538,6 @@
 void
 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
 {
-    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
-#endif
 }
 
 /**
@@ -2705,10 +2558,6 @@
 
     if (ctx == NULL) return;
     parent = ctxt->node;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
-#endif
 
     ret = xmlNewDocPI(ctxt->myDoc, target, data);
     if (ret == NULL) return;
@@ -2729,25 +2578,12 @@
 	return;
     }
     if (parent == NULL) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Setting PI %s as root\n", target);
-#endif
         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
 	return;
     }
     if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding PI %s child to %s\n", target, parent->name);
-#endif
 	xmlAddChild(parent, ret);
     } else {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding PI %s sibling to ", target);
-	xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
 	xmlAddSibling(parent, ret);
     }
 }
@@ -2768,9 +2604,6 @@
 
     if (ctx == NULL) return;
     parent = ctxt->node;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
-#endif
     ret = xmlNewDocComment(ctxt->myDoc, value);
     if (ret == NULL) return;
     if (ctxt->linenumbers) {
@@ -2790,25 +2623,12 @@
 	return;
     }
     if (parent == NULL) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Setting xmlSAX2Comment as root\n");
-#endif
         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
 	return;
     }
     if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding xmlSAX2Comment child to %s\n", parent->name);
-#endif
 	xmlAddChild(parent, ret);
     } else {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding xmlSAX2Comment sibling to ");
-	xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
 	xmlAddSibling(parent, ret);
     }
 }
diff --git a/third_party/libxml/src/buf.c b/third_party/libxml/src/buf.c
index fbaf926..e0afd798 100644
--- a/third_party/libxml/src/buf.c
+++ b/third_party/libxml/src/buf.c
@@ -21,8 +21,6 @@
 #include <stdlib.h>
 
 #include <libxml/tree.h>
-#include <libxml/globals.h>
-#include <libxml/tree.h>
 #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
 
 #include "private/buf.h"
@@ -225,10 +223,6 @@
 int
 xmlBufGetAllocationScheme(xmlBufPtr buf) {
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufGetAllocationScheme: buf == NULL\n");
-#endif
         return(-1);
     }
     return(buf->alloc);
@@ -247,10 +241,6 @@
 xmlBufSetAllocationScheme(xmlBufPtr buf,
                           xmlBufferAllocationScheme scheme) {
     if ((buf == NULL) || (buf->error != 0)) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufSetAllocationScheme: buf == NULL or in error\n");
-#endif
         return(-1);
     }
     if (buf->alloc == XML_BUFFER_ALLOC_IO)
@@ -285,10 +275,6 @@
 void
 xmlBufFree(xmlBufPtr buf) {
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufFree: buf == NULL\n");
-#endif
 	return;
     }
 
@@ -479,17 +465,9 @@
     size_t ret;
 
     if ((buf == NULL) || (buf->error != 0)) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufDump: buf == NULL or in error\n");
-#endif
 	return(0);
     }
     if (buf->content == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufDump: buf->content == NULL\n");
-#endif
 	return(0);
     }
     CHECK_COMPAT(buf)
@@ -785,10 +763,6 @@
     CHECK_COMPAT(buf)
 
     if (len < -1) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufAdd: len < 0\n");
-#endif
 	return -1;
     }
     if (len == 0) return 0;
@@ -882,10 +856,6 @@
     CHECK_COMPAT(buf)
     if (xmlStrchr(string, '\"')) {
         if (xmlStrchr(string, '\'')) {
-#ifdef DEBUG_BUFFER
-	    xmlGenericError(xmlGenericErrorContext,
- "xmlBufWriteQuotedString: string contains quote and double-quotes !\n");
-#endif
 	    xmlBufCCat(buf, "\"");
             base = cur = string;
             while(*cur != 0){
@@ -1056,39 +1026,10 @@
 }
 
 /**
- * xmlBufGetInputBase:
+ * xmlBufUpdateInput:
  * @buf: an xmlBufPtr
  * @input: an xmlParserInputPtr
- *
- * Get the base of the @input relative to the beginning of the buffer
- *
- * Returns the size_t corresponding to the displacement
- */
-size_t
-xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) {
-    size_t base;
-
-    if ((input == NULL) || (buf == NULL) || (buf->error))
-        return(0);
-    CHECK_COMPAT(buf)
-    base = input->base - buf->content;
-    /*
-     * We could do some pointer arithmetic checks but that's probably
-     * sufficient.
-     */
-    if (base > buf->size) {
-        xmlBufOverflowError(buf, "Input reference outside of the buffer");
-        base = 0;
-    }
-    return(base);
-}
-
-/**
- * xmlBufSetInputBaseCur:
- * @buf: an xmlBufPtr
- * @input: an xmlParserInputPtr
- * @base: the base value relative to the beginning of the buffer
- * @cur: the cur value relative to the beginning of the buffer
+ * @pos: the cur value relative to the beginning of the buffer
  *
  * Update the input to use the base and cur relative to the buffer
  * after a possible reallocation of its content
@@ -1096,8 +1037,7 @@
  * Returns -1 in case of error, 0 otherwise
  */
 int
-xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
-                      size_t base, size_t cur) {
+xmlBufUpdateInput(xmlBufPtr buf, xmlParserInputPtr input, size_t pos) {
     if (input == NULL)
         return(-1);
     /*
@@ -1109,8 +1049,8 @@
         return(-1);
     }
     CHECK_COMPAT(buf)
-    input->base = &buf->content[base];
-    input->cur = input->base + cur;
+    input->base = buf->content;
+    input->cur = input->base + pos;
     input->end = &buf->content[buf->use];
     return(0);
 }
diff --git a/third_party/libxml/src/config.h.cmake.in b/third_party/libxml/src/config.h.cmake.in
index 0d8c341f..8fd47dea 100644
--- a/third_party/libxml/src/config.h.cmake.in
+++ b/third_party/libxml/src/config.h.cmake.in
@@ -60,9 +60,6 @@
 /* Define if <pthread.h> is there */
 #cmakedefine HAVE_PTHREAD_H 1
 
-/* Define to 1 if you have the `rand_r' function. */
-#cmakedefine HAVE_RAND_R 1
-
 /* Have shl_load based dso */
 #cmakedefine HAVE_SHLLOAD 1
 
diff --git a/third_party/libxml/src/config.h.in b/third_party/libxml/src/config.h.in
index 66139ba..440eb48f 100644
--- a/third_party/libxml/src/config.h.in
+++ b/third_party/libxml/src/config.h.in
@@ -68,9 +68,6 @@
 /* Define to 1 if you have the <pthread.h> header file. */
 #undef HAVE_PTHREAD_H
 
-/* Define to 1 if you have the `rand_r' function. */
-#undef HAVE_RAND_R
-
 /* Have shl_load based dso */
 #undef HAVE_SHLLOAD
 
@@ -172,6 +169,9 @@
 /* Determine what socket length (socklen_t) data type is */
 #undef XML_SOCKLEN_T
 
+/* TLS specifier */
+#undef XML_THREAD_LOCAL
+
 /* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
    <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
    #define below would cause a syntax error. */
diff --git a/third_party/libxml/src/configure.ac b/third_party/libxml/src/configure.ac
index 08e03f5d..c3071b7 100644
--- a/third_party/libxml/src/configure.ac
+++ b/third_party/libxml/src/configure.ac
@@ -64,79 +64,81 @@
 dnl
 
 AC_ARG_WITH(c14n,
-[  --with-c14n             add the Canonicalization support (on)])
+[  --with-c14n             Canonical XML 1.0 support (on)])
 AC_ARG_WITH(catalog,
-[  --with-catalog          add the Catalog support (on)])
+[  --with-catalog          XML Catalogs support (on)])
 AC_ARG_WITH(debug,
-[  --with-debug            add the debugging module (on)])
-AC_ARG_WITH(fexceptions,
-[  --with-fexceptions      add GCC flag -fexceptions for C++ exceptions (off)])
+[  --with-debug            debugging module and shell (on)])
 AC_ARG_WITH(ftp,
-[  --with-ftp              add the FTP support (off)])
+[  --with-ftp              FTP support (off)])
 AC_ARG_WITH(history,
-[  --with-history          add history support to xmllint shell(off)])
+[  --with-history          history support for shell (off)])
+AC_ARG_WITH(readline,
+[  --with-readline[[=DIR]]   use readline in DIR (for shell history)])
 AC_ARG_WITH(html,
-[  --with-html             add the HTML support (on)])
+[  --with-html             HTML parser (on)])
 AC_ARG_WITH(http,
-[  --with-http             add the HTTP support (on)])
+[  --with-http             HTTP support (on)])
 AC_ARG_WITH(iconv,
-[  --with-iconv[[=DIR]]      add ICONV support (on)])
+[  --with-iconv[[=DIR]]      iconv support (on)])
 AC_ARG_WITH(icu,
-[  --with-icu                add ICU support (off)])
+[  --with-icu              ICU support (off)])
 AC_ARG_WITH(iso8859x,
-[  --with-iso8859x         add ISO8859X support if no iconv (on)])
-AC_ARG_WITH(legacy,
-[  --with-legacy           add deprecated APIs for compatibility (off)])
+[  --with-iso8859x         ISO-8859-X support if no iconv (on)])
+AC_ARG_WITH(lzma,
+[  --with-lzma[[=DIR]]       use liblzma in DIR (on)])
 AC_ARG_WITH(mem_debug,
-[  --with-mem-debug        add the memory debugging module (off)])
+[  --with-mem-debug        memory debugging module (off)])
+AC_ARG_WITH(modules,
+[  --with-modules          dynamic modules support (on)])
+AC_ARG_WITH(output,
+[  --with-output           serialization support (on)])
+AC_ARG_WITH(pattern,
+[  --with-pattern          xmlPattern selection interface (on)])
+AC_ARG_WITH(push,
+[  --with-push             push parser interfaces (on)])
+AC_ARG_WITH(python,
+[  --with-python           Python bindings (on)])
+AC_ARG_WITH(reader,
+[  --with-reader           xmlReader parsing interface (on)])
+AC_ARG_WITH(regexps,
+[  --with-regexps          regular expressions support (on)])
+AC_ARG_WITH(run_debug,
+[  --with-run-debug        runtime debugging module (off)])
+AC_ARG_WITH(sax1,
+[  --with-sax1             older SAX1 interface (on)])
+AC_ARG_WITH(schemas,
+[  --with-schemas          XML Schemas 1.0 and RELAX NG support (on)])
+AC_ARG_WITH(schematron,
+[  --with-schematron       Schematron support (on)])
+AC_ARG_WITH(threads,
+[  --with-threads          multithreading support (on)])
+AC_ARG_WITH(thread-alloc,
+[  --with-thread-alloc     per-thread malloc hooks (off)])
+AC_ARG_WITH(tree,
+[  --with-tree             DOM like tree manipulation APIs (on)])
+AC_ARG_WITH(valid,
+[  --with-valid            DTD validation support (on)])
+AC_ARG_WITH(writer,
+[  --with-writer           xmlWriter serialization interface (on)])
+AC_ARG_WITH(xinclude,
+[  --with-xinclude         XInclude 1.0 support (on)])
+AC_ARG_WITH(xpath,
+[  --with-xpath            XPath 1.0 support (on)])
+AC_ARG_WITH(xptr,
+[  --with-xptr             XPointer support (on)])
+AC_ARG_WITH(zlib,
+[  --with-zlib[[=DIR]]       use libz in DIR (on)])
+
 AC_ARG_WITH(minimum,
 [  --with-minimum          build a minimally sized library (off)])
-AC_ARG_WITH(output,
-[  --with-output           add the serialization support (on)])
-AC_ARG_WITH(pattern,
-[  --with-pattern          add the xmlPattern selection interface (on)])
-AC_ARG_WITH(push,
-[  --with-push             add the PUSH parser interfaces (on)])
-AC_ARG_WITH(python,
-[  --with-python           build Python bindings (on)])
-AC_ARG_WITH(reader,
-[  --with-reader           add the xmlReader parsing interface (on)])
-AC_ARG_WITH(readline,
-[  --with-readline[[=DIR]]   use readline in DIR])
-AC_ARG_WITH(regexps,
-[  --with-regexps          add Regular Expressions support (on)])
-AC_ARG_WITH(run_debug,
-[  --with-run-debug        add the runtime debugging module (off)])
-AC_ARG_WITH(sax1,
-[  --with-sax1             add the older SAX1 interface (on)])
-AC_ARG_WITH(schemas,
-[  --with-schemas          add Relax-NG and Schemas support (on)])
-AC_ARG_WITH(schematron,
-[  --with-schematron       add Schematron support (on)])
-AC_ARG_WITH(threads,
-[  --with-threads          add multithread support(on)])
-AC_ARG_WITH(thread-alloc,
-[  --with-thread-alloc     add per-thread memory(off)])
-AC_ARG_WITH(tree,
-[  --with-tree             add the DOM like tree manipulation APIs (on)])
-AC_ARG_WITH(valid,
-[  --with-valid            add the DTD validation support (on)])
-AC_ARG_WITH(writer,
-[  --with-writer           add the xmlWriter saving interface (on)])
-AC_ARG_WITH(xinclude,
-[  --with-xinclude         add the XInclude support (on)])
-AC_ARG_WITH(xpath,
-[  --with-xpath            add the XPATH support (on)])
-AC_ARG_WITH(xptr,
-[  --with-xptr             add the XPointer support (on)])
-AC_ARG_WITH(xptr-locs,
-[  --with-xptr-locs        add support for XPointer locations (off)])
-AC_ARG_WITH(modules,
-[  --with-modules          add the dynamic modules support (on)])
-AC_ARG_WITH(zlib,
-[  --with-zlib[[=DIR]]       use libz in DIR])
-AC_ARG_WITH(lzma,
-[  --with-lzma[[=DIR]]       use liblzma in DIR])
+AC_ARG_WITH(legacy,
+[  --with-legacy           maximum ABI compatibility (off)])
+
+AC_ARG_WITH(tls,
+[  --with-tls              thread-local storage (on)])
+AC_ARG_WITH(fexceptions,
+[  --with-fexceptions      add GCC flag -fexceptions for C++ exceptions (off)])
 AC_ARG_WITH(coverage,
 [  --with-coverage         build for code coverage with GCC (off)])
 
@@ -230,6 +232,7 @@
     test "$with_http" = "" && with_http=no
     test "$with_iconv" = "" && with_iconv=no
     test "$with_iso8859x" = "" && with_iso8859x=no
+    test "$with_lzma" = "" && with_lzma=no
     test "$with_mem_debug" = "" && with_mem_debug=no
     test "$with_output" = "" && with_output=no
     test "$with_pattern" = "" && with_pattern=no
@@ -283,6 +286,11 @@
     fi
 fi
 
+XML_PRIVATE_LIBS=
+XML_PRIVATE_CFLAGS=
+XML_PC_LIBS=
+XML_PC_REQUIRES=
+
 dnl
 dnl Checks for header files.
 dnl
@@ -307,7 +315,7 @@
 AC_CHECK_FUNCS(snprintf vsnprintf,, NEED_TRIO=1)
 
 dnl Checks for library functions.
-AC_CHECK_FUNCS([gettimeofday ftime stat rand_r isascii mmap munmap])
+AC_CHECK_FUNCS([gettimeofday ftime stat isascii mmap munmap])
 
 AH_VERBATIM([HAVE_MUNMAP_AFTER],[/* mmap() is no good without munmap() */
 #if defined(HAVE_MMAP) && !defined(HAVE_MUNMAP)
@@ -435,6 +443,20 @@
 XML_INCLUDEDIR='-I${includedir}/libxml2'
 XML_CFLAGS=""
 
+dnl Thread-local storage
+if test "$with_tls" != "no"; then
+    AC_COMPILE_IFELSE([
+        AC_LANG_SOURCE([_Thread_local int v;]) ], [
+        AC_DEFINE([XML_THREAD_LOCAL], [_Thread_local], [TLS specifier]) ], [
+    AC_COMPILE_IFELSE([
+        AC_LANG_SOURCE([__thread int v;]) ], [
+        AC_DEFINE([XML_THREAD_LOCAL], [__thread], [TLS specifier]) ], [
+    AC_COMPILE_IFELSE([
+        AC_LANG_SOURCE([__declspec(thread) int v;]) ], [
+        AC_DEFINE([XML_THREAD_LOCAL], [__declspec(thread)], [TLS specifier]) ], [
+    WARN_NO_TLS=1 ])])])
+fi
+
 dnl Checking whether __attribute__((destructor)) is accepted by the compiler
 AC_MSG_CHECKING([whether __attribute__((destructor)) is accepted])
 AC_TRY_COMPILE2([
@@ -497,7 +519,7 @@
     fi
 
     # warnings we'd like to see
-    AM_CFLAGS="${AM_CFLAGS} -pedantic -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline"
+    AM_CFLAGS="${AM_CFLAGS} -pedantic -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes"
     # warnings we'd like to suppress
     AM_CFLAGS="${AM_CFLAGS} -Wno-long-long -Wno-format-extra-args"
     case "${host}" in
@@ -828,7 +850,7 @@
 if test "${NEED_TRIO}" = "1" ; then
     echo Adding trio library for string functions
     WITH_TRIO=1
-else    
+else
     WITH_TRIO=0
 fi
 AM_CONDITIONAL(WITH_TRIO_SOURCES, test "${NEED_TRIO}" = "1")
@@ -947,7 +969,7 @@
     if test "x$Z_DIR" = "x"; then
         # Try pkg-config first so that static linking works.
         PKG_CHECK_MODULES([Z],[zlib],
-            [WITH_ZLIB=1],
+            [WITH_ZLIB=1; XML_PC_REQUIRES="${XML_PC_REQUIRES} zlib"],
             [:])
     fi
 
@@ -972,10 +994,14 @@
                 else
                     Z_LIBS="-lz"
                 fi])
+                XML_PC_LIBS="${XML_PC_LIBS} ${Z_LIBS}"
             )
         CPPFLAGS=$_cppflags
         LIBS=$_libs
     fi
+
+    XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${Z_CFLAGS}"
+    XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${Z_LIBS}"
 fi
 AC_SUBST(WITH_ZLIB)
 
@@ -995,7 +1021,7 @@
     if test "x$LZMA_DIR" = "x"; then
         # Try pkg-config first so that static linking works.
         PKG_CHECK_MODULES([LZMA],[liblzma],
-            [WITH_LZMA=1],
+            [WITH_LZMA=1; XML_PC_REQUIRES="${XML_PC_REQUIRES} liblzma"],
             [:])
     fi
 
@@ -1018,10 +1044,14 @@
                 else
                     LZMA_LIBS="-llzma"
                 fi])
+                XML_PC_LIBS="${XML_PC_LIBS} ${LZMA_LIBS}"
             )
         CPPFLAGS=$_cppflags
         LIBS=$_libs
     fi
+
+    XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${LZMA_CFLAGS}"
+    XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${LZMA_LIBS}"
 fi
 AC_SUBST(WITH_LZMA)
 AM_CONDITIONAL(WITH_LZMA_SOURCES, test "$WITH_LZMA" = "1")
@@ -1075,15 +1105,14 @@
 dnl Checks for ICU library.
 dnl
 WITH_ICU=0
-ICU_LIBS=""
 
-if test "$with_icu" != "yes" ; then
+if test "$with_icu" = "no" || test "$with_icu" = "" ; then
     echo Disabling ICU support
 else
     # Try pkg-config first so that static linking works.
     # If this succeeeds, we ignore the WITH_ICU directory.
     PKG_CHECK_MODULES([ICU], [icu-i18n], [
-        WITH_ICU=1
+        WITH_ICU=1; XML_PC_REQUIRES="${XML_PC_REQUIRES} icu-i18n"
         m4_ifdef([PKG_CHECK_VAR],
             [PKG_CHECK_VAR([ICU_DEFS], [icu-i18n], [DEFS])])
         if test "x$ICU_DEFS" != "x"; then
@@ -1097,10 +1126,11 @@
             WITH_ICU=1
             ICU_CFLAGS=`${ICU_CONFIG} --cflags`
             ICU_LIBS=`${ICU_CONFIG} --ldflags`
+            XML_PC_LIBS="${XML_PC_LIBS} ${ICU_LIBS}"
         else
-	    _cppflags="${CPPFLAGS}"
-	    _libs="${LIBS}"
-            if test "$with_icu" != "yes" && test "$with_icu" != "" ; then
+            _cppflags="${CPPFLAGS}"
+            _libs="${LIBS}"
+            if test "$with_icu" != "yes" ; then
                 ICU_DIR=$with_icu
                 CPPFLAGS="${CPPFLAGS} -I$ICU_DIR/include"
                 LIBS="${LIBS} -L$ICU_DIR/lib"
@@ -1114,10 +1144,14 @@
                         ICU_CFLAGS="-I$ICU_DIR/include"
                         ICU_LIBS="-L$ICU_DIR/lib $ICU_LIBS"
                     fi])])
+                    XML_PC_LIBS="${XML_PC_LIBS} ${ICU_LIBS}"
             CPPFLAGS=$_cppflags
             LIBS=$_libs
         fi
     fi
+
+    XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${ICU_CFLAGS}"
+    XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${ICU_LIBS}"
 fi
 AC_SUBST(WITH_ICU)
 
@@ -1132,8 +1166,35 @@
 
 XML_LIBS="-lxml2"
 XML_LIBTOOLLIBS="libxml2.la"
-XML_PRIVATE_LIBS="$Z_LIBS $LZMA_LIBS $THREAD_LIBS $ICONV_LIBS $ICU_LIBS $LIBM $NET_LIBS"
-XML_PRIVATE_CFLAGS="$Z_CFLAGS $LZMA_CFLAGS $THREAD_CFLAGS $ICONV_CFLAGS $ICU_CFLAGS"
+NON_PC_LIBS="${THREAD_LIBS} ${ICONV_LIBS} ${LIBM} ${NET_LIBS}"
+XML_PC_LIBS="${XML_PC_LIBS} ${NON_PC_LIBS}"
+XML_PRIVATE_LIBS="${XML_PRIVATE_LIBS} ${NON_PC_LIBS}"
+XML_PRIVATE_CFLAGS="${XML_PRIVATE_CFLAGS} ${THREAD_CFLAGS} ${ICONV_CFLAGS}"
+
+dnl When static-only:
+dnl * Duplicate xml-config static --libs into --dynamic.
+dnl * Fold pkg-config private fields into main fields.
+if test "x$enable_shared" = "xno"; then
+  XML_PRIVATE_LIBS_NO_SHARED="${XML_PRIVATE_LIBS}"
+  XML_PC_PRIVATE=
+  XML_PC_LIBS_PRIVATE=
+else
+  XML_PRIVATE_LIBS_NO_SHARED=
+  XML_PC_PRIVATE=".private"
+  XML_PC_LIBS_PRIVATE="
+Libs.private:"
+fi
+AC_SUBST(XML_PRIVATE_LIBS_NO_SHARED)
+AC_SUBST(XML_PC_PRIVATE)
+AC_SUBST(XML_PC_LIBS_PRIVATE)
+AM_SUBST_NOTMAKE(XML_PRIVATE_LIBS_NO_SHARED)
+AM_SUBST_NOTMAKE(XML_PC_PRIVATE)
+AM_SUBST_NOTMAKE(XML_PC_LIBS_PRIVATE)
+
+AC_SUBST(XML_PC_LIBS)
+AC_SUBST(XML_PC_REQUIRES)
+AM_SUBST_NOTMAKE(XML_PC_LIBS)
+AM_SUBST_NOTMAKE(XML_PC_REQUIRES)
 
 AC_SUBST(AM_CFLAGS)
 AC_SUBST(AM_LDFLAGS)
@@ -1156,10 +1217,10 @@
 AC_CONFIG_FILES([xml2-config], [chmod +x xml2-config])
 AC_OUTPUT
 
-AC_COMPILE_IFELSE([AC_LANG_SOURCE([_Thread_local int v;])], [], [
+if test "$WARN_NO_TLS" != ""; then
     echo "================================================================"
-    echo "WARNING: Your C compiler doesn't support C11."
-    echo "Future versions of libxml2 will probably require a C11 compiler,"
-    echo "at least for features like multi-threading."
+    echo "WARNING: Your C compiler appears to not support thread-local"
+    echo "storage. Future versions of libxml2 will require this feature"
+    echo "for multi-threading."
     echo "================================================================"
-])
+fi
diff --git a/third_party/libxml/src/dict.c b/third_party/libxml/src/dict.c
index 67b2a2e..c804939 100644
--- a/third_party/libxml/src/dict.c
+++ b/third_party/libxml/src/dict.c
@@ -20,12 +20,17 @@
 #include "libxml.h"
 
 #include <limits.h>
-#include <stdlib.h>
+#include <string.h>
 #include <time.h>
 
 #include "private/dict.h"
 #include "private/threads.h"
 
+#include <libxml/parser.h>
+#include <libxml/dict.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlerror.h>
+
 /*
  * Following http://www.ocert.org/advisories/ocert-2011-003.html
  * it seems that having hash randomization might be a good idea
@@ -41,28 +46,13 @@
 #define DICT_RANDOMIZATION
 #endif
 
-#include <string.h>
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#else
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#elif defined(_WIN32)
-typedef unsigned __int32 uint32_t;
-#endif
-#endif
-#include <libxml/tree.h>
-#include <libxml/dict.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/xmlerror.h>
-#include <libxml/globals.h>
-
 /* #define DEBUG_GROW */
 /* #define DICT_DEBUG_PATTERNS */
 
-#define MAX_HASH_LEN 3
+#define MAX_HASH_LEN 16
+#define MAX_FILL 2
+#define GROWTH_FACTOR 4
 #define MIN_DICT_SIZE 128
-#define MAX_DICT_HASH 100000000
 #define WITH_BIG_KEY
 
 #ifdef WITH_BIG_KEY
@@ -95,7 +85,7 @@
     const xmlChar *name;
     unsigned int len;
     int valid;
-    unsigned long okey;
+    unsigned okey;
 };
 
 typedef struct _xmlDictStrings xmlDictStrings;
@@ -121,7 +111,7 @@
 
     struct _xmlDict *subdict;
     /* used for randomization */
-    int seed;
+    unsigned seed;
     /* used to impose a limit on size */
     size_t limit;
 };
@@ -132,13 +122,14 @@
  */
 static xmlMutex xmlDictMutex;
 
-#ifdef DICT_RANDOMIZATION
-#ifdef HAVE_RAND_R
 /*
  * Internal data for random function, protected by xmlDictMutex
  */
-static unsigned int rand_seed = 0;
-#endif
+static unsigned globalRngState[2];
+
+#ifdef XML_THREAD_LOCAL
+XML_THREAD_LOCAL static int localRngInitialized = 0;
+XML_THREAD_LOCAL static unsigned localRngState[2];
 #endif
 
 /**
@@ -146,45 +137,74 @@
  *
  * DEPRECATED: Alias for xmlInitParser.
  */
-int xmlInitializeDict(void) {
+int
+xmlInitializeDict(void) {
     xmlInitParser();
     return(0);
 }
 
 /**
- * __xmlInitializeDict:
+ * xmlInitializeDict:
  *
- * This function is not public
- * Do the dictionary mutex initialization.
+ * Initialize mutex and global PRNG seed.
  */
-int __xmlInitializeDict(void) {
+#ifdef __clang__
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
+#endif
+void
+xmlInitDictInternal(void) {
+    int var;
+
     xmlInitMutex(&xmlDictMutex);
 
-#ifdef DICT_RANDOMIZATION
-#ifdef HAVE_RAND_R
-    rand_seed = time(NULL);
-    rand_r(& rand_seed);
-#else
-    srand(time(NULL));
-#endif
-#endif
-    return(1);
+    /* TODO: Get seed values from system PRNG */
+
+    globalRngState[0] = (unsigned) time(NULL) ^
+                        HASH_ROL((unsigned) (size_t) &xmlInitializeDict, 8);
+    globalRngState[1] = HASH_ROL((unsigned) (size_t) &xmlDictMutex, 16) ^
+                        HASH_ROL((unsigned) (size_t) &var, 24);
 }
 
-#ifdef DICT_RANDOMIZATION
-int __xmlRandom(void) {
-    int ret;
+#ifdef __clang__
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
+#endif
+static unsigned
+xoroshiro64ss(unsigned *s) {
+    unsigned s0 = s[0];
+    unsigned s1 = s[1];
+    unsigned result = HASH_ROL(s0 * 0x9E3779BB, 5) * 5;
+
+    s1 ^= s0;
+    s[0] = HASH_ROL(s0, 26) ^ s1 ^ (s1 << 9);
+    s[1] = HASH_ROL(s1, 13);
+
+    return(result & 0xFFFFFFFF);
+}
+
+unsigned
+xmlRandom(void) {
+#ifdef XML_THREAD_LOCAL
+    if (!localRngInitialized) {
+        xmlMutexLock(&xmlDictMutex);
+        localRngState[0] = xoroshiro64ss(globalRngState);
+        localRngState[1] = xoroshiro64ss(globalRngState);
+        localRngInitialized = 1;
+        xmlMutexUnlock(&xmlDictMutex);
+    }
+
+    return(xoroshiro64ss(localRngState));
+#else
+    unsigned ret;
 
     xmlMutexLock(&xmlDictMutex);
-#ifdef HAVE_RAND_R
-    ret = rand_r(& rand_seed);
-#else
-    ret = rand();
-#endif
+    ret = xoroshiro64ss(globalRngState);
     xmlMutexUnlock(&xmlDictMutex);
+
     return(ret);
-}
 #endif
+}
 
 /**
  * xmlDictCleanup:
@@ -347,34 +367,28 @@
  *
  * Calculate a hash key using a good hash function that works well for
  * larger hash table sizes.
- *
- * Hash function by "One-at-a-Time Hash" see
- * http://burtleburtle.net/bob/hash/doobs.html
  */
 
 #ifdef __clang__
 ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
 ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
 #endif
-static uint32_t
-xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
-    uint32_t hash;
+static unsigned
+xmlDictComputeBigKey(const xmlChar* data, int namelen, unsigned seed) {
+    unsigned h1, h2;
     int i;
 
     if (namelen <= 0 || data == NULL) return(0);
 
-    hash = seed;
+    HASH_INIT(h1, h2, seed);
 
-    for (i = 0;i < namelen; i++) {
-        hash += data[i];
-	hash += (hash << 10);
-	hash ^= (hash >> 6);
+    for (i = 0; i < namelen; i++) {
+        HASH_UPDATE(h1, h2, data[i]);
     }
-    hash += (hash << 3);
-    hash ^= (hash >> 11);
-    hash += (hash << 15);
 
-    return hash;
+    HASH_FINISH(h1, h2);
+
+    return h2;
 }
 
 /*
@@ -392,34 +406,27 @@
 ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
 ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
 #endif
-static unsigned long
+static unsigned
 xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
-                      const xmlChar *name, int len, int seed)
+                      const xmlChar *name, int len, unsigned seed)
 {
-    uint32_t hash;
+    unsigned h1, h2;
     int i;
 
-    hash = seed;
+    HASH_INIT(h1, h2, seed);
 
-    for (i = 0;i < plen; i++) {
-        hash += prefix[i];
-	hash += (hash << 10);
-	hash ^= (hash >> 6);
+    for (i = 0; i < plen; i++) {
+        HASH_UPDATE(h1, h2, prefix[i]);
     }
-    hash += ':';
-    hash += (hash << 10);
-    hash ^= (hash >> 6);
+    HASH_UPDATE(h1, h2, ':');
 
-    for (i = 0;i < len; i++) {
-        hash += name[i];
-	hash += (hash << 10);
-	hash ^= (hash >> 6);
+    for (i = 0; i < len; i++) {
+        HASH_UPDATE(h1, h2, name[i]);
     }
-    hash += (hash << 3);
-    hash ^= (hash >> 11);
-    hash += (hash << 15);
 
-    return hash;
+    HASH_FINISH(h1, h2);
+
+    return h2;
 }
 #endif /* WITH_BIG_KEY */
 
@@ -429,9 +436,13 @@
  * Calculate a hash key using a fast hash function that works well
  * for low hash table fill.
  */
-static unsigned long
-xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
-    unsigned long value = seed;
+#ifdef __clang__
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
+#endif
+static unsigned
+xmlDictComputeFastKey(const xmlChar *name, int namelen, unsigned seed) {
+    unsigned value = seed;
 
     if ((name == NULL) || (namelen <= 0))
         return(value);
@@ -473,11 +484,15 @@
  *
  * Neither of the two strings must be NULL.
  */
-static unsigned long
+#ifdef __clang__
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
+#endif
+static unsigned
 xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
-                       const xmlChar *name, int len, int seed)
+                       const xmlChar *name, int len, unsigned seed)
 {
-    unsigned long value = seed;
+    unsigned value = seed;
 
     if (plen == 0)
 	value += 30 * ':';
@@ -577,7 +592,7 @@
         if (dict->dict) {
 	    memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
 #ifdef DICT_RANDOMIZATION
-            dict->seed = __xmlRandom();
+            dict->seed = xmlRandom();
 #else
             dict->seed = 0;
 #endif
@@ -642,28 +657,26 @@
  */
 static int
 xmlDictGrow(xmlDictPtr dict, size_t size) {
-    unsigned long key, okey;
+    unsigned key, okey;
     size_t oldsize, i;
     xmlDictEntryPtr iter, next;
     struct _xmlDictEntry *olddict;
 #ifdef DEBUG_GROW
-    unsigned long nbElem = 0;
+    unsigned nbElem = 0;
 #endif
     int ret = 0;
     int keep_keys = 1;
 
     if (dict == NULL)
 	return(-1);
-    if (size < 8)
-        return(-1);
-    if (size > MAX_DICT_HASH)
-	return(-1);
+    oldsize = dict->size;
+    if (size <= oldsize)
+	return(0);
 
 #ifdef DICT_DEBUG_PATTERNS
     fprintf(stderr, "*");
 #endif
 
-    oldsize = dict->size;
     olddict = dict->dict;
     if (olddict == NULL)
         return(-1);
@@ -836,11 +849,11 @@
  */
 const xmlChar *
 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
-    unsigned long key, okey, nbi = 0;
+    unsigned key, okey, nbi = 0;
     xmlDictEntryPtr entry;
     xmlDictEntryPtr insert;
     const xmlChar *ret;
-    unsigned int l;
+    size_t l;
 
     if ((dict == NULL) || (name == NULL))
 	return(NULL);
@@ -889,7 +902,7 @@
     }
 
     if (dict->subdict) {
-        unsigned long skey;
+        unsigned skey;
 
         /* we cannot always reuse the same okey for the subdict */
         if (((dict->size == MIN_DICT_SIZE) &&
@@ -954,9 +967,12 @@
 
     dict->nbElems++;
 
-    if ((nbi > MAX_HASH_LEN) &&
-        (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) {
-	if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0)
+    if ((dict->nbElems > dict->size / MAX_FILL) ||
+        (nbi > MAX_HASH_LEN)) {
+        int newSize = dict->size > INT_MAX / GROWTH_FACTOR ?
+                      INT_MAX :
+                      GROWTH_FACTOR * dict->size;
+	if (xmlDictGrow(dict, newSize) != 0)
 	    return(NULL);
     }
     /* Note that entry may have been freed at this point by xmlDictGrow */
@@ -976,9 +992,9 @@
  */
 const xmlChar *
 xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
-    unsigned long key, okey;
+    unsigned key, okey;
     xmlDictEntryPtr insert;
-    unsigned int l;
+    size_t l;
 
     if ((dict == NULL) || (name == NULL))
 	return(NULL);
@@ -1025,7 +1041,7 @@
     }
 
     if (dict->subdict) {
-        unsigned long skey;
+        unsigned skey;
 
         /* we cannot always reuse the same okey for the subdict */
         if (((dict->size == MIN_DICT_SIZE) &&
@@ -1082,11 +1098,11 @@
  */
 const xmlChar *
 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
-    unsigned long okey, key, nbi = 0;
+    unsigned okey, key, nbi = 0;
     xmlDictEntryPtr entry;
     xmlDictEntryPtr insert;
     const xmlChar *ret;
-    unsigned int len, plen, l;
+    size_t len, plen, l;
 
     if ((dict == NULL) || (name == NULL))
 	return(NULL);
@@ -1095,6 +1111,8 @@
 
     l = len = strlen((const char *) name);
     plen = strlen((const char *) prefix);
+    if ((len > INT_MAX / 2) || (plen > INT_MAX / 2))
+        return(NULL);
     len += 1 + plen;
 
     /*
@@ -1118,7 +1136,7 @@
     }
 
     if (dict->subdict) {
-        unsigned long skey;
+        unsigned skey;
 
         /* we cannot always reuse the same okey for the subdict */
         if (((dict->size == MIN_DICT_SIZE) &&
@@ -1167,9 +1185,14 @@
 
     dict->nbElems++;
 
-    if ((nbi > MAX_HASH_LEN) &&
-        (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
-	xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
+    if ((dict->nbElems > dict->size / MAX_FILL) ||
+        (nbi > MAX_HASH_LEN)) {
+        int newSize = dict->size > INT_MAX / GROWTH_FACTOR ?
+                      INT_MAX :
+                      GROWTH_FACTOR * dict->size;
+	if (xmlDictGrow(dict, newSize) != 0)
+	    return(NULL);
+    }
     /* Note that entry may have been freed at this point by xmlDictGrow */
 
     return(ret);
diff --git a/third_party/libxml/src/encoding.c b/third_party/libxml/src/encoding.c
index 3d461cd..bac65ac 100644
--- a/third_party/libxml/src/encoding.c
+++ b/third_party/libxml/src/encoding.c
@@ -34,10 +34,10 @@
 
 #include <libxml/encoding.h>
 #include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
 #ifdef LIBXML_HTML_ENABLED
 #include <libxml/HTMLparser.h>
 #endif
-#include <libxml/globals.h>
 #include <libxml/xmlerror.h>
 
 #include "private/buf.h"
@@ -69,13 +69,6 @@
 static int xmlCharEncodingAliasesNb = 0;
 static int xmlCharEncodingAliasesMax = 0;
 
-#if defined(LIBXML_ICONV_ENABLED) || defined(LIBXML_ICU_ENABLED)
-#if 0
-#define DEBUG_ENCODING  /* Define this to get encoding traces */
-#endif
-#else
-#endif
-
 static int xmlLittleEndian = 1;
 
 #ifdef LIBXML_ICU_ENABLED
@@ -691,10 +684,6 @@
 	    outb[1] = 0xFE;
 	    *outlen = 2;
 	    *inlen = 0;
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-		    "Added FFFE Byte Order Mark\n");
-#endif
 	    return(2);
 	}
 	*outlen = 0;
@@ -1222,9 +1211,6 @@
     if (!strcmp(upper, "SHIFT_JIS")) return(XML_CHAR_ENCODING_SHIFT_JIS);
     if (!strcmp(upper, "EUC-JP")) return(XML_CHAR_ENCODING_EUC_JP);
 
-#ifdef DEBUG_ENCODING
-    xmlGenericError(xmlGenericErrorContext, "Unknown encoding %s\n", name);
-#endif
     return(XML_CHAR_ENCODING_ERROR);
 }
 
@@ -1462,10 +1448,6 @@
      * registers and returns the handler.
      */
     xmlRegisterCharEncodingHandler(handler);
-#ifdef DEBUG_ENCODING
-    xmlGenericError(xmlGenericErrorContext,
-	    "Registered encoding handler for %s\n", name);
-#endif
     return(handler);
 }
 
@@ -1679,10 +1661,6 @@
 	    break;
     }
 
-#ifdef DEBUG_ENCODING
-    xmlGenericError(xmlGenericErrorContext,
-	    "No handler found for encoding %d\n", enc);
-#endif
     return(NULL);
 }
 
@@ -1739,10 +1717,6 @@
     if (handlers != NULL) {
         for (i = 0;i < nbCharEncodingHandler; i++) {
             if (!strcmp(upper, handlers[i]->name)) {
-#ifdef DEBUG_ENCODING
-                xmlGenericError(xmlGenericErrorContext,
-                        "Found registered handler for encoding %s\n", name);
-#endif
                 return(handlers[i]);
             }
         }
@@ -1778,10 +1752,6 @@
 	    enc->output = NULL;
 	    enc->iconv_in = icv_in;
 	    enc->iconv_out = icv_out;
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-		    "Found iconv handler for encoding %s\n", name);
-#endif
 	    return enc;
     } else if ((icv_in != (iconv_t) -1) || icv_out != (iconv_t) -1) {
 	    if (icv_in != (iconv_t) -1)
@@ -1814,10 +1784,6 @@
 	    encu->output = NULL;
 	    encu->uconv_in = ucv_in;
 	    encu->uconv_out = ucv_out;
-#ifdef DEBUG_ENCODING
-            xmlGenericError(xmlGenericErrorContext,
-		    "Found ICU converter handler for encoding %s\n", name);
-#endif
 	    return encu;
     } else if (ucv_in != NULL || ucv_out != NULL) {
             closeIcuConverter(ucv_in);
@@ -1825,11 +1791,6 @@
     }
 #endif /* LIBXML_ICU_ENABLED */
 
-#ifdef DEBUG_ENCODING
-    xmlGenericError(xmlGenericErrorContext,
-	    "No handler found for encoding %s\n", name);
-#endif
-
     /*
      * Fallback using the canonical names
      */
@@ -1915,7 +1876,6 @@
  * @outlen:  the length of @out
  * @in:  a pointer to an array of input bytes
  * @inlen:  the length of @in
- * @flush: if true, indicates end of input
  *
  * Returns an XML_ENC_ERR code.
  *
@@ -1925,7 +1885,7 @@
  */
 static int
 xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
-                const unsigned char *in, int *inlen, int flush) {
+                const unsigned char *in, int *inlen) {
     const char *ucv_in = (const char *) in;
     char *ucv_out = (char *) out;
     UErrorCode err = U_ZERO_ERROR;
@@ -1935,25 +1895,36 @@
         return(XML_ENC_ERR_INTERNAL);
     }
 
+    /*
+     * Note that the ICU API is stateful. It can always consume a certain
+     * amount of input even if the output buffer would overflow. The
+     * remaining input must be processed by calling ucnv_convertEx with a
+     * possibly empty input buffer.
+     *
+     * ucnv_convertEx is always called with reset and flush set to 0,
+     * so we don't mess up the state. This should never generate
+     * U_TRUNCATED_CHAR_FOUND errors.
+     *
+     * This also means that ICU xmlCharEncodingHandlers should never be
+     * reused. It would be a lot nicer if there was a way to emulate the
+     * stateless iconv API.
+     */
     if (toUnicode) {
         /* encoding => UTF-16 => UTF-8 */
         ucnv_convertEx(cd->utf8, cd->uconv, &ucv_out, ucv_out + *outlen,
                        &ucv_in, ucv_in + *inlen, cd->pivot_buf,
                        &cd->pivot_source, &cd->pivot_target,
-                       cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, flush, &err);
+                       cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, 0, &err);
     } else {
         /* UTF-8 => UTF-16 => encoding */
         ucnv_convertEx(cd->uconv, cd->utf8, &ucv_out, ucv_out + *outlen,
                        &ucv_in, ucv_in + *inlen, cd->pivot_buf,
                        &cd->pivot_source, &cd->pivot_target,
-                       cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, flush, &err);
+                       cd->pivot_buf + ICU_PIVOT_BUF_SIZE, 0, 0, &err);
     }
     *inlen = ucv_in - (const char*) in;
     *outlen = ucv_out - (char *) out;
     if (U_SUCCESS(err)) {
-        /* reset pivot buf if this is the last call for input (flush==TRUE) */
-        if (flush)
-            cd->pivot_source = cd->pivot_target = cd->pivot_buf;
         return(XML_ENC_ERR_SUCCESS);
     }
     if (err == U_BUFFER_OVERFLOW_ERROR)
@@ -2005,19 +1976,17 @@
  * @outlen:  the length of @out
  * @in:  a pointer to an array of input bytes
  * @inlen:  the length of @in
- * @flush:  flush (ICU-related)
- *
- * Returns an XML_ENC_ERR code.
  *
  * The value of @inlen after return is the number of octets consumed
  *     as the return value is 0, else unpredictable.
  * The value of @outlen after return is the number of octets produced.
+ *
+ * Returns an XML_ENC_ERR code.
  */
 int
 xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
-                 int *outlen, const unsigned char *in, int *inlen, int flush) {
+                 int *outlen, const unsigned char *in, int *inlen) {
     int ret;
-    (void)flush;
 
     if (handler->input != NULL) {
         ret = handler->input(out, outlen, in, inlen);
@@ -2031,8 +2000,7 @@
 #endif /* LIBXML_ICONV_ENABLED */
 #ifdef LIBXML_ICU_ENABLED
     else if (handler->uconv_in != NULL) {
-        ret = xmlUconvWrapper(handler->uconv_in, 1, out, outlen, in, inlen,
-                              flush);
+        ret = xmlUconvWrapper(handler->uconv_in, 1, out, outlen, in, inlen);
     }
 #endif /* LIBXML_ICU_ENABLED */
     else {
@@ -2041,8 +2009,8 @@
         ret = XML_ENC_ERR_INTERNAL;
     }
 
-    /* Ignore space and partial errors when reading. */
-    if ((ret == XML_ENC_ERR_SPACE) || (ret == XML_ENC_ERR_PARTIAL))
+    /* Ignore partial errors when reading. */
+    if (ret == XML_ENC_ERR_PARTIAL)
         ret = XML_ENC_ERR_SUCCESS;
 
     return(ret);
@@ -2079,8 +2047,7 @@
 #endif /* LIBXML_ICONV_ENABLED */
 #ifdef LIBXML_ICU_ENABLED
     else if (handler->uconv_out != NULL) {
-        ret = xmlUconvWrapper(handler->uconv_out, 0, out, outlen, in, inlen,
-                              1);
+        ret = xmlUconvWrapper(handler->uconv_out, 0, out, outlen, in, inlen);
     }
 #endif /* LIBXML_ICU_ENABLED */
     else {
@@ -2103,6 +2070,8 @@
  * @in:  an xmlBuffer for the input
  *
  * DEPERECATED: Don't use.
+ *
+ * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 int
 xmlCharEncFirstLine(xmlCharEncodingHandler *handler, xmlBufferPtr out,
@@ -2113,22 +2082,23 @@
 /**
  * xmlCharEncInput:
  * @input: a parser input buffer
- * @flush: try to flush all the raw buffer
  *
  * Generic front-end for the encoding handler on parser input
  *
  * Returns the number of bytes written or an XML_ENC_ERR code.
  */
 int
-xmlCharEncInput(xmlParserInputBufferPtr input, int flush)
+xmlCharEncInput(xmlParserInputBufferPtr input)
 {
     int ret;
-    size_t written;
+    size_t avail;
     size_t toconv;
     int c_in;
     int c_out;
     xmlBufPtr in;
     xmlBufPtr out;
+    const xmlChar *inData;
+    size_t inTotal = 0;
 
     if ((input == NULL) || (input->encoder == NULL) ||
         (input->buffer == NULL) || (input->raw == NULL))
@@ -2139,25 +2109,39 @@
     toconv = xmlBufUse(in);
     if (toconv == 0)
         return (0);
-    if ((toconv > 64 * 1024) && (flush == 0))
-        toconv = 64 * 1024;
-    written = xmlBufAvail(out);
-    if (toconv * 2 >= written) {
-        if (xmlBufGrow(out, toconv * 2) < 0) {
-            input->error = XML_ERR_NO_MEMORY;
-            return(XML_ENC_ERR_MEMORY);
-        }
-        written = xmlBufAvail(out);
-    }
-    if ((written > 128 * 1024) && (flush == 0))
-        written = 128 * 1024;
+    inData = xmlBufContent(in);
+    inTotal = 0;
 
-    c_in = toconv;
-    c_out = written;
-    ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out,
-                           xmlBufContent(in), &c_in, flush);
-    xmlBufShrink(in, c_in);
-    xmlBufAddLen(out, c_out);
+    do {
+        c_in = toconv > INT_MAX / 2 ? INT_MAX / 2 : toconv;
+
+        avail = xmlBufAvail(out);
+        if (avail > INT_MAX)
+            avail = INT_MAX;
+        if (avail < toconv * 2) {
+            if (xmlBufGrow(out, toconv * 2) < 0) {
+                input->error = XML_ERR_NO_MEMORY;
+                return(XML_ENC_ERR_MEMORY);
+            }
+            avail = xmlBufAvail(out);
+        }
+
+        c_in = toconv;
+        c_out = avail;
+        ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out,
+                               inData, &c_in);
+        inTotal += c_in;
+        inData += c_in;
+        toconv -= c_in;
+        xmlBufAddLen(out, c_out);
+    } while (ret == XML_ENC_ERR_SPACE);
+
+    xmlBufShrink(in, inTotal);
+
+    if (input->rawconsumed > ULONG_MAX - (unsigned long)c_in)
+        input->rawconsumed = ULONG_MAX;
+    else
+        input->rawconsumed += c_in;
 
     if ((c_out == 0) && (ret != 0)) {
         if (input->error == 0)
@@ -2202,7 +2186,7 @@
         written = out->size - out->use - 1;
     }
     ret = xmlEncInputChunk(handler, &out->content[out->use], &written,
-                           in->content, &toconv, 1);
+                           in->content, &toconv);
     xmlBufferShrink(in, toconv);
     out->use += written;
     out->content[out->use] = 0;
@@ -2257,10 +2241,6 @@
         xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
                           NULL, &c_in);
         xmlBufAddLen(out, c_out);
-#ifdef DEBUG_ENCODING
-	xmlGenericError(xmlGenericErrorContext,
-		"initialized encoder\n");
-#endif
         return(c_out);
     }
 
@@ -2268,8 +2248,6 @@
      * Conversion itself.
      */
     toconv = xmlBufUse(in);
-    if (toconv == 0)
-        return (writtentot);
     if (toconv > 64 * 1024)
         toconv = 64 * 1024;
     if (toconv * 4 >= written) {
@@ -2303,14 +2281,6 @@
         if (cur <= 0)
             goto error;
 
-#ifdef DEBUG_ENCODING
-        xmlGenericError(xmlGenericErrorContext,
-                "handling output conversion error\n");
-        xmlGenericError(xmlGenericErrorContext,
-                "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-                content[0], content[1],
-                content[2], content[3]);
-#endif
         /*
          * Removes the UTF8 sequence, and replace it by a charref
          * and continue the transcoding phase, hoping the error
@@ -2388,10 +2358,6 @@
                           NULL, &toconv);
         out->use += written;
         out->content[out->use] = 0;
-#ifdef DEBUG_ENCODING
-	xmlGenericError(xmlGenericErrorContext,
-		"initialized encoder\n");
-#endif
         return(0);
     }
 
@@ -2399,8 +2365,6 @@
      * Conversion itself.
      */
     toconv = in->use;
-    if (toconv == 0)
-	return(0);
     if (toconv * 4 >= written) {
         xmlBufferGrow(out, toconv * 4);
 	written = out->size - out->use - 1;
@@ -2428,14 +2392,6 @@
         if (cur <= 0)
             return(ret);
 
-#ifdef DEBUG_ENCODING
-        xmlGenericError(xmlGenericErrorContext,
-                "handling output conversion error\n");
-        xmlGenericError(xmlGenericErrorContext,
-                "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
-                in->content[0], in->content[1],
-                in->content[2], in->content[3]);
-#endif
         /*
          * Removes the UTF8 sequence, and replace it by a charref
          * and continue the transcoding phase, hoping the error
@@ -2526,14 +2482,6 @@
         handler->name = NULL;
         xmlFree(handler);
     }
-#ifdef DEBUG_ENCODING
-    if (ret)
-        xmlGenericError(xmlGenericErrorContext,
-		"failed to close the encoding handler\n");
-    else
-        xmlGenericError(xmlGenericErrorContext,
-		"closed the encoding handler\n");
-#endif
 
     return(ret);
 }
diff --git a/third_party/libxml/src/entities.c b/third_party/libxml/src/entities.c
index 52eb9d5..09d47d7 100644
--- a/third_party/libxml/src/entities.c
+++ b/third_party/libxml/src/entities.c
@@ -23,7 +23,6 @@
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/xmlerror.h>
-#include <libxml/globals.h>
 #include <libxml/dict.h>
 
 #include "private/entities.h"
@@ -718,8 +717,6 @@
 		    (((cur[0] & 0xF8) == 0xF8))) {
 		    xmlEntitiesErr(XML_CHECK_NOT_UTF8,
 			    "xmlEncodeEntities: input not UTF-8");
-		    if (doc != NULL)
-			doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
 		    snprintf(buf, sizeof(buf), "&#%d;", *cur);
 		    buf[sizeof(buf) - 1] = 0;
 		    ptr = buf;
@@ -751,8 +748,6 @@
 		if ((l == 1) || (!IS_CHAR(val))) {
 		    xmlEntitiesErr(XML_ERR_INVALID_CHAR,
 			"xmlEncodeEntities: char out of range\n");
-		    if (doc != NULL)
-			doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
 		    snprintf(buf, sizeof(buf), "&#%d;", *cur);
 		    buf[sizeof(buf) - 1] = 0;
 		    ptr = buf;
diff --git a/third_party/libxml/src/error.c b/third_party/libxml/src/error.c
index 4de1418..d9a0f4c 100644
--- a/third_party/libxml/src/error.c
+++ b/third_party/libxml/src/error.c
@@ -14,7 +14,6 @@
 #include <libxml/parser.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xmlmemory.h>
-#include <libxml/globals.h>
 
 #include "private/error.h"
 
diff --git a/third_party/libxml/src/globals.c b/third_party/libxml/src/globals.c
index c3e10a7..0fb1c51c 100644
--- a/third_party/libxml/src/globals.c
+++ b/third_party/libxml/src/globals.c
@@ -2,9 +2,6 @@
  * globals.c: definition and handling of the set of global variables
  *            of the library
  *
- * The bottom of this file is automatically generated by build_glob.py
- * based on the description file global.data
- *
  * See Copyright for the status of this software.
  *
  * Gary Pennington <Gary.Pennington@uk.sun.com>
@@ -14,51 +11,131 @@
 #define IN_LIBXML
 #include "libxml.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#define XML_GLOBALS_NO_REDEFINITION
 #include <libxml/globals.h>
+#include <libxml/xmlerror.h>
 #include <libxml/xmlmemory.h>
+#include <libxml/xmlIO.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/parser.h>
 #include <libxml/threads.h>
+#include <libxml/tree.h>
+#include <libxml/SAX.h>
+#include <libxml/SAX2.h>
 
 #include "private/error.h"
 #include "private/globals.h"
 #include "private/threads.h"
 #include "private/tree.h"
 
-/* #define DEBUG_GLOBALS */
+/*
+ * Thread-local storage emulation.
+ *
+ * This works by replacing a global variable
+ *
+ *     extern xmlError xmlLastError;
+ *
+ * with a macro that calls a function returning a pointer to the global in
+ * thread-local storage:
+ *
+ *     xmlError *__xmlLastError(void);
+ *     #define xmlError (*__xmlLastError());
+ *
+ * The code can operate in a multitude of ways depending on the environment.
+ * First we support POSIX and Windows threads. Then we support both thread-local
+ * storage provided by the compiler and older methods like thread-specific data
+ * (pthreads) or TlsAlloc (Windows).
+ *
+ * To clean up thread-local storage, we use thread-specific data on POSIX.
+ * On Windows, we either use DllMain when compiling a DLL or a registered wait
+ * function for static builds.
+ */
 
 /*
  * Helpful Macro
  */
 #ifdef LIBXML_THREAD_ENABLED
-#define IS_MAIN_THREAD (xmlIsMainThread())
+#define IS_MAIN_THREAD (xmlIsMainThreadInternal())
 #else
 #define IS_MAIN_THREAD 1
 #endif
 
+static int parserInitialized;
+
 /*
  * Mutex to protect "ForNewThreads" variables
  */
 static xmlMutex xmlThrDefMutex;
 
-/**
- * xmlInitGlobals:
- *
- * DEPRECATED: Alias for xmlInitParser.
- */
-void xmlInitGlobals(void) {
-    xmlInitParser();
-}
+#define XML_DECLARE_MEMBER(name, type, attrs) \
+  type gs_##name;
 
-/**
- * xmlInitGlobalsInternal:
- *
- * Additional initialisation for multi-threading
+struct _xmlGlobalState {
+    int initialized;
+
+#if defined(HAVE_WIN32_THREADS) && \
+    defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
+    void *threadHandle;
+    void *waitHandle;
+#endif
+
+#define XML_OP XML_DECLARE_MEMBER
+XML_GLOBALS_ALLOC
+XML_GLOBALS_ERROR
+XML_GLOBALS_HTML
+XML_GLOBALS_IO
+XML_GLOBALS_PARSER
+XML_GLOBALS_SAVE
+XML_GLOBALS_TREE
+#undef XML_OP
+};
+
+#ifdef LIBXML_THREAD_ENABLED
+
+#ifdef XML_THREAD_LOCAL
+static XML_THREAD_LOCAL xmlGlobalState globalState;
+#endif
+
+#ifdef HAVE_POSIX_THREADS
+
+/*
+ * Weak symbol hack, see threads.c
  */
-void xmlInitGlobalsInternal(void) {
-    xmlInitMutex(&xmlThrDefMutex);
-}
+#if defined(__GNUC__) && \
+    defined(__GLIBC__) && \
+    __GLIBC__ * 100 + __GLIBC_MINOR__ < 234
+
+#define XML_PTHREAD_WEAK
+
+static int libxml_is_threaded = -1;
+
+#endif
+
+/*
+ * On POSIX, we need thread-specific data even with thread-local storage
+ * to destroy indirect references from global state (xmlLastError) at
+ * thread exit.
+ */
+static pthread_key_t globalkey;
+static pthread_t mainthread;
+
+#elif defined HAVE_WIN32_THREADS
+
+#ifndef XML_THREAD_LOCAL
+static DWORD globalkey = TLS_OUT_OF_INDEXES;
+#endif
+static DWORD mainthread;
+
+#endif /* HAVE_WIN32_THREADS */
+
+static void
+xmlFreeGlobalState(void *state);
+
+#endif /* LIBXML_THREAD_ENABLED */
 
 /************************************************************************
  *									*
@@ -69,13 +146,8 @@
 /*
  * Memory allocation routines
  */
-#undef	xmlFree
-#undef	xmlMalloc
-#undef	xmlMallocAtomic
-#undef	xmlMemStrdup
-#undef	xmlRealloc
 
-#if defined(DEBUG_MEMORY_LOCATION) || defined(DEBUG_MEMORY)
+#if defined(DEBUG_MEMORY_LOCATION)
 xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
 xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
 xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
@@ -140,46 +212,7 @@
  * Returns the copy of the string or NULL in case of error
  */
 xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup;
-#endif /* DEBUG_MEMORY_LOCATION || DEBUG_MEMORY */
-
-#include <libxml/threads.h>
-#include <libxml/globals.h>
-#include <libxml/SAX.h>
-
-#undef	htmlDefaultSAXHandler
-#undef	oldXMLWDcompatibility
-#undef	xmlBufferAllocScheme
-#undef	xmlDefaultBufferSize
-#undef	xmlDefaultSAXHandler
-#undef	xmlDefaultSAXLocator
-#undef	xmlDoValidityCheckingDefaultValue
-#undef	xmlGenericError
-#undef	xmlStructuredError
-#undef	xmlGenericErrorContext
-#undef	xmlStructuredErrorContext
-#undef	xmlGetWarningsDefaultValue
-#undef	xmlIndentTreeOutput
-#undef  xmlTreeIndentString
-#undef	xmlKeepBlanksDefaultValue
-#undef	xmlLineNumbersDefaultValue
-#undef	xmlLoadExtDtdDefaultValue
-#undef	xmlParserDebugEntities
-#undef	xmlParserVersion
-#undef	xmlPedanticParserDefaultValue
-#undef	xmlSaveNoEmptyTags
-#undef	xmlSubstituteEntitiesDefaultValue
-#undef	xmlRegisterNodeDefaultValue
-#undef	xmlDeregisterNodeDefaultValue
-#undef	xmlLastError
-
-#undef  xmlParserInputBufferCreateFilenameValue
-#undef  xmlOutputBufferCreateFilenameValue
-/**
- * xmlParserVersion:
- *
- * Constant string describing the internal version of the library
- */
-const char *xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA;
+#endif /* DEBUG_MEMORY_LOCATION */
 
 /**
  * xmlBufferAllocScheme:
@@ -364,6 +397,7 @@
 static void *xmlStructuredErrorContextThrDef = NULL;
 xmlError xmlLastError;
 
+#ifdef LIBXML_OUTPUT_ENABLED
 /*
  * output defaults
  */
@@ -394,6 +428,7 @@
  */
 int xmlSaveNoEmptyTags = 0;
 static int xmlSaveNoEmptyTagsThrDef = 0;
+#endif /* LIBXML_OUTPUT_ENABLED */
 
 #ifdef LIBXML_SAX1_ENABLED
 /**
@@ -492,77 +527,48 @@
 };
 #endif /* LIBXML_HTML_ENABLED */
 
+/************************************************************************
+ *									*
+ *			Per thread global state handling		*
+ *									*
+ ************************************************************************/
+
 /**
- * xmlInitializeGlobalState:
- * @gs: a pointer to a newly allocated global state
+ * xmlInitGlobals:
  *
- * xmlInitializeGlobalState() initialize a global state with all the
- * default values of the library.
+ * DEPRECATED: Alias for xmlInitParser.
  */
-void
-xmlInitializeGlobalState(xmlGlobalStatePtr gs)
-{
-#ifdef DEBUG_GLOBALS
-    fprintf(stderr, "Initializing globals at %p for thread %d\n",
-	    (void *) gs, xmlGetThreadId());
+void xmlInitGlobals(void) {
+    xmlInitParser();
+}
+
+/**
+ * xmlInitGlobalsInternal:
+ *
+ * Additional initialisation for multi-threading
+ */
+void xmlInitGlobalsInternal(void) {
+    xmlInitMutex(&xmlThrDefMutex);
+
+#ifdef HAVE_POSIX_THREADS
+#ifdef XML_PTHREAD_WEAK
+    if (libxml_is_threaded == -1)
+        libxml_is_threaded =
+            (pthread_getspecific != NULL) &&
+            (pthread_setspecific != NULL) &&
+            (pthread_key_create != NULL) &&
+            (pthread_key_delete != NULL);
+    if (libxml_is_threaded == 0)
+        return;
+#endif /* XML_PTHREAD_WEAK */
+    pthread_key_create(&globalkey, xmlFreeGlobalState);
+    mainthread = pthread_self();
+#elif defined(HAVE_WIN32_THREADS)
+#ifndef XML_THREAD_LOCAL
+    globalkey = TlsAlloc();
 #endif
-
-    xmlMutexLock(&xmlThrDefMutex);
-
-#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED)
-    inithtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler);
+    mainthread = GetCurrentThreadId();
 #endif
-
-    gs->oldXMLWDcompatibility = 0;
-    gs->xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
-    gs->xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
-#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED)
-    initxmlDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1);
-#endif /* LIBXML_SAX1_ENABLED */
-    gs->xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId;
-    gs->xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId;
-    gs->xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber;
-    gs->xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber;
-    gs->xmlDoValidityCheckingDefaultValue =
-         xmlDoValidityCheckingDefaultValueThrDef;
-#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
-    gs->xmlFree = (xmlFreeFunc) xmlMemFree;
-    gs->xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
-    gs->xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
-    gs->xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
-    gs->xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
-#else
-    gs->xmlFree = (xmlFreeFunc) free;
-    gs->xmlMalloc = (xmlMallocFunc) malloc;
-    gs->xmlMallocAtomic = (xmlMallocFunc) malloc;
-    gs->xmlRealloc = (xmlReallocFunc) realloc;
-    gs->xmlMemStrdup = (xmlStrdupFunc) xmlStrdup;
-#endif
-    gs->xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
-    gs->xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
-    gs->xmlTreeIndentString = xmlTreeIndentStringThrDef;
-    gs->xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
-    gs->xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
-    gs->xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
-    gs->xmlParserDebugEntities = xmlParserDebugEntitiesThrDef;
-    gs->xmlParserVersion = LIBXML_VERSION_STRING;
-    gs->xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
-    gs->xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
-    gs->xmlSubstituteEntitiesDefaultValue =
-        xmlSubstituteEntitiesDefaultValueThrDef;
-
-    gs->xmlGenericError = xmlGenericErrorThrDef;
-    gs->xmlStructuredError = xmlStructuredErrorThrDef;
-    gs->xmlGenericErrorContext = xmlGenericErrorContextThrDef;
-    gs->xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
-    gs->xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
-    gs->xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
-
-	gs->xmlParserInputBufferCreateFilenameValue = xmlParserInputBufferCreateFilenameValueThrDef;
-	gs->xmlOutputBufferCreateFilenameValue = xmlOutputBufferCreateFilenameValueThrDef;
-    memset(&gs->xmlLastError, 0, sizeof(xmlError));
-
-    xmlMutexUnlock(&xmlThrDefMutex);
 }
 
 /**
@@ -585,9 +591,383 @@
     xmlResetError(&xmlLastError);
 
     xmlCleanupMutex(&xmlThrDefMutex);
-    __xmlGlobalInitMutexDestroy();
+
+#ifdef HAVE_POSIX_THREADS
+#ifdef XML_PTHREAD_WEAK
+    if (libxml_is_threaded == 0)
+        return;
+#endif /* XML_PTHREAD_WEAK */
+    pthread_key_delete(globalkey);
+#elif defined(HAVE_WIN32_THREADS)
+#ifndef XML_THREAD_LOCAL
+    if (globalkey != TLS_OUT_OF_INDEXES) {
+        TlsFree(globalkey);
+        globalkey = TLS_OUT_OF_INDEXES;
+    }
+#endif
+#endif
 }
 
+/**
+ * xmlInitializeGlobalState:
+ * @gs: a pointer to a newly allocated global state
+ *
+ * DEPRECATED: No-op.
+ */
+void
+xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED)
+{
+}
+
+/**
+ * xmlGetGlobalState:
+ *
+ * DEPRECATED
+ *
+ * Returns NULL.
+ */
+xmlGlobalStatePtr
+xmlGetGlobalState(void)
+{
+    return(NULL);
+}
+
+static int
+xmlIsMainThreadInternal(void) {
+    if (parserInitialized == 0) {
+        xmlInitParser();
+        parserInitialized = 1;
+    }
+
+#ifdef HAVE_POSIX_THREADS
+#ifdef XML_PTHREAD_WEAK
+    if (libxml_is_threaded == 0)
+        return (1);
+#endif
+    return (pthread_equal(mainthread, pthread_self()));
+#elif defined HAVE_WIN32_THREADS
+    return (mainthread == GetCurrentThreadId());
+#else
+    return (1);
+#endif
+}
+
+/**
+ * xmlIsMainThread:
+ *
+ * DEPRECATED: Internal function, do not use.
+ *
+ * Check whether the current thread is the main thread.
+ *
+ * Returns 1 if the current thread is the main thread, 0 otherwise
+ */
+int
+xmlIsMainThread(void) {
+    return(xmlIsMainThreadInternal());
+}
+
+#ifdef LIBXML_THREAD_ENABLED
+
+static void
+xmlFreeGlobalState(void *state)
+{
+    xmlGlobalState *gs = (xmlGlobalState *) state;
+
+    /*
+     * Free any memory allocated in the thread's xmlLastError. If it
+     * weren't for this indirect allocation, we wouldn't need
+     * a destructor with thread-local storage at all!
+     *
+     * It would be nice if we could make xmlLastError a special error
+     * type which uses statically allocated, fixed-size buffers.
+     * But the xmlError struct is fully public and widely used,
+     * so changes are dangerous.
+     */
+    xmlResetError(&(gs->gs_xmlLastError));
+#ifndef XML_THREAD_LOCAL
+    free(state);
+#endif
+}
+
+#if defined(HAVE_WIN32_THREADS) && \
+    defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
+static void WINAPI
+xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) {
+    xmlGlobalStatePtr gs = ctxt;
+
+    UnregisterWait(gs->waitHandle);
+    CloseHandle(gs->threadHandle);
+    xmlFreeGlobalState(gs);
+}
+
+static int
+xmlRegisterGlobalStateDtor(xmlGlobalState *gs) {
+    void *processHandle = GetCurrentProcess();
+    void *threadHandle;
+    void *waitHandle;
+
+    if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle,
+                &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
+        return(-1);
+    }
+
+    if (RegisterWaitForSingleObject(&waitHandle, threadHandle,
+                xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) {
+        CloseHandle(threadHandle);
+        return(-1);
+    }
+
+    gs->threadHandle = threadHandle;
+    gs->waitHandle = waitHandle;
+    return(0);
+}
+#endif /* LIBXML_STATIC */
+
+static void
+xmlInitGlobalState(xmlGlobalStatePtr gs) {
+    xmlMutexLock(&xmlThrDefMutex);
+
+#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED)
+    inithtmlDefaultSAXHandler(&gs->gs_htmlDefaultSAXHandler);
+#endif
+
+    gs->gs_oldXMLWDcompatibility = 0;
+    gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
+    gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
+#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED)
+    initxmlDefaultSAXHandler(&gs->gs_xmlDefaultSAXHandler, 1);
+#endif /* LIBXML_SAX1_ENABLED */
+    gs->gs_xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId;
+    gs->gs_xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId;
+    gs->gs_xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber;
+    gs->gs_xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber;
+    gs->gs_xmlDoValidityCheckingDefaultValue =
+         xmlDoValidityCheckingDefaultValueThrDef;
+#if defined(DEBUG_MEMORY_LOCATION)
+    gs->gs_xmlFree = (xmlFreeFunc) xmlMemFree;
+    gs->gs_xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
+    gs->gs_xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
+    gs->gs_xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
+    gs->gs_xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
+#endif
+    gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
+#ifdef LIBXML_OUTPUT_ENABLED
+    gs->gs_xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
+    gs->gs_xmlTreeIndentString = xmlTreeIndentStringThrDef;
+    gs->gs_xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
+#endif
+    gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
+    gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
+    gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
+    gs->gs_xmlParserDebugEntities = xmlParserDebugEntitiesThrDef;
+    gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
+    gs->gs_xmlSubstituteEntitiesDefaultValue =
+        xmlSubstituteEntitiesDefaultValueThrDef;
+
+    gs->gs_xmlGenericError = xmlGenericErrorThrDef;
+    gs->gs_xmlStructuredError = xmlStructuredErrorThrDef;
+    gs->gs_xmlGenericErrorContext = xmlGenericErrorContextThrDef;
+    gs->gs_xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
+    gs->gs_xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
+    gs->gs_xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
+
+    gs->gs_xmlParserInputBufferCreateFilenameValue =
+        xmlParserInputBufferCreateFilenameValueThrDef;
+    gs->gs_xmlOutputBufferCreateFilenameValue =
+        xmlOutputBufferCreateFilenameValueThrDef;
+    memset(&gs->gs_xmlLastError, 0, sizeof(xmlError));
+
+    xmlMutexUnlock(&xmlThrDefMutex);
+
+#ifdef HAVE_POSIX_THREADS
+    pthread_setspecific(globalkey, gs);
+#elif defined HAVE_WIN32_THREADS
+#ifndef XML_THREAD_LOCAL
+    TlsSetValue(globalkey, gs);
+#endif
+#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
+    xmlRegisterGlobalStateDtor(gs);
+#endif
+#endif
+
+    gs->initialized = 1;
+}
+
+#ifndef XML_THREAD_LOCAL
+/**
+ * xmlNewGlobalState:
+ *
+ * xmlNewGlobalState() allocates a global state. This structure is used to
+ * hold all data for use by a thread when supporting backwards compatibility
+ * of libxml2 to pre-thread-safe behaviour.
+ *
+ * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
+ */
+static xmlGlobalStatePtr
+xmlNewGlobalState(int allowFailure)
+{
+    xmlGlobalState *gs;
+
+    gs = malloc(sizeof(xmlGlobalState));
+    if (gs == NULL) {
+        if (allowFailure)
+            return(NULL);
+
+        /*
+         * If an application didn't call xmlCheckThreadLocalStorage to make
+         * sure that global state could be allocated, it's too late to
+         * handle the error.
+         */
+        fprintf(stderr, "libxml2: Failed to allocate globals for thread\n"
+                        "libxml2: See xmlCheckThreadLocalStorage\n");
+        abort();
+    }
+
+    memset(gs, 0, sizeof(xmlGlobalState));
+    xmlInitGlobalState(gs);
+    return (gs);
+}
+#endif
+
+static xmlGlobalStatePtr
+xmlGetThreadLocalStorage(int allowFailure) {
+    xmlGlobalState *gs;
+
+    (void) allowFailure;
+
+#ifdef XML_THREAD_LOCAL
+    gs = &globalState;
+    if (gs->initialized == 0)
+        xmlInitGlobalState(gs);
+#elif defined(HAVE_POSIX_THREADS)
+    gs = (xmlGlobalState *) pthread_getspecific(globalkey);
+    if (gs == NULL)
+        gs = xmlNewGlobalState(allowFailure);
+#elif defined(HAVE_WIN32_THREADS)
+    gs = (xmlGlobalState *) TlsGetValue(globalkey);
+    if (gs == NULL)
+        gs = xmlNewGlobalState(allowFailure);
+#else
+    gs = NULL;
+#endif
+
+    return(gs);
+}
+
+/* Define thread-local storage accessors with macro magic */
+
+#define XML_DEFINE_GLOBAL_WRAPPER(name, type, attrs) \
+    type *__##name(void) { \
+        if (IS_MAIN_THREAD) \
+            return (&name); \
+        else \
+            return (&xmlGetThreadLocalStorage(0)->gs_##name); \
+    }
+
+#define XML_OP XML_DEFINE_GLOBAL_WRAPPER
+XML_GLOBALS_ALLOC
+XML_GLOBALS_ERROR
+XML_GLOBALS_HTML
+XML_GLOBALS_IO
+XML_GLOBALS_PARSER
+XML_GLOBALS_SAVE
+XML_GLOBALS_TREE
+#undef XML_OP
+
+/* For backward compatibility */
+
+const char *const *
+__xmlParserVersion(void) {
+    return &xmlParserVersion;
+}
+
+#endif /* LIBXML_THREAD_ENABLED */
+
+/**
+ * xmlCheckThreadLocalStorage:
+ *
+ * Check whether thread-local storage could be allocated.
+ *
+ * In cross-platform code running in multithreaded environments, this
+ * function should be called once in each thread before calling other
+ * library functions to make sure that thread-local storage was
+ * allocated properly.
+ *
+ * Returns 0 on success or -1 if a memory allocation failed. A failed
+ * allocation signals a typically fatal and irrecoverable out-of-memory
+ * situation. Don't call any library functions in this case.
+ *
+ * This function never fails if the library is compiled with support
+ * for thread-local storage.
+ *
+ * This function never fails for the "main" thread which is the first
+ * thread calling xmlInitParser.
+ *
+ * Available since v2.12.0.
+ */
+int
+xmlCheckThreadLocalStorage(void) {
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_THREAD_LOCAL)
+    if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL))
+        return(-1);
+#endif
+    return(0);
+}
+
+/**
+ * DllMain:
+ * @hinstDLL: handle to DLL instance
+ * @fdwReason: Reason code for entry
+ * @lpvReserved: generic pointer (depends upon reason code)
+ *
+ * Entry point for Windows library. It is being used to free thread-specific
+ * storage.
+ *
+ * Returns TRUE always
+ */
+#if defined(HAVE_WIN32_THREADS) && \
+    (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+#if defined(LIBXML_STATIC_FOR_DLL)
+int
+xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
+           ATTRIBUTE_UNUSED void *lpvReserved)
+#else
+/* declare to avoid "no previous prototype for 'DllMain'" warning */
+/* Note that we do NOT want to include this function declaration in
+   a public header because it's meant to be called by Windows itself,
+   not a program that uses this library.  This also has to be exported. */
+
+XMLPUBFUN BOOL WINAPI
+DllMain (HINSTANCE hinstDLL,
+         DWORD     fdwReason,
+         LPVOID    lpvReserved);
+
+BOOL WINAPI
+DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
+        ATTRIBUTE_UNUSED LPVOID lpvReserved)
+#endif
+{
+    switch (fdwReason) {
+        case DLL_THREAD_DETACH:
+#ifdef XML_THREAD_LOCAL
+            xmlFreeGlobalState(&globalState);
+#else
+            if (globalkey != TLS_OUT_OF_INDEXES) {
+                xmlGlobalState *globalval;
+
+                globalval = (xmlGlobalState *) TlsGetValue(globalkey);
+                if (globalval) {
+                    xmlFreeGlobalState(globalval);
+                    TlsSetValue(globalkey, NULL);
+                }
+            }
+#endif
+            break;
+    }
+    return TRUE;
+}
+#endif
+
 void
 xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
     xmlMutexLock(&xmlThrDefMutex);
@@ -607,22 +987,123 @@
     xmlMutexUnlock(&xmlThrDefMutex);
 }
 
-/**
- * xmlRegisterNodeDefault:
- * @func: function pointer to the new RegisterNodeFunc
- *
- * Registers a callback for node creation
- *
- * Returns the old value of the registration function
- */
-xmlRegisterNodeFunc
-xmlRegisterNodeDefault(xmlRegisterNodeFunc func)
-{
-    xmlRegisterNodeFunc old = xmlRegisterNodeDefaultValue;
+xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
+    xmlBufferAllocationScheme ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlBufferAllocSchemeThrDef;
+    xmlBufferAllocSchemeThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
 
-    __xmlRegisterCallbacks = 1;
-    xmlRegisterNodeDefaultValue = func;
-    return(old);
+int xmlThrDefDefaultBufferSize(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlDefaultBufferSizeThrDef;
+    xmlDefaultBufferSizeThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+int xmlThrDefDoValidityCheckingDefaultValue(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlDoValidityCheckingDefaultValueThrDef;
+    xmlDoValidityCheckingDefaultValueThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+int xmlThrDefGetWarningsDefaultValue(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlGetWarningsDefaultValueThrDef;
+    xmlGetWarningsDefaultValueThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+int xmlThrDefIndentTreeOutput(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlIndentTreeOutputThrDef;
+    xmlIndentTreeOutputThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+const char * xmlThrDefTreeIndentString(const char * v) {
+    const char * ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlTreeIndentStringThrDef;
+    xmlTreeIndentStringThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+int xmlThrDefSaveNoEmptyTags(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlSaveNoEmptyTagsThrDef;
+    xmlSaveNoEmptyTagsThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+#endif
+
+int xmlThrDefKeepBlanksDefaultValue(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlKeepBlanksDefaultValueThrDef;
+    xmlKeepBlanksDefaultValueThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+int xmlThrDefLineNumbersDefaultValue(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlLineNumbersDefaultValueThrDef;
+    xmlLineNumbersDefaultValueThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+int xmlThrDefLoadExtDtdDefaultValue(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlLoadExtDtdDefaultValueThrDef;
+    xmlLoadExtDtdDefaultValueThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+int xmlThrDefParserDebugEntities(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlParserDebugEntitiesThrDef;
+    xmlParserDebugEntitiesThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+int xmlThrDefPedanticParserDefaultValue(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlPedanticParserDefaultValueThrDef;
+    xmlPedanticParserDefaultValueThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
+}
+
+int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
+    int ret;
+    xmlMutexLock(&xmlThrDefMutex);
+    ret = xmlSubstituteEntitiesDefaultValueThrDef;
+    xmlSubstituteEntitiesDefaultValueThrDef = v;
+    xmlMutexUnlock(&xmlThrDefMutex);
+    return ret;
 }
 
 xmlRegisterNodeFunc
@@ -640,24 +1121,6 @@
     return(old);
 }
 
-/**
- * xmlDeregisterNodeDefault:
- * @func: function pointer to the new DeregisterNodeFunc
- *
- * Registers a callback for node destruction
- *
- * Returns the previous value of the deregistration function
- */
-xmlDeregisterNodeFunc
-xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func)
-{
-    xmlDeregisterNodeFunc old = xmlDeregisterNodeDefaultValue;
-
-    __xmlRegisterCallbacks = 1;
-    xmlDeregisterNodeDefaultValue = func;
-    return(old);
-}
-
 xmlDeregisterNodeFunc
 xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
 {
@@ -708,413 +1171,3 @@
     return(old);
 }
 
-#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_SAX1_ENABLED)
-#undef	htmlDefaultSAXHandler
-xmlSAXHandlerV1 *
-__htmlDefaultSAXHandler(void) {
-    if (IS_MAIN_THREAD)
-	return (&htmlDefaultSAXHandler);
-    else
-	return (&xmlGetGlobalState()->htmlDefaultSAXHandler);
-}
-#endif
-
-#undef xmlLastError
-xmlError *
-__xmlLastError(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlLastError);
-    else
-	return (&xmlGetGlobalState()->xmlLastError);
-}
-
-/*
- * The following memory routines were apparently lost at some point,
- * and were re-inserted at this point on June 10, 2004.  Hope it's
- * the right place for them :-)
- */
-#if defined(LIBXML_THREAD_ALLOC_ENABLED) && defined(LIBXML_THREAD_ENABLED)
-#undef xmlMalloc
-xmlMallocFunc *
-__xmlMalloc(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlMalloc);
-    else
-	return (&xmlGetGlobalState()->xmlMalloc);
-}
-
-#undef xmlMallocAtomic
-xmlMallocFunc *
-__xmlMallocAtomic(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlMallocAtomic);
-    else
-        return (&xmlGetGlobalState()->xmlMallocAtomic);
-}
-
-#undef xmlRealloc
-xmlReallocFunc *
-__xmlRealloc(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlRealloc);
-    else
-        return (&xmlGetGlobalState()->xmlRealloc);
-}
-
-#undef xmlFree
-xmlFreeFunc *
-__xmlFree(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlFree);
-    else
-        return (&xmlGetGlobalState()->xmlFree);
-}
-
-xmlStrdupFunc *
-__xmlMemStrdup(void){
-    if (IS_MAIN_THREAD)
-        return (&xmlMemStrdup);
-    else
-        return (&xmlGetGlobalState()->xmlMemStrdup);
-}
-
-#endif
-
-/*
- * Everything starting from the line below is
- * Automatically generated by build_glob.py.
- * Do not modify the previous line.
- */
-
-
-#undef	oldXMLWDcompatibility
-int *
-__oldXMLWDcompatibility(void) {
-    if (IS_MAIN_THREAD)
-	return (&oldXMLWDcompatibility);
-    else
-	return (&xmlGetGlobalState()->oldXMLWDcompatibility);
-}
-
-#undef	xmlBufferAllocScheme
-xmlBufferAllocationScheme *
-__xmlBufferAllocScheme(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlBufferAllocScheme);
-    else
-	return (&xmlGetGlobalState()->xmlBufferAllocScheme);
-}
-xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
-    xmlBufferAllocationScheme ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlBufferAllocSchemeThrDef;
-    xmlBufferAllocSchemeThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlDefaultBufferSize
-int *
-__xmlDefaultBufferSize(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDefaultBufferSize);
-    else
-	return (&xmlGetGlobalState()->xmlDefaultBufferSize);
-}
-int xmlThrDefDefaultBufferSize(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlDefaultBufferSizeThrDef;
-    xmlDefaultBufferSizeThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#ifdef LIBXML_SAX1_ENABLED
-#undef	xmlDefaultSAXHandler
-xmlSAXHandlerV1 *
-__xmlDefaultSAXHandler(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDefaultSAXHandler);
-    else
-	return (&xmlGetGlobalState()->xmlDefaultSAXHandler);
-}
-#endif /* LIBXML_SAX1_ENABLED */
-
-#undef	xmlDefaultSAXLocator
-xmlSAXLocator *
-__xmlDefaultSAXLocator(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDefaultSAXLocator);
-    else
-	return (&xmlGetGlobalState()->xmlDefaultSAXLocator);
-}
-
-#undef	xmlDoValidityCheckingDefaultValue
-int *
-__xmlDoValidityCheckingDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDoValidityCheckingDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlDoValidityCheckingDefaultValue);
-}
-int xmlThrDefDoValidityCheckingDefaultValue(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlDoValidityCheckingDefaultValueThrDef;
-    xmlDoValidityCheckingDefaultValueThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlGenericError
-xmlGenericErrorFunc *
-__xmlGenericError(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlGenericError);
-    else
-	return (&xmlGetGlobalState()->xmlGenericError);
-}
-
-#undef	xmlStructuredError
-xmlStructuredErrorFunc *
-__xmlStructuredError(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlStructuredError);
-    else
-	return (&xmlGetGlobalState()->xmlStructuredError);
-}
-
-#undef	xmlGenericErrorContext
-void * *
-__xmlGenericErrorContext(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlGenericErrorContext);
-    else
-	return (&xmlGetGlobalState()->xmlGenericErrorContext);
-}
-
-#undef	xmlStructuredErrorContext
-void * *
-__xmlStructuredErrorContext(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlStructuredErrorContext);
-    else
-	return (&xmlGetGlobalState()->xmlStructuredErrorContext);
-}
-
-#undef	xmlGetWarningsDefaultValue
-int *
-__xmlGetWarningsDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlGetWarningsDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlGetWarningsDefaultValue);
-}
-int xmlThrDefGetWarningsDefaultValue(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlGetWarningsDefaultValueThrDef;
-    xmlGetWarningsDefaultValueThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlIndentTreeOutput
-int *
-__xmlIndentTreeOutput(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlIndentTreeOutput);
-    else
-	return (&xmlGetGlobalState()->xmlIndentTreeOutput);
-}
-int xmlThrDefIndentTreeOutput(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlIndentTreeOutputThrDef;
-    xmlIndentTreeOutputThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlTreeIndentString
-const char * *
-__xmlTreeIndentString(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlTreeIndentString);
-    else
-	return (&xmlGetGlobalState()->xmlTreeIndentString);
-}
-const char * xmlThrDefTreeIndentString(const char * v) {
-    const char * ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlTreeIndentStringThrDef;
-    xmlTreeIndentStringThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlKeepBlanksDefaultValue
-int *
-__xmlKeepBlanksDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlKeepBlanksDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlKeepBlanksDefaultValue);
-}
-int xmlThrDefKeepBlanksDefaultValue(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlKeepBlanksDefaultValueThrDef;
-    xmlKeepBlanksDefaultValueThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlLineNumbersDefaultValue
-int *
-__xmlLineNumbersDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlLineNumbersDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlLineNumbersDefaultValue);
-}
-int xmlThrDefLineNumbersDefaultValue(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlLineNumbersDefaultValueThrDef;
-    xmlLineNumbersDefaultValueThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlLoadExtDtdDefaultValue
-int *
-__xmlLoadExtDtdDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlLoadExtDtdDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlLoadExtDtdDefaultValue);
-}
-int xmlThrDefLoadExtDtdDefaultValue(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlLoadExtDtdDefaultValueThrDef;
-    xmlLoadExtDtdDefaultValueThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlParserDebugEntities
-int *
-__xmlParserDebugEntities(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlParserDebugEntities);
-    else
-	return (&xmlGetGlobalState()->xmlParserDebugEntities);
-}
-int xmlThrDefParserDebugEntities(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlParserDebugEntitiesThrDef;
-    xmlParserDebugEntitiesThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlParserVersion
-const char * *
-__xmlParserVersion(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlParserVersion);
-    else
-	return (&xmlGetGlobalState()->xmlParserVersion);
-}
-
-#undef	xmlPedanticParserDefaultValue
-int *
-__xmlPedanticParserDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlPedanticParserDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlPedanticParserDefaultValue);
-}
-int xmlThrDefPedanticParserDefaultValue(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlPedanticParserDefaultValueThrDef;
-    xmlPedanticParserDefaultValueThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlSaveNoEmptyTags
-int *
-__xmlSaveNoEmptyTags(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlSaveNoEmptyTags);
-    else
-	return (&xmlGetGlobalState()->xmlSaveNoEmptyTags);
-}
-int xmlThrDefSaveNoEmptyTags(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlSaveNoEmptyTagsThrDef;
-    xmlSaveNoEmptyTagsThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlSubstituteEntitiesDefaultValue
-int *
-__xmlSubstituteEntitiesDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlSubstituteEntitiesDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlSubstituteEntitiesDefaultValue);
-}
-int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
-    int ret;
-    xmlMutexLock(&xmlThrDefMutex);
-    ret = xmlSubstituteEntitiesDefaultValueThrDef;
-    xmlSubstituteEntitiesDefaultValueThrDef = v;
-    xmlMutexUnlock(&xmlThrDefMutex);
-    return ret;
-}
-
-#undef	xmlRegisterNodeDefaultValue
-xmlRegisterNodeFunc *
-__xmlRegisterNodeDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlRegisterNodeDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlRegisterNodeDefaultValue);
-}
-
-#undef	xmlDeregisterNodeDefaultValue
-xmlDeregisterNodeFunc *
-__xmlDeregisterNodeDefaultValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlDeregisterNodeDefaultValue);
-    else
-	return (&xmlGetGlobalState()->xmlDeregisterNodeDefaultValue);
-}
-
-#undef	xmlParserInputBufferCreateFilenameValue
-xmlParserInputBufferCreateFilenameFunc *
-__xmlParserInputBufferCreateFilenameValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlParserInputBufferCreateFilenameValue);
-    else
-	return (&xmlGetGlobalState()->xmlParserInputBufferCreateFilenameValue);
-}
-
-#undef	xmlOutputBufferCreateFilenameValue
-xmlOutputBufferCreateFilenameFunc *
-__xmlOutputBufferCreateFilenameValue(void) {
-    if (IS_MAIN_THREAD)
-	return (&xmlOutputBufferCreateFilenameValue);
-    else
-	return (&xmlGetGlobalState()->xmlOutputBufferCreateFilenameValue);
-}
-
diff --git a/third_party/libxml/src/hash.c b/third_party/libxml/src/hash.c
index cbcc429..34825f3 100644
--- a/third_party/libxml/src/hash.c
+++ b/third_party/libxml/src/hash.c
@@ -37,11 +37,13 @@
 #include <libxml/hash.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/xmlerror.h>
-#include <libxml/globals.h>
 
 #include "private/dict.h"
 
-#define MAX_HASH_LEN 8
+#define MAX_HASH_LEN 16
+#define MAX_FILL 2
+#define GROWTH_FACTOR 4
+#define MIN_HASH_SIZE 16
 
 /* #define DEBUG_GROW */
 
@@ -67,9 +69,7 @@
     int size;
     int nbElems;
     xmlDictPtr dict;
-#ifdef HASH_RANDOMIZATION
-    int random_seed;
-#endif
+    unsigned random_seed;
 };
 
 /*
@@ -80,92 +80,88 @@
 ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
 ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
 #endif
-static unsigned long
+static unsigned
 xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
 	          const xmlChar *name2, const xmlChar *name3) {
-    unsigned long value = 0L;
-    unsigned long ch;
+    unsigned h1, h2, ch;
 
-#ifdef HASH_RANDOMIZATION
-    value = table->random_seed;
-#endif
+    HASH_INIT(h1, h2, table->random_seed);
+
     if (name != NULL) {
-	value += 30 * (*name);
 	while ((ch = *name++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
     }
-    value = value ^ ((value << 5) + (value >> 3));
+    HASH_UPDATE(h1, h2, 0);
     if (name2 != NULL) {
 	while ((ch = *name2++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
     }
-    value = value ^ ((value << 5) + (value >> 3));
+    HASH_UPDATE(h1, h2, 0);
     if (name3 != NULL) {
 	while ((ch = *name3++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
     }
-    return (value % table->size);
+
+    HASH_FINISH(h1, h2);
+
+    return (h2 % table->size);
 }
 
 #ifdef __clang__
 ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
 ATTRIBUTE_NO_SANITIZE("unsigned-shift-base")
 #endif
-static unsigned long
+static unsigned
 xmlHashComputeQKey(xmlHashTablePtr table,
 		   const xmlChar *prefix, const xmlChar *name,
 		   const xmlChar *prefix2, const xmlChar *name2,
 		   const xmlChar *prefix3, const xmlChar *name3) {
-    unsigned long value = 0L;
-    unsigned long ch;
+    unsigned h1, h2, ch;
 
-#ifdef HASH_RANDOMIZATION
-    value = table->random_seed;
-#endif
-    if (prefix != NULL)
-	value += 30 * (*prefix);
-    else
-	value += 30 * (*name);
+    HASH_INIT(h1, h2, table->random_seed);
 
     if (prefix != NULL) {
 	while ((ch = *prefix++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
-	value = value ^ ((value << 5) + (value >> 3) + ':');
+        HASH_UPDATE(h1, h2, ':');
     }
     if (name != NULL) {
 	while ((ch = *name++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
     }
-    value = value ^ ((value << 5) + (value >> 3));
+    HASH_UPDATE(h1, h2, 0);
     if (prefix2 != NULL) {
 	while ((ch = *prefix2++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
-	value = value ^ ((value << 5) + (value >> 3) + ':');
+        HASH_UPDATE(h1, h2, ':');
     }
     if (name2 != NULL) {
 	while ((ch = *name2++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
     }
-    value = value ^ ((value << 5) + (value >> 3));
+    HASH_UPDATE(h1, h2, 0);
     if (prefix3 != NULL) {
 	while ((ch = *prefix3++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
-	value = value ^ ((value << 5) + (value >> 3) + ':');
+        HASH_UPDATE(h1, h2, ':');
     }
     if (name3 != NULL) {
 	while ((ch = *name3++) != 0) {
-	    value = value ^ ((value << 5) + (value >> 3) + ch);
+            HASH_UPDATE(h1, h2, ch);
 	}
     }
-    return (value % table->size);
+
+    HASH_FINISH(h1, h2);
+
+    return (h2 % table->size);
 }
 
 /**
@@ -182,8 +178,8 @@
 
     xmlInitParser();
 
-    if (size <= 0)
-        size = 256;
+    if (size <= MIN_HASH_SIZE)
+        size = MIN_HASH_SIZE;
 
     table = xmlMalloc(sizeof(xmlHashTable));
     if (table) {
@@ -194,7 +190,9 @@
         if (table->table) {
 	    memset(table->table, 0, size * sizeof(xmlHashEntry));
 #ifdef HASH_RANDOMIZATION
-            table->random_seed = __xmlRandom();
+            table->random_seed = xmlRandom();
+#else
+            table->random_seed = 0;
 #endif
 	    return(table);
         }
@@ -235,22 +233,20 @@
  */
 static int
 xmlHashGrow(xmlHashTablePtr table, int size) {
-    unsigned long key;
+    unsigned key;
     int oldsize, i;
     xmlHashEntryPtr iter, next;
     struct _xmlHashEntry *oldtable;
 #ifdef DEBUG_GROW
-    unsigned long nbElem = 0;
+    unsigned nbElem = 0;
 #endif
 
     if (table == NULL)
 	return(-1);
-    if (size < 8)
-        return(-1);
-    if (size > 8 * 2048)
-	return(-1);
-
     oldsize = table->size;
+    if (size <= oldsize)
+        return(0);
+
     oldtable = table->table;
     if (oldtable == NULL)
         return(-1);
@@ -537,11 +533,11 @@
 xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
 	         const xmlChar *name2, const xmlChar *name3,
 		 void *userdata) {
-    unsigned long key, len = 0;
+    unsigned key, len = 0;
     xmlHashEntryPtr entry;
     xmlHashEntryPtr insert;
 
-    if ((table == NULL) || (name == NULL))
+    if ((table == NULL) || (name == NULL) || (table->nbElems == INT_MAX))
 	return(-1);
 
     /*
@@ -644,8 +640,13 @@
 
     table->nbElems++;
 
-    if (len > MAX_HASH_LEN)
-	xmlHashGrow(table, MAX_HASH_LEN * table->size);
+    if ((table->nbElems > table->size / MAX_FILL) ||
+        (len > MAX_HASH_LEN)) {
+        int newSize = table->size > INT_MAX / GROWTH_FACTOR ?
+                      INT_MAX :
+                      GROWTH_FACTOR * table->size;
+	xmlHashGrow(table, newSize);
+    }
 
     return(0);
 
@@ -676,11 +677,11 @@
 xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name,
 	           const xmlChar *name2, const xmlChar *name3,
 		   void *userdata, xmlHashDeallocator f) {
-    unsigned long key;
+    unsigned key;
     xmlHashEntryPtr entry;
     xmlHashEntryPtr insert;
 
-    if ((table == NULL) || name == NULL)
+    if ((table == NULL) || (name == NULL) || (table->nbElems == INT_MAX))
 	return(-1);
 
     /*
@@ -820,7 +821,7 @@
 void *
 xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name,
 	       const xmlChar *name2, const xmlChar *name3) {
-    unsigned long key;
+    unsigned key;
     xmlHashEntryPtr entry;
 
     if (table == NULL)
@@ -866,7 +867,7 @@
                 const xmlChar *prefix, const xmlChar *name,
 		const xmlChar *prefix2, const xmlChar *name2,
 		const xmlChar *prefix3, const xmlChar *name3) {
-    unsigned long key;
+    unsigned key;
     xmlHashEntryPtr entry;
 
     if (table == NULL)
@@ -1142,7 +1143,7 @@
 int
 xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
     const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) {
-    unsigned long key;
+    unsigned key;
     xmlHashEntryPtr entry;
     xmlHashEntryPtr prev = NULL;
 
diff --git a/third_party/libxml/src/include/libxml/HTMLparser.h b/third_party/libxml/src/include/libxml/HTMLparser.h
index e43feee..115a48a5 100644
--- a/third_party/libxml/src/include/libxml/HTMLparser.h
+++ b/third_party/libxml/src/include/libxml/HTMLparser.h
@@ -80,6 +80,23 @@
     const char *desc;   /* the description */
 };
 
+/** DOC_DISABLE */
+#ifdef LIBXML_SAX1_ENABLED
+#define XML_GLOBALS_HTML \
+  XML_OP(htmlDefaultSAXHandler, xmlSAXHandlerV1, XML_DEPRECATED)
+#else
+#define XML_GLOBALS_HTML
+#endif
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_HTML
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+#define htmlDefaultSAXHandler XML_GLOBAL_MACRO(htmlDefaultSAXHandler)
+#endif
+/** DOC_ENABLE */
+
 /*
  * There is only few public functions.
  */
@@ -316,5 +333,11 @@
 }
 #endif
 
+#else /* LIBXML_HTML_ENABLED */
+
+/** DOC_DISABLE */
+#define XML_GLOBALS_HTML
+/** DOC_ENABLE */
+
 #endif /* LIBXML_HTML_ENABLED */
 #endif /* __HTML_PARSER_H__ */
diff --git a/third_party/libxml/src/include/libxml/SAX.h b/third_party/libxml/src/include/libxml/SAX.h
index ecd3211a..eea1057 100644
--- a/third_party/libxml/src/include/libxml/SAX.h
+++ b/third_party/libxml/src/include/libxml/SAX.h
@@ -12,8 +12,6 @@
 #ifndef __XML_SAX_H__
 #define __XML_SAX_H__
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <libxml/xmlversion.h>
 #include <libxml/parser.h>
 
diff --git a/third_party/libxml/src/include/libxml/SAX2.h b/third_party/libxml/src/include/libxml/SAX2.h
index 35e7a5f4..4c4ecce8 100644
--- a/third_party/libxml/src/include/libxml/SAX2.h
+++ b/third_party/libxml/src/include/libxml/SAX2.h
@@ -12,8 +12,6 @@
 #ifndef __XML_SAX2_H__
 #define __XML_SAX2_H__
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <libxml/xmlversion.h>
 #include <libxml/parser.h>
 
diff --git a/third_party/libxml/src/include/libxml/c14n.h b/third_party/libxml/src/include/libxml/c14n.h
index 51e5419..f9bdf9b5 100644
--- a/third_party/libxml/src/include/libxml/c14n.h
+++ b/third_party/libxml/src/include/libxml/c14n.h
@@ -20,7 +20,6 @@
 #include <libxml/xmlversion.h>
 
 #ifdef LIBXML_C14N_ENABLED
-#ifdef LIBXML_OUTPUT_ENABLED
 
 #include <libxml/tree.h>
 #include <libxml/xpath.h>
@@ -122,7 +121,6 @@
 }
 #endif /* __cplusplus */
 
-#endif /* LIBXML_OUTPUT_ENABLED */
 #endif /* LIBXML_C14N_ENABLED */
 #endif /* __XML_C14N_H__ */
 
diff --git a/third_party/libxml/src/include/libxml/dict.h b/third_party/libxml/src/include/libxml/dict.h
index eb8f85db..4641a509 100644
--- a/third_party/libxml/src/include/libxml/dict.h
+++ b/third_party/libxml/src/include/libxml/dict.h
@@ -11,8 +11,9 @@
 #ifndef __XML_DICT_H__
 #define __XML_DICT_H__
 
-#include <stddef.h>
+#include <libxml/xmlstring.h>
 #include <libxml/xmlversion.h>
+#include <stddef.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/libxml/src/include/libxml/encoding.h b/third_party/libxml/src/include/libxml/encoding.h
index 91fe87d..5dbad90d 100644
--- a/third_party/libxml/src/include/libxml/encoding.h
+++ b/third_party/libxml/src/include/libxml/encoding.h
@@ -151,14 +151,6 @@
 #endif /* LIBXML_ICU_ENABLED */
 };
 
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/tree.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * Interfaces for encoding handlers.
  */
@@ -203,20 +195,18 @@
 	xmlDetectCharEncoding		(const unsigned char *in,
 					 int len);
 
-XMLPUBFUN int
-	xmlCharEncOutFunc		(xmlCharEncodingHandler *handler,
-					 xmlBufferPtr out,
-					 xmlBufferPtr in);
+struct _xmlBuffer;
+XMLPUBFUN int xmlCharEncOutFunc(xmlCharEncodingHandler* handler,
+                                struct _xmlBuffer* out,
+                                struct _xmlBuffer* in);
 
-XMLPUBFUN int
-	xmlCharEncInFunc		(xmlCharEncodingHandler *handler,
-					 xmlBufferPtr out,
-					 xmlBufferPtr in);
+XMLPUBFUN int xmlCharEncInFunc(xmlCharEncodingHandler* handler,
+                               struct _xmlBuffer* out,
+                               struct _xmlBuffer* in);
 XML_DEPRECATED
-XMLPUBFUN int
-	xmlCharEncFirstLine		(xmlCharEncodingHandler *handler,
-					 xmlBufferPtr out,
-					 xmlBufferPtr in);
+XMLPUBFUN int xmlCharEncFirstLine(xmlCharEncodingHandler* handler,
+                                  struct _xmlBuffer* out,
+                                  struct _xmlBuffer* in);
 XMLPUBFUN int
 	xmlCharEncCloseFunc		(xmlCharEncodingHandler *handler);
 
diff --git a/third_party/libxml/src/include/libxml/globals.h b/third_party/libxml/src/include/libxml/globals.h
index 5969729..f109b92 100644
--- a/third_party/libxml/src/include/libxml/globals.h
+++ b/third_party/libxml/src/include/libxml/globals.h
@@ -1,526 +1,38 @@
 /*
  * Summary: interface for all global variables of the library
- * Description: all the global variables and thread handling for
- *              those variables is handled by this module.
- *
- * The bottom of this file is automatically generated by build_glob.py
- * based on the description file global.data
+ * Description: Deprecated, don't use
  *
  * Copy: See Copyright for the status of this software.
- *
- * Author: Gary Pennington <Gary.Pennington@uk.sun.com>, Daniel Veillard
  */
 
 #ifndef __XML_GLOBALS_H
 #define __XML_GLOBALS_H
 
 #include <libxml/xmlversion.h>
+
+/*
+ * This file was required to access global variables until version v2.12.0.
+ *
+ * These includes are for backward compatibility.
+ */
+#include <libxml/HTMLparser.h>
 #include <libxml/parser.h>
+#include <libxml/threads.h>
+#include <libxml/xmlIO.h>
 #include <libxml/xmlerror.h>
-#include <libxml/SAX2.h>
-#include <libxml/xmlmemory.h>
+#include <libxml/xmlsave.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-XML_DEPRECATED
-XMLPUBFUN void xmlInitGlobals(void);
-XML_DEPRECATED
-XMLPUBFUN void xmlCleanupGlobals(void);
-
-/**
- * xmlParserInputBufferCreateFilenameFunc:
- * @URI: the URI to read from
- * @enc: the requested source encoding
- *
- * Signature for the function doing the lookup for a suitable input method
- * corresponding to an URI.
- *
- * Returns the new xmlParserInputBufferPtr in case of success or NULL if no
- *         method was found.
- */
-typedef xmlParserInputBufferPtr (*xmlParserInputBufferCreateFilenameFunc) (const char *URI,
-									   xmlCharEncoding enc);
-
-
-/**
- * xmlOutputBufferCreateFilenameFunc:
- * @URI: the URI to write to
- * @enc: the requested target encoding
- *
- * Signature for the function doing the lookup for a suitable output method
- * corresponding to an URI.
- *
- * Returns the new xmlOutputBufferPtr in case of success or NULL if no
- *         method was found.
- */
-typedef xmlOutputBufferPtr (*xmlOutputBufferCreateFilenameFunc) (const char *URI,
-								 xmlCharEncodingHandlerPtr encoder,
-								 int compression);
-
-XMLPUBFUN xmlParserInputBufferCreateFilenameFunc
-xmlParserInputBufferCreateFilenameDefault (xmlParserInputBufferCreateFilenameFunc func);
-XMLPUBFUN xmlOutputBufferCreateFilenameFunc
-xmlOutputBufferCreateFilenameDefault (xmlOutputBufferCreateFilenameFunc func);
-
-/*
- * Externally global symbols which need to be protected for backwards
- * compatibility support.
- */
-
-#undef	htmlDefaultSAXHandler
-#undef	oldXMLWDcompatibility
-#undef	xmlBufferAllocScheme
-#undef	xmlDefaultBufferSize
-#undef	xmlDefaultSAXHandler
-#undef	xmlDefaultSAXLocator
-#undef	xmlDoValidityCheckingDefaultValue
-#undef	xmlFree
-#undef	xmlGenericError
-#undef	xmlStructuredError
-#undef	xmlGenericErrorContext
-#undef	xmlStructuredErrorContext
-#undef	xmlGetWarningsDefaultValue
-#undef	xmlIndentTreeOutput
-#undef  xmlTreeIndentString
-#undef	xmlKeepBlanksDefaultValue
-#undef	xmlLineNumbersDefaultValue
-#undef	xmlLoadExtDtdDefaultValue
-#undef	xmlMalloc
-#undef	xmlMallocAtomic
-#undef	xmlMemStrdup
-#undef	xmlParserDebugEntities
-#undef	xmlParserVersion
-#undef	xmlPedanticParserDefaultValue
-#undef	xmlRealloc
-#undef	xmlSaveNoEmptyTags
-#undef	xmlSubstituteEntitiesDefaultValue
-#undef  xmlRegisterNodeDefaultValue
-#undef  xmlDeregisterNodeDefaultValue
-#undef  xmlLastError
-#undef  xmlParserInputBufferCreateFilenameValue
-#undef  xmlOutputBufferCreateFilenameValue
-
-/**
- * xmlRegisterNodeFunc:
- * @node: the current node
- *
- * Signature for the registration callback of a created node
- */
-typedef void (*xmlRegisterNodeFunc) (xmlNodePtr node);
-/**
- * xmlDeregisterNodeFunc:
- * @node: the current node
- *
- * Signature for the deregistration callback of a discarded node
- */
-typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node);
-
 typedef struct _xmlGlobalState xmlGlobalState;
-typedef xmlGlobalState *xmlGlobalStatePtr;
-struct _xmlGlobalState
-{
-	const char *xmlParserVersion;
+typedef xmlGlobalState* xmlGlobalStatePtr;
 
-	xmlSAXLocator xmlDefaultSAXLocator;
-	xmlSAXHandlerV1 xmlDefaultSAXHandler;
-	xmlSAXHandlerV1 docbDefaultSAXHandler; /* unused */
-	xmlSAXHandlerV1 htmlDefaultSAXHandler;
-
-	xmlFreeFunc xmlFree;
-	xmlMallocFunc xmlMalloc;
-	xmlStrdupFunc xmlMemStrdup;
-	xmlReallocFunc xmlRealloc;
-
-	xmlGenericErrorFunc xmlGenericError;
-	xmlStructuredErrorFunc xmlStructuredError;
-	void *xmlGenericErrorContext;
-
-	int oldXMLWDcompatibility;
-
-	xmlBufferAllocationScheme xmlBufferAllocScheme;
-	int xmlDefaultBufferSize;
-
-	int xmlSubstituteEntitiesDefaultValue;
-	int xmlDoValidityCheckingDefaultValue;
-	int xmlGetWarningsDefaultValue;
-	int xmlKeepBlanksDefaultValue;
-	int xmlLineNumbersDefaultValue;
-	int xmlLoadExtDtdDefaultValue;
-	int xmlParserDebugEntities;
-	int xmlPedanticParserDefaultValue;
-
-	int xmlSaveNoEmptyTags;
-	int xmlIndentTreeOutput;
-	const char *xmlTreeIndentString;
-
-	xmlRegisterNodeFunc xmlRegisterNodeDefaultValue;
-	xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue;
-
-	xmlMallocFunc xmlMallocAtomic;
-	xmlError xmlLastError;
-
-	xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue;
-	xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue;
-
-	void *xmlStructuredErrorContext;
-};
-
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/threads.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-XMLPUBFUN void	xmlInitializeGlobalState(xmlGlobalStatePtr gs);
-
-XMLPUBFUN void xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler);
-
-XMLPUBFUN void xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler);
-
-XMLPUBFUN xmlRegisterNodeFunc xmlRegisterNodeDefault(xmlRegisterNodeFunc func);
-XMLPUBFUN xmlRegisterNodeFunc xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func);
-XMLPUBFUN xmlDeregisterNodeFunc xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func);
-XMLPUBFUN xmlDeregisterNodeFunc xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func);
-
-XMLPUBFUN xmlOutputBufferCreateFilenameFunc
-	xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func);
-XMLPUBFUN xmlParserInputBufferCreateFilenameFunc
-	xmlThrDefParserInputBufferCreateFilenameDefault(
-				xmlParserInputBufferCreateFilenameFunc func);
-
-/*
- * In general the memory allocation entry points are not kept
- * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED
- *    - xmlMalloc
- *    - xmlMallocAtomic
- *    - xmlRealloc
- *    - xmlMemStrdup
- *    - xmlFree
- */
-
-#ifdef LIBXML_THREAD_ALLOC_ENABLED
-/** DOC_DISABLE */
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlMallocFunc * __xmlMalloc(void);
-#define xmlMalloc \
-(*(__xmlMalloc()))
-#else
-XMLPUBVAR xmlMallocFunc xmlMalloc;
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlMallocFunc * __xmlMallocAtomic(void);
-#define xmlMallocAtomic \
-(*(__xmlMallocAtomic()))
-#else
-XMLPUBVAR xmlMallocFunc xmlMallocAtomic;
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlReallocFunc * __xmlRealloc(void);
-#define xmlRealloc \
-(*(__xmlRealloc()))
-#else
-XMLPUBVAR xmlReallocFunc xmlRealloc;
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlFreeFunc * __xmlFree(void);
-#define xmlFree \
-(*(__xmlFree()))
-#else
-XMLPUBVAR xmlFreeFunc xmlFree;
-#endif
-
-#ifdef LIBXML_THREAD_ENABLED
-XMLPUBFUN  xmlStrdupFunc * __xmlMemStrdup(void);
-#define xmlMemStrdup \
-(*(__xmlMemStrdup()))
-#else
-XMLPUBVAR xmlStrdupFunc xmlMemStrdup;
-#endif
-
-/** DOC_ENABLE */
-#else /* !LIBXML_THREAD_ALLOC_ENABLED */
-XMLPUBVAR xmlMallocFunc xmlMalloc;
-XMLPUBVAR xmlMallocFunc xmlMallocAtomic;
-XMLPUBVAR xmlReallocFunc xmlRealloc;
-XMLPUBVAR xmlFreeFunc xmlFree;
-XMLPUBVAR xmlStrdupFunc xmlMemStrdup;
-#endif /* LIBXML_THREAD_ALLOC_ENABLED */
-
-#ifdef LIBXML_HTML_ENABLED
-XML_DEPRECATED
-XMLPUBFUN xmlSAXHandlerV1 * __htmlDefaultSAXHandler(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define htmlDefaultSAXHandler \
-(*(__htmlDefaultSAXHandler()))
-#else
-XML_DEPRECATED
-XMLPUBVAR xmlSAXHandlerV1 htmlDefaultSAXHandler;
-#endif
-#endif
-
-XMLPUBFUN xmlError * __xmlLastError(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlLastError \
-(*(__xmlLastError()))
-#else
-XMLPUBVAR xmlError xmlLastError;
-#endif
-
-/*
- * Everything starting from the line below is
- * Automatically generated by build_glob.py.
- * Do not modify the previous line.
- */
-
-
-XML_DEPRECATED
-XMLPUBFUN int * __oldXMLWDcompatibility(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define oldXMLWDcompatibility \
-(*(__oldXMLWDcompatibility()))
-#else
-XML_DEPRECATED
-XMLPUBVAR int oldXMLWDcompatibility;
-#endif
-
-XML_DEPRECATED
-XMLPUBFUN xmlBufferAllocationScheme * __xmlBufferAllocScheme(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlBufferAllocScheme \
-(*(__xmlBufferAllocScheme()))
-#else
-XML_DEPRECATED
-XMLPUBVAR xmlBufferAllocationScheme xmlBufferAllocScheme;
-#endif
-XML_DEPRECATED
-XMLPUBFUN xmlBufferAllocationScheme
-	xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v);
-
-XML_DEPRECATED
-XMLPUBFUN int * __xmlDefaultBufferSize(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDefaultBufferSize \
-(*(__xmlDefaultBufferSize()))
-#else
-XML_DEPRECATED
-XMLPUBVAR int xmlDefaultBufferSize;
-#endif
-XML_DEPRECATED
-XMLPUBFUN int xmlThrDefDefaultBufferSize(int v);
-
-XML_DEPRECATED
-XMLPUBFUN xmlSAXHandlerV1 * __xmlDefaultSAXHandler(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDefaultSAXHandler \
-(*(__xmlDefaultSAXHandler()))
-#else
-XML_DEPRECATED
-XMLPUBVAR xmlSAXHandlerV1 xmlDefaultSAXHandler;
-#endif
-
-XML_DEPRECATED
-XMLPUBFUN xmlSAXLocator * __xmlDefaultSAXLocator(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDefaultSAXLocator \
-(*(__xmlDefaultSAXLocator()))
-#else
-XML_DEPRECATED
-XMLPUBVAR xmlSAXLocator xmlDefaultSAXLocator;
-#endif
-
-XMLPUBFUN int * __xmlDoValidityCheckingDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDoValidityCheckingDefaultValue \
-(*(__xmlDoValidityCheckingDefaultValue()))
-#else
-XMLPUBVAR int xmlDoValidityCheckingDefaultValue;
-#endif
-XMLPUBFUN int xmlThrDefDoValidityCheckingDefaultValue(int v);
-
-XMLPUBFUN xmlGenericErrorFunc * __xmlGenericError(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlGenericError \
-(*(__xmlGenericError()))
-#else
-XMLPUBVAR xmlGenericErrorFunc xmlGenericError;
-#endif
-
-XMLPUBFUN xmlStructuredErrorFunc * __xmlStructuredError(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlStructuredError \
-(*(__xmlStructuredError()))
-#else
-XMLPUBVAR xmlStructuredErrorFunc xmlStructuredError;
-#endif
-
-XMLPUBFUN void * * __xmlGenericErrorContext(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlGenericErrorContext \
-(*(__xmlGenericErrorContext()))
-#else
-XMLPUBVAR void * xmlGenericErrorContext;
-#endif
-
-XMLPUBFUN void * * __xmlStructuredErrorContext(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlStructuredErrorContext \
-(*(__xmlStructuredErrorContext()))
-#else
-XMLPUBVAR void * xmlStructuredErrorContext;
-#endif
-
-XMLPUBFUN int * __xmlGetWarningsDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlGetWarningsDefaultValue \
-(*(__xmlGetWarningsDefaultValue()))
-#else
-XMLPUBVAR int xmlGetWarningsDefaultValue;
-#endif
-XMLPUBFUN int xmlThrDefGetWarningsDefaultValue(int v);
-
-XMLPUBFUN int * __xmlIndentTreeOutput(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlIndentTreeOutput \
-(*(__xmlIndentTreeOutput()))
-#else
-XMLPUBVAR int xmlIndentTreeOutput;
-#endif
-XMLPUBFUN int xmlThrDefIndentTreeOutput(int v);
-
-XMLPUBFUN const char * * __xmlTreeIndentString(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlTreeIndentString \
-(*(__xmlTreeIndentString()))
-#else
-XMLPUBVAR const char * xmlTreeIndentString;
-#endif
-XMLPUBFUN const char * xmlThrDefTreeIndentString(const char * v);
-
-XMLPUBFUN int * __xmlKeepBlanksDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlKeepBlanksDefaultValue \
-(*(__xmlKeepBlanksDefaultValue()))
-#else
-XMLPUBVAR int xmlKeepBlanksDefaultValue;
-#endif
-XMLPUBFUN int xmlThrDefKeepBlanksDefaultValue(int v);
-
-XML_DEPRECATED
-XMLPUBFUN int * __xmlLineNumbersDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlLineNumbersDefaultValue \
-(*(__xmlLineNumbersDefaultValue()))
-#else
-XML_DEPRECATED
-XMLPUBVAR int xmlLineNumbersDefaultValue;
-#endif
-XML_DEPRECATED
-XMLPUBFUN int xmlThrDefLineNumbersDefaultValue(int v);
-
-XMLPUBFUN int * __xmlLoadExtDtdDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlLoadExtDtdDefaultValue \
-(*(__xmlLoadExtDtdDefaultValue()))
-#else
-XMLPUBVAR int xmlLoadExtDtdDefaultValue;
-#endif
-XMLPUBFUN int xmlThrDefLoadExtDtdDefaultValue(int v);
-
-XMLPUBFUN int * __xmlParserDebugEntities(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlParserDebugEntities \
-(*(__xmlParserDebugEntities()))
-#else
-XMLPUBVAR int xmlParserDebugEntities;
-#endif
-XMLPUBFUN int xmlThrDefParserDebugEntities(int v);
-
-XMLPUBFUN const char * * __xmlParserVersion(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlParserVersion \
-(*(__xmlParserVersion()))
-#else
-XMLPUBVAR const char * xmlParserVersion;
-#endif
-
-XML_DEPRECATED
-XMLPUBFUN int * __xmlPedanticParserDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlPedanticParserDefaultValue \
-(*(__xmlPedanticParserDefaultValue()))
-#else
-XML_DEPRECATED
-XMLPUBVAR int xmlPedanticParserDefaultValue;
-#endif
-XML_DEPRECATED
-XMLPUBFUN int xmlThrDefPedanticParserDefaultValue(int v);
-
-XMLPUBFUN int * __xmlSaveNoEmptyTags(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlSaveNoEmptyTags \
-(*(__xmlSaveNoEmptyTags()))
-#else
-XMLPUBVAR int xmlSaveNoEmptyTags;
-#endif
-XMLPUBFUN int xmlThrDefSaveNoEmptyTags(int v);
-
-XMLPUBFUN int * __xmlSubstituteEntitiesDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlSubstituteEntitiesDefaultValue \
-(*(__xmlSubstituteEntitiesDefaultValue()))
-#else
-XMLPUBVAR int xmlSubstituteEntitiesDefaultValue;
-#endif
-XMLPUBFUN int xmlThrDefSubstituteEntitiesDefaultValue(int v);
-
-XML_DEPRECATED
-XMLPUBFUN xmlRegisterNodeFunc * __xmlRegisterNodeDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlRegisterNodeDefaultValue \
-(*(__xmlRegisterNodeDefaultValue()))
-#else
-XML_DEPRECATED
-XMLPUBVAR xmlRegisterNodeFunc xmlRegisterNodeDefaultValue;
-#endif
-
-XML_DEPRECATED
-XMLPUBFUN xmlDeregisterNodeFunc * __xmlDeregisterNodeDefaultValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlDeregisterNodeDefaultValue \
-(*(__xmlDeregisterNodeDefaultValue()))
-#else
-XML_DEPRECATED
-XMLPUBVAR xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue;
-#endif
-
-XML_DEPRECATED
-XMLPUBFUN xmlParserInputBufferCreateFilenameFunc * \
-				__xmlParserInputBufferCreateFilenameValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlParserInputBufferCreateFilenameValue \
-(*(__xmlParserInputBufferCreateFilenameValue()))
-#else
-XML_DEPRECATED
-XMLPUBVAR xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue;
-#endif
-
-XML_DEPRECATED
-XMLPUBFUN xmlOutputBufferCreateFilenameFunc * __xmlOutputBufferCreateFilenameValue(void);
-#ifdef LIBXML_THREAD_ENABLED
-#define xmlOutputBufferCreateFilenameValue \
-(*(__xmlOutputBufferCreateFilenameValue()))
-#else
-XML_DEPRECATED
-XMLPUBVAR xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue;
-#endif
+XML_DEPRECATED XMLPUBFUN void xmlInitGlobals(void);
+XML_DEPRECATED XMLPUBFUN void xmlCleanupGlobals(void);
+XML_DEPRECATED XMLPUBFUN void xmlInitializeGlobalState(xmlGlobalStatePtr gs);
+XML_DEPRECATED XMLPUBFUN xmlGlobalStatePtr xmlGetGlobalState(void);
 
 #ifdef __cplusplus
 }
diff --git a/third_party/libxml/src/include/libxml/hash.h b/third_party/libxml/src/include/libxml/hash.h
index 1dac035..4185338 100644
--- a/third_party/libxml/src/include/libxml/hash.h
+++ b/third_party/libxml/src/include/libxml/hash.h
@@ -11,6 +11,10 @@
 #ifndef __XML_HASH_H__
 #define __XML_HASH_H__
 
+#include <libxml/dict.h>
+#include <libxml/xmlstring.h>
+#include <libxml/xmlversion.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -21,18 +25,6 @@
 typedef struct _xmlHashTable xmlHashTable;
 typedef xmlHashTable *xmlHashTablePtr;
 
-#ifdef __cplusplus
-}
-#endif
-
-#include <libxml/xmlversion.h>
-#include <libxml/parser.h>
-#include <libxml/dict.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * Recent version of gcc produce a warning when a function pointer is assigned
  * to an object pointer, or vice versa.  The following macro is a dirty hack
@@ -55,7 +47,6 @@
 
 #define XML_CAST_FPTR(fptr) fptr
 
-
 /*
  * function types:
  */
@@ -103,133 +94,108 @@
 /*
  * Constructor and destructor.
  */
-XMLPUBFUN xmlHashTablePtr
-			xmlHashCreate	(int size);
-XMLPUBFUN xmlHashTablePtr
-			xmlHashCreateDict(int size,
-					 xmlDictPtr dict);
-XMLPUBFUN void
-			xmlHashFree	(xmlHashTablePtr table,
-					 xmlHashDeallocator f);
-XMLPUBFUN void
-			xmlHashDefaultDeallocator(void *entry,
-					 const xmlChar *name);
+XMLPUBFUN xmlHashTablePtr xmlHashCreate(int size);
+XMLPUBFUN xmlHashTablePtr xmlHashCreateDict(int size, xmlDictPtr dict);
+XMLPUBFUN void xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc);
+XMLPUBFUN void xmlHashDefaultDeallocator(void* entry, const xmlChar* name);
 
 /*
  * Add a new entry to the hash table.
  */
-XMLPUBFUN int
-			xmlHashAddEntry	(xmlHashTablePtr table,
-		                         const xmlChar *name,
-		                         void *userdata);
-XMLPUBFUN int
-			xmlHashUpdateEntry(xmlHashTablePtr table,
-		                         const xmlChar *name,
-		                         void *userdata,
-					 xmlHashDeallocator f);
-XMLPUBFUN int
-			xmlHashAddEntry2(xmlHashTablePtr table,
-		                         const xmlChar *name,
-		                         const xmlChar *name2,
-		                         void *userdata);
-XMLPUBFUN int
-			xmlHashUpdateEntry2(xmlHashTablePtr table,
-		                         const xmlChar *name,
-		                         const xmlChar *name2,
-		                         void *userdata,
-					 xmlHashDeallocator f);
-XMLPUBFUN int
-			xmlHashAddEntry3(xmlHashTablePtr table,
-		                         const xmlChar *name,
-		                         const xmlChar *name2,
-		                         const xmlChar *name3,
-		                         void *userdata);
-XMLPUBFUN int
-			xmlHashUpdateEntry3(xmlHashTablePtr table,
-		                         const xmlChar *name,
-		                         const xmlChar *name2,
-		                         const xmlChar *name3,
-		                         void *userdata,
-					 xmlHashDeallocator f);
+XMLPUBFUN int xmlHashAddEntry(xmlHashTablePtr hash,
+                              const xmlChar* name,
+                              void* userdata);
+XMLPUBFUN int xmlHashUpdateEntry(xmlHashTablePtr hash,
+                                 const xmlChar* name,
+                                 void* userdata,
+                                 xmlHashDeallocator dealloc);
+XMLPUBFUN int xmlHashAddEntry2(xmlHashTablePtr hash,
+                               const xmlChar* name,
+                               const xmlChar* name2,
+                               void* userdata);
+XMLPUBFUN int xmlHashUpdateEntry2(xmlHashTablePtr hash,
+                                  const xmlChar* name,
+                                  const xmlChar* name2,
+                                  void* userdata,
+                                  xmlHashDeallocator dealloc);
+XMLPUBFUN int xmlHashAddEntry3(xmlHashTablePtr hash,
+                               const xmlChar* name,
+                               const xmlChar* name2,
+                               const xmlChar* name3,
+                               void* userdata);
+XMLPUBFUN int xmlHashUpdateEntry3(xmlHashTablePtr hash,
+                                  const xmlChar* name,
+                                  const xmlChar* name2,
+                                  const xmlChar* name3,
+                                  void* userdata,
+                                  xmlHashDeallocator dealloc);
 
 /*
  * Remove an entry from the hash table.
  */
-XMLPUBFUN int
-			xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name,
-                           xmlHashDeallocator f);
-XMLPUBFUN int
-			xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name,
-                            const xmlChar *name2, xmlHashDeallocator f);
-XMLPUBFUN int 
-			xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name,
-                            const xmlChar *name2, const xmlChar *name3,
-                            xmlHashDeallocator f);
+XMLPUBFUN int xmlHashRemoveEntry(xmlHashTablePtr hash,
+                                 const xmlChar* name,
+                                 xmlHashDeallocator dealloc);
+XMLPUBFUN int xmlHashRemoveEntry2(xmlHashTablePtr hash,
+                                  const xmlChar* name,
+                                  const xmlChar* name2,
+                                  xmlHashDeallocator dealloc);
+XMLPUBFUN int xmlHashRemoveEntry3(xmlHashTablePtr hash,
+                                  const xmlChar* name,
+                                  const xmlChar* name2,
+                                  const xmlChar* name3,
+                                  xmlHashDeallocator dealloc);
 
 /*
- * Retrieve the userdata.
+ * Retrieve the payload.
  */
-XMLPUBFUN void *
-			xmlHashLookup	(xmlHashTablePtr table,
-					 const xmlChar *name);
-XMLPUBFUN void *
-			xmlHashLookup2	(xmlHashTablePtr table,
-					 const xmlChar *name,
-					 const xmlChar *name2);
-XMLPUBFUN void *
-			xmlHashLookup3	(xmlHashTablePtr table,
-					 const xmlChar *name,
-					 const xmlChar *name2,
-					 const xmlChar *name3);
-XMLPUBFUN void *
-			xmlHashQLookup	(xmlHashTablePtr table,
-					 const xmlChar *name,
-					 const xmlChar *prefix);
-XMLPUBFUN void *
-			xmlHashQLookup2	(xmlHashTablePtr table,
-					 const xmlChar *name,
-					 const xmlChar *prefix,
-					 const xmlChar *name2,
-					 const xmlChar *prefix2);
-XMLPUBFUN void *
-			xmlHashQLookup3	(xmlHashTablePtr table,
-					 const xmlChar *name,
-					 const xmlChar *prefix,
-					 const xmlChar *name2,
-					 const xmlChar *prefix2,
-					 const xmlChar *name3,
-					 const xmlChar *prefix3);
+XMLPUBFUN void* xmlHashLookup(xmlHashTablePtr hash, const xmlChar* name);
+XMLPUBFUN void* xmlHashLookup2(xmlHashTablePtr hash,
+                               const xmlChar* name,
+                               const xmlChar* name2);
+XMLPUBFUN void* xmlHashLookup3(xmlHashTablePtr hash,
+                               const xmlChar* name,
+                               const xmlChar* name2,
+                               const xmlChar* name3);
+XMLPUBFUN void* xmlHashQLookup(xmlHashTablePtr hash,
+                               const xmlChar* prefix,
+                               const xmlChar* name);
+XMLPUBFUN void* xmlHashQLookup2(xmlHashTablePtr hash,
+                                const xmlChar* prefix,
+                                const xmlChar* name,
+                                const xmlChar* prefix2,
+                                const xmlChar* name2);
+XMLPUBFUN void* xmlHashQLookup3(xmlHashTablePtr hash,
+                                const xmlChar* prefix,
+                                const xmlChar* name,
+                                const xmlChar* prefix2,
+                                const xmlChar* name2,
+                                const xmlChar* prefix3,
+                                const xmlChar* name3);
 
 /*
  * Helpers.
  */
-XMLPUBFUN xmlHashTablePtr
-			xmlHashCopy	(xmlHashTablePtr table,
-					 xmlHashCopier f);
-XMLPUBFUN int
-			xmlHashSize	(xmlHashTablePtr table);
-XMLPUBFUN void
-			xmlHashScan	(xmlHashTablePtr table,
-					 xmlHashScanner f,
-					 void *data);
-XMLPUBFUN void
-			xmlHashScan3	(xmlHashTablePtr table,
-					 const xmlChar *name,
-					 const xmlChar *name2,
-					 const xmlChar *name3,
-					 xmlHashScanner f,
-					 void *data);
-XMLPUBFUN void
-			xmlHashScanFull	(xmlHashTablePtr table,
-					 xmlHashScannerFull f,
-					 void *data);
-XMLPUBFUN void
-			xmlHashScanFull3(xmlHashTablePtr table,
-					 const xmlChar *name,
-					 const xmlChar *name2,
-					 const xmlChar *name3,
-					 xmlHashScannerFull f,
-					 void *data);
+XMLPUBFUN xmlHashTablePtr xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy);
+XMLPUBFUN int xmlHashSize(xmlHashTablePtr hash);
+XMLPUBFUN void xmlHashScan(xmlHashTablePtr hash,
+                           xmlHashScanner scan,
+                           void* data);
+XMLPUBFUN void xmlHashScan3(xmlHashTablePtr hash,
+                            const xmlChar* name,
+                            const xmlChar* name2,
+                            const xmlChar* name3,
+                            xmlHashScanner scan,
+                            void* data);
+XMLPUBFUN void xmlHashScanFull(xmlHashTablePtr hash,
+                               xmlHashScannerFull scan,
+                               void* data);
+XMLPUBFUN void xmlHashScanFull3(xmlHashTablePtr hash,
+                                const xmlChar* name,
+                                const xmlChar* name2,
+                                const xmlChar* name3,
+                                xmlHashScannerFull scan,
+                                void* data);
 #ifdef __cplusplus
 }
 #endif
diff --git a/third_party/libxml/src/include/libxml/nanoftp.h b/third_party/libxml/src/include/libxml/nanoftp.h
index 87a22aa..ed3ac4f 100644
--- a/third_party/libxml/src/include/libxml/nanoftp.h
+++ b/third_party/libxml/src/include/libxml/nanoftp.h
@@ -14,7 +14,7 @@
 
 #include <libxml/xmlversion.h>
 
-#ifdef LIBXML_FTP_ENABLED
+#if defined(LIBXML_FTP_ENABLED)
 
 /* Needed for portability to Windows 64 bits */
 #if defined(_WIN32)
@@ -182,5 +182,5 @@
 #ifdef __cplusplus
 }
 #endif
-#endif /* LIBXML_FTP_ENABLED */
+#endif /* defined(LIBXML_FTP_ENABLED) || defined(LIBXML_LEGACY_ENABLED) */
 #endif /* __NANO_FTP_H__ */
diff --git a/third_party/libxml/src/include/libxml/parser.h b/third_party/libxml/src/include/libxml/parser.h
index 51d71e6..50e89de 100644
--- a/third_party/libxml/src/include/libxml/parser.h
+++ b/third_party/libxml/src/include/libxml/parser.h
@@ -10,14 +10,20 @@
 #ifndef __XML_PARSER_H__
 #define __XML_PARSER_H__
 
-#include <libxml/xmlversion.h>
-#include <libxml/tree.h>
 #include <libxml/dict.h>
-#include <libxml/hash.h>
-#include <libxml/valid.h>
+#include <libxml/encoding.h>
 #include <libxml/entities.h>
+#include <libxml/hash.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/xmlIO.h>
 #include <libxml/xmlerror.h>
+#include <libxml/xmlmemory.h>
 #include <libxml/xmlstring.h>
+#include <libxml/xmlversion.h>
+/* for compatibility */
+#include <libxml/SAX2.h>
+#include <libxml/threads.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -63,9 +69,9 @@
     int col;                          /* Current column */
     unsigned long consumed;           /* How many xmlChars already consumed */
     xmlParserInputDeallocate free;    /* function to deallocate the base */
-    const xmlChar *encoding;          /* the encoding string for entity */
+    const xmlChar* encoding;          /* unused */
     const xmlChar *version;           /* the version string for entity */
-    int standalone;                   /* Was that entity marked standalone */
+    int flags;                        /* Flags */
     int id;                           /* an unique identifier for the entity */
     unsigned long parentConsumed;     /* consumed bytes from parents */
     xmlEntityPtr entity;              /* entity, if any */
@@ -105,24 +111,25 @@
  * The recursive one use the state info for entities processing.
  */
 typedef enum {
-    XML_PARSER_EOF = -1,	/* nothing is to be parsed */
-    XML_PARSER_START = 0,	/* nothing has been parsed */
-    XML_PARSER_MISC,		/* Misc* before int subset */
-    XML_PARSER_PI,		/* Within a processing instruction */
-    XML_PARSER_DTD,		/* within some DTD content */
-    XML_PARSER_PROLOG,		/* Misc* after internal subset */
-    XML_PARSER_COMMENT,		/* within a comment */
-    XML_PARSER_START_TAG,	/* within a start tag */
-    XML_PARSER_CONTENT,		/* within the content */
-    XML_PARSER_CDATA_SECTION,	/* within a CDATA section */
-    XML_PARSER_END_TAG,		/* within a closing tag */
-    XML_PARSER_ENTITY_DECL,	/* within an entity declaration */
-    XML_PARSER_ENTITY_VALUE,	/* within an entity value in a decl */
-    XML_PARSER_ATTRIBUTE_VALUE,	/* within an attribute value */
-    XML_PARSER_SYSTEM_LITERAL,	/* within a SYSTEM value */
-    XML_PARSER_EPILOG,		/* the Misc* after the last end tag */
-    XML_PARSER_IGNORE,		/* within an IGNORED section */
-    XML_PARSER_PUBLIC_LITERAL	/* within a PUBLIC value */
+  XML_PARSER_EOF = -1,        /* nothing is to be parsed */
+  XML_PARSER_START = 0,       /* nothing has been parsed */
+  XML_PARSER_MISC,            /* Misc* before int subset */
+  XML_PARSER_PI,              /* Within a processing instruction */
+  XML_PARSER_DTD,             /* within some DTD content */
+  XML_PARSER_PROLOG,          /* Misc* after internal subset */
+  XML_PARSER_COMMENT,         /* within a comment */
+  XML_PARSER_START_TAG,       /* within a start tag */
+  XML_PARSER_CONTENT,         /* within the content */
+  XML_PARSER_CDATA_SECTION,   /* within a CDATA section */
+  XML_PARSER_END_TAG,         /* within a closing tag */
+  XML_PARSER_ENTITY_DECL,     /* within an entity declaration */
+  XML_PARSER_ENTITY_VALUE,    /* within an entity value in a decl */
+  XML_PARSER_ATTRIBUTE_VALUE, /* within an attribute value */
+  XML_PARSER_SYSTEM_LITERAL,  /* within a SYSTEM value */
+  XML_PARSER_EPILOG,          /* the Misc* after the last end tag */
+  XML_PARSER_IGNORE,          /* within an IGNORED section */
+  XML_PARSER_PUBLIC_LITERAL,  /* within a PUBLIC value */
+  XML_PARSER_XML_DECL         /* before XML decl (but after BOM) */
 } xmlParserInputState;
 
 /**
@@ -245,8 +252,7 @@
 
     int                depth;         /* to prevent entity substitution loops */
     xmlParserInputPtr  entity;        /* used to check entities boundaries */
-    int                charset;       /* encoding of the in-memory content
-				         actually an xmlCharEncoding */
+    int charset;                      /* unused */
     int                nodelen;       /* Those two fields are there to */
     int                nodemem;       /* Speed up large node parsing */
     int                pedantic;      /* signal pedantic warnings */
@@ -312,6 +318,7 @@
     int           endCheckState;    /* quote state for push parser */
     unsigned short     nbErrors;    /* number of errors */
     unsigned short   nbWarnings;    /* number of warnings */
+    unsigned maxAmpl;               /* maximum amplification factor */
 };
 
 /**
@@ -804,18 +811,61 @@
 					 const char *ID,
 					 xmlParserCtxtPtr context);
 
-#ifdef __cplusplus
-}
+/*
+ * Variables
+ */
+
+XMLPUBVAR const char* const xmlParserVersion;
+#ifdef LIBXML_THREAD_ENABLED
+/* backward compatibility */
+XMLPUBFUN const char* const* __xmlParserVersion(void);
 #endif
 
-#include <libxml/encoding.h>
-#include <libxml/xmlIO.h>
-#include <libxml/globals.h>
+/** DOC_DISABLE */
+#define XML_GLOBALS_PARSER_CORE                                  \
+  XML_OP(oldXMLWDcompatibility, int, XML_DEPRECATED)             \
+  XML_OP(xmlDefaultSAXLocator, xmlSAXLocator, XML_DEPRECATED)    \
+  XML_OP(xmlDoValidityCheckingDefaultValue, int, XML_DEPRECATED) \
+  XML_OP(xmlGetWarningsDefaultValue, int, XML_DEPRECATED)        \
+  XML_OP(xmlKeepBlanksDefaultValue, int, XML_DEPRECATED)         \
+  XML_OP(xmlLineNumbersDefaultValue, int, XML_DEPRECATED)        \
+  XML_OP(xmlLoadExtDtdDefaultValue, int, XML_DEPRECATED)         \
+  XML_OP(xmlParserDebugEntities, int, XML_DEPRECATED)            \
+  XML_OP(xmlPedanticParserDefaultValue, int, XML_DEPRECATED)     \
+  XML_OP(xmlSubstituteEntitiesDefaultValue, int, XML_DEPRECATED)
 
-#ifdef __cplusplus
-extern "C" {
+#ifdef LIBXML_SAX1_ENABLED
+#define XML_GLOBALS_PARSER_SAX1 \
+  XML_OP(xmlDefaultSAXHandler, xmlSAXHandlerV1, XML_DEPRECATED)
+#else
+#define XML_GLOBALS_PARSER_SAX1
 #endif
 
+#define XML_GLOBALS_PARSER \
+  XML_GLOBALS_PARSER_CORE  \
+  XML_GLOBALS_PARSER_SAX1
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_PARSER
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+#define oldXMLWDcompatibility XML_GLOBAL_MACRO(oldXMLWDcompatibility)
+#define xmlDefaultSAXHandler XML_GLOBAL_MACRO(xmlDefaultSAXHandler)
+#define xmlDefaultSAXLocator XML_GLOBAL_MACRO(xmlDefaultSAXLocator)
+#define xmlDoValidityCheckingDefaultValue \
+  XML_GLOBAL_MACRO(xmlDoValidityCheckingDefaultValue)
+#define xmlGetWarningsDefaultValue XML_GLOBAL_MACRO(xmlGetWarningsDefaultValue)
+#define xmlKeepBlanksDefaultValue XML_GLOBAL_MACRO(xmlKeepBlanksDefaultValue)
+#define xmlLineNumbersDefaultValue XML_GLOBAL_MACRO(xmlLineNumbersDefaultValue)
+#define xmlLoadExtDtdDefaultValue XML_GLOBAL_MACRO(xmlLoadExtDtdDefaultValue)
+#define xmlParserDebugEntities XML_GLOBAL_MACRO(xmlParserDebugEntities)
+#define xmlPedanticParserDefaultValue \
+  XML_GLOBAL_MACRO(xmlPedanticParserDefaultValue)
+#define xmlSubstituteEntitiesDefaultValue \
+  XML_GLOBAL_MACRO(xmlSubstituteEntitiesDefaultValue)
+#endif
+/** DOC_ENABLE */
 
 /*
  * Init/Cleanup
@@ -849,16 +899,20 @@
 		xmlParseMemory		(const char *buffer,
 					 int size);
 #endif /* LIBXML_SAX1_ENABLED */
-XMLPUBFUN int
-		xmlSubstituteEntitiesDefault(int val);
-XMLPUBFUN int
-		xmlKeepBlanksDefault	(int val);
+XML_DEPRECATED XMLPUBFUN int xmlSubstituteEntitiesDefault(int val);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefSubstituteEntitiesDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int xmlKeepBlanksDefault(int val);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefKeepBlanksDefaultValue(int v);
 XMLPUBFUN void
 		xmlStopParser		(xmlParserCtxtPtr ctxt);
-XMLPUBFUN int
-		xmlPedanticParserDefault(int val);
-XMLPUBFUN int
-		xmlLineNumbersDefault	(int val);
+XML_DEPRECATED XMLPUBFUN int xmlPedanticParserDefault(int val);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefPedanticParserDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int xmlLineNumbersDefault(int val);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefLineNumbersDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefDoValidityCheckingDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefGetWarningsDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefLoadExtDtdDefaultValue(int v);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefParserDebugEntities(int v);
 
 #ifdef LIBXML_SAX1_ENABLED
 /*
@@ -1151,6 +1205,8 @@
 XMLPUBFUN int
 		xmlCtxtUseOptions	(xmlParserCtxtPtr ctxt,
 					 int options);
+XMLPUBFUN void xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt,
+                                          unsigned maxAmpl);
 XMLPUBFUN xmlDocPtr
 		xmlReadDoc		(const xmlChar *cur,
 					 const char *URL,
diff --git a/third_party/libxml/src/include/libxml/parserInternals.h b/third_party/libxml/src/include/libxml/parserInternals.h
index 513981e..8ef4568 100644
--- a/third_party/libxml/src/include/libxml/parserInternals.h
+++ b/third_party/libxml/src/include/libxml/parserInternals.h
@@ -12,10 +12,11 @@
 #ifndef __XML_PARSER_INTERNALS_H__
 #define __XML_PARSER_INTERNALS_H__
 
-#include <libxml/xmlversion.h>
-#include <libxml/parser.h>
 #include <libxml/HTMLparser.h>
+#include <libxml/SAX2.h>
 #include <libxml/chvalid.h>
+#include <libxml/parser.h>
+#include <libxml/xmlversion.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/libxml/src/include/libxml/relaxng.h b/third_party/libxml/src/include/libxml/relaxng.h
index aecaea3..4662507 100644
--- a/third_party/libxml/src/include/libxml/relaxng.h
+++ b/third_party/libxml/src/include/libxml/relaxng.h
@@ -10,9 +10,9 @@
 #ifndef __XML_RELAX_NG__
 #define __XML_RELAX_NG__
 
-#include <libxml/xmlversion.h>
-#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
 #include <libxml/xmlstring.h>
+#include <libxml/xmlversion.h>
 
 #ifdef LIBXML_SCHEMAS_ENABLED
 
diff --git a/third_party/libxml/src/include/libxml/threads.h b/third_party/libxml/src/include/libxml/threads.h
index dd2304cc4..3c46e019 100644
--- a/third_party/libxml/src/include/libxml/threads.h
+++ b/third_party/libxml/src/include/libxml/threads.h
@@ -29,13 +29,8 @@
 typedef struct _xmlRMutex xmlRMutex;
 typedef xmlRMutex *xmlRMutexPtr;
 
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/globals.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+XMLPUBFUN int xmlCheckThreadLocalStorage(void);
+
 XMLPUBFUN xmlMutexPtr
 			xmlNewMutex	(void);
 XMLPUBFUN void
@@ -73,13 +68,10 @@
 XML_DEPRECATED
 XMLPUBFUN void
 			xmlCleanupThreads(void);
-XML_DEPRECATED
-XMLPUBFUN xmlGlobalStatePtr
-			xmlGetGlobalState(void);
 
 /** DOC_DISABLE */
 #if defined(LIBXML_THREAD_ENABLED) && defined(_WIN32) && \
-    !defined(HAVE_COMPILER_TLS) && defined(LIBXML_STATIC_FOR_DLL)
+    defined(LIBXML_STATIC_FOR_DLL)
 int
 xmlDllMain(void *hinstDLL, unsigned long fdwReason,
            void *lpvReserved);
diff --git a/third_party/libxml/src/include/libxml/tree.h b/third_party/libxml/src/include/libxml/tree.h
index a1cabf69..a1dec53 100644
--- a/third_party/libxml/src/include/libxml/tree.h
+++ b/third_party/libxml/src/include/libxml/tree.h
@@ -12,10 +12,12 @@
 #ifndef __XML_TREE_H__
 #define __XML_TREE_H__
 
-#include <stdio.h>
-#include <limits.h>
-#include <libxml/xmlversion.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlregexp.h>
 #include <libxml/xmlstring.h>
+#include <libxml/xmlversion.h>
+#include <limits.h>
+#include <stdio.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -329,14 +331,6 @@
     XML_ELEMENT_TYPE_ELEMENT
 } xmlElementTypeVal;
 
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/xmlregexp.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * xmlElement:
  *
@@ -573,12 +567,11 @@
     struct _xmlDtd  *extSubset;	/* the document external subset */
     struct _xmlNs   *oldNs;	/* Global namespace, the old way */
     const xmlChar  *version;	/* the XML version string */
-    const xmlChar  *encoding;   /* external initial encoding, if any */
+    const xmlChar* encoding;    /* actual encoding, if any */
     void           *ids;        /* Hash table for ID attributes if any */
     void           *refs;       /* Hash table for IDREFs attributes if any */
     const xmlChar  *URL;	/* The URI for that document */
-    int             charset;    /* Internal flag for charset handling,
-				   actually an xmlCharEncoding */
+    int charset;                /* unused */
     struct _xmlDict *dict;      /* dict used to allocate names or NULL */
     void           *psvi;	/* for type/PSVI information */
     int             parseFlags;	/* set of xmlParserOption used to parse the
@@ -631,6 +624,22 @@
 };
 
 /**
+ * xmlRegisterNodeFunc:
+ * @node: the current node
+ *
+ * Signature for the registration callback of a created node
+ */
+typedef void (*xmlRegisterNodeFunc)(xmlNodePtr node);
+
+/**
+ * xmlDeregisterNodeFunc:
+ * @node: the current node
+ *
+ * Signature for the deregistration callback of a discarded node
+ */
+typedef void (*xmlDeregisterNodeFunc)(xmlNodePtr node);
+
+/**
  * xmlChildrenNode:
  *
  * Macro for compatibility naming layer with libxml1. Maps
@@ -654,6 +663,27 @@
  * Variables.
  */
 
+/** DOC_DISABLE */
+#define XML_GLOBALS_TREE                                                   \
+  XML_OP(xmlBufferAllocScheme, xmlBufferAllocationScheme, XML_DEPRECATED)  \
+  XML_OP(xmlDefaultBufferSize, int, XML_DEPRECATED)                        \
+  XML_OP(xmlRegisterNodeDefaultValue, xmlRegisterNodeFunc, XML_DEPRECATED) \
+  XML_OP(xmlDeregisterNodeDefaultValue, xmlDeregisterNodeFunc, XML_DEPRECATED)
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_TREE
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+#define xmlBufferAllocScheme XML_GLOBAL_MACRO(xmlBufferAllocScheme)
+#define xmlDefaultBufferSize XML_GLOBAL_MACRO(xmlDefaultBufferSize)
+#define xmlRegisterNodeDefaultValue \
+  XML_GLOBAL_MACRO(xmlRegisterNodeDefaultValue)
+#define xmlDeregisterNodeDefaultValue \
+  XML_GLOBAL_MACRO(xmlDeregisterNodeDefaultValue)
+#endif
+/** DOC_ENABLE */
+
 /*
  * Some helper functions
  */
@@ -1297,12 +1327,22 @@
 XMLPUBFUN xmlNodePtr
             xmlPreviousElementSibling   (xmlNodePtr node);
 #endif
+
+XMLPUBFUN xmlRegisterNodeFunc xmlRegisterNodeDefault(xmlRegisterNodeFunc func);
+XMLPUBFUN xmlDeregisterNodeFunc
+xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func);
+XMLPUBFUN xmlRegisterNodeFunc
+xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func);
+XMLPUBFUN xmlDeregisterNodeFunc
+xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func);
+
+XML_DEPRECATED XMLPUBFUN xmlBufferAllocationScheme
+xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v);
+XML_DEPRECATED XMLPUBFUN int xmlThrDefDefaultBufferSize(int v);
+
 #ifdef __cplusplus
 }
 #endif
-#ifndef __XML_PARSER_H__
-#include <libxml/xmlmemory.h>
-#endif
 
 #endif /* __XML_TREE_H__ */
 
diff --git a/third_party/libxml/src/include/libxml/uri.h b/third_party/libxml/src/include/libxml/uri.h
index 0470a5d9..358600b6 100644
--- a/third_party/libxml/src/include/libxml/uri.h
+++ b/third_party/libxml/src/include/libxml/uri.h
@@ -11,8 +11,8 @@
 #ifndef __XML_URI_H__
 #define __XML_URI_H__
 
+#include <libxml/xmlstring.h>
 #include <libxml/xmlversion.h>
-#include <libxml/tree.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/libxml/src/include/libxml/xmlIO.h b/third_party/libxml/src/include/libxml/xmlIO.h
index 55d25ed9..4c3a202 100644
--- a/third_party/libxml/src/include/libxml/xmlIO.h
+++ b/third_party/libxml/src/include/libxml/xmlIO.h
@@ -10,8 +10,10 @@
 #ifndef __XML_IO_H__
 #define __XML_IO_H__
 
-#include <stdio.h>
+#include <libxml/encoding.h>
+#include <libxml/tree.h>
 #include <libxml/xmlversion.h>
+#include <stdio.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -110,18 +112,37 @@
 typedef int (*xmlOutputCloseCallback) (void * context);
 #endif /* LIBXML_OUTPUT_ENABLED */
 
-#ifdef __cplusplus
-}
-#endif
+/**
+ * xmlParserInputBufferCreateFilenameFunc:
+ * @URI: the URI to read from
+ * @enc: the requested source encoding
+ *
+ * Signature for the function doing the lookup for a suitable input method
+ * corresponding to an URI.
+ *
+ * Returns the new xmlParserInputBufferPtr in case of success or NULL if no
+ *         method was found.
+ */
+typedef xmlParserInputBufferPtr (*xmlParserInputBufferCreateFilenameFunc)(
+    const char* URI,
+    xmlCharEncoding enc);
 
-#include <libxml/globals.h>
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-#include <libxml/encoding.h>
+/**
+ * xmlOutputBufferCreateFilenameFunc:
+ * @URI: the URI to write to
+ * @enc: the requested target encoding
+ *
+ * Signature for the function doing the lookup for a suitable output method
+ * corresponding to an URI.
+ *
+ * Returns the new xmlOutputBufferPtr in case of success or NULL if no
+ *         method was found.
+ */
+typedef xmlOutputBufferPtr (*xmlOutputBufferCreateFilenameFunc)(
+    const char* URI,
+    xmlCharEncodingHandlerPtr encoder,
+    int compression);
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 struct _xmlParserInputBuffer {
     void*                  context;
     xmlInputReadCallback   readcallback;
@@ -152,6 +173,25 @@
 };
 #endif /* LIBXML_OUTPUT_ENABLED */
 
+/** DOC_DISABLE */
+#define XML_GLOBALS_IO                                           \
+  XML_OP(xmlParserInputBufferCreateFilenameValue,                \
+         xmlParserInputBufferCreateFilenameFunc, XML_DEPRECATED) \
+  XML_OP(xmlOutputBufferCreateFilenameValue,                     \
+         xmlOutputBufferCreateFilenameFunc, XML_DEPRECATED)
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_IO
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+#define xmlParserInputBufferCreateFilenameValue \
+  XML_GLOBAL_MACRO(xmlParserInputBufferCreateFilenameValue)
+#define xmlOutputBufferCreateFilenameValue \
+  XML_GLOBAL_MACRO(xmlOutputBufferCreateFilenameValue)
+#endif
+/** DOC_ENABLE */
+
 /*
  * Interfaces for input
  */
@@ -349,7 +389,7 @@
 /**
  * Default 'ftp://' protocol callbacks
  */
-#ifdef LIBXML_FTP_ENABLED
+#if defined(LIBXML_FTP_ENABLED)
 XMLPUBFUN int
 	xmlIOFTPMatch			(const char *filename);
 XMLPUBFUN void *
@@ -360,7 +400,19 @@
 					 int len);
 XMLPUBFUN int
 	xmlIOFTPClose			(void * context);
-#endif /* LIBXML_FTP_ENABLED */
+#endif /* defined(LIBXML_FTP_ENABLED) */
+
+XMLPUBFUN xmlParserInputBufferCreateFilenameFunc
+xmlParserInputBufferCreateFilenameDefault(
+    xmlParserInputBufferCreateFilenameFunc func);
+XMLPUBFUN xmlOutputBufferCreateFilenameFunc
+xmlOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func);
+XMLPUBFUN xmlOutputBufferCreateFilenameFunc
+xmlThrDefOutputBufferCreateFilenameDefault(
+    xmlOutputBufferCreateFilenameFunc func);
+XMLPUBFUN xmlParserInputBufferCreateFilenameFunc
+xmlThrDefParserInputBufferCreateFilenameDefault(
+    xmlParserInputBufferCreateFilenameFunc func);
 
 #ifdef __cplusplus
 }
diff --git a/third_party/libxml/src/include/libxml/xmlerror.h b/third_party/libxml/src/include/libxml/xmlerror.h
index 830b4a6..79ac16c 100644
--- a/third_party/libxml/src/include/libxml/xmlerror.h
+++ b/third_party/libxml/src/include/libxml/xmlerror.h
@@ -7,11 +7,11 @@
  * Author: Daniel Veillard
  */
 
-#include <libxml/parser.h>
-
 #ifndef __XML_ERROR_H__
 #define __XML_ERROR_H__
 
+#include <libxml/xmlversion.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -97,742 +97,743 @@
  * This is an error that the XML (or HTML) parser can generate
  */
 typedef enum {
-    XML_ERR_OK = 0,
-    XML_ERR_INTERNAL_ERROR, /* 1 */
-    XML_ERR_NO_MEMORY, /* 2 */
-    XML_ERR_DOCUMENT_START, /* 3 */
-    XML_ERR_DOCUMENT_EMPTY, /* 4 */
-    XML_ERR_DOCUMENT_END, /* 5 */
-    XML_ERR_INVALID_HEX_CHARREF, /* 6 */
-    XML_ERR_INVALID_DEC_CHARREF, /* 7 */
-    XML_ERR_INVALID_CHARREF, /* 8 */
-    XML_ERR_INVALID_CHAR, /* 9 */
-    XML_ERR_CHARREF_AT_EOF, /* 10 */
-    XML_ERR_CHARREF_IN_PROLOG, /* 11 */
-    XML_ERR_CHARREF_IN_EPILOG, /* 12 */
-    XML_ERR_CHARREF_IN_DTD, /* 13 */
-    XML_ERR_ENTITYREF_AT_EOF, /* 14 */
-    XML_ERR_ENTITYREF_IN_PROLOG, /* 15 */
-    XML_ERR_ENTITYREF_IN_EPILOG, /* 16 */
-    XML_ERR_ENTITYREF_IN_DTD, /* 17 */
-    XML_ERR_PEREF_AT_EOF, /* 18 */
-    XML_ERR_PEREF_IN_PROLOG, /* 19 */
-    XML_ERR_PEREF_IN_EPILOG, /* 20 */
-    XML_ERR_PEREF_IN_INT_SUBSET, /* 21 */
-    XML_ERR_ENTITYREF_NO_NAME, /* 22 */
-    XML_ERR_ENTITYREF_SEMICOL_MISSING, /* 23 */
-    XML_ERR_PEREF_NO_NAME, /* 24 */
-    XML_ERR_PEREF_SEMICOL_MISSING, /* 25 */
-    XML_ERR_UNDECLARED_ENTITY, /* 26 */
-    XML_WAR_UNDECLARED_ENTITY, /* 27 */
-    XML_ERR_UNPARSED_ENTITY, /* 28 */
-    XML_ERR_ENTITY_IS_EXTERNAL, /* 29 */
-    XML_ERR_ENTITY_IS_PARAMETER, /* 30 */
-    XML_ERR_UNKNOWN_ENCODING, /* 31 */
-    XML_ERR_UNSUPPORTED_ENCODING, /* 32 */
-    XML_ERR_STRING_NOT_STARTED, /* 33 */
-    XML_ERR_STRING_NOT_CLOSED, /* 34 */
-    XML_ERR_NS_DECL_ERROR, /* 35 */
-    XML_ERR_ENTITY_NOT_STARTED, /* 36 */
-    XML_ERR_ENTITY_NOT_FINISHED, /* 37 */
-    XML_ERR_LT_IN_ATTRIBUTE, /* 38 */
-    XML_ERR_ATTRIBUTE_NOT_STARTED, /* 39 */
-    XML_ERR_ATTRIBUTE_NOT_FINISHED, /* 40 */
-    XML_ERR_ATTRIBUTE_WITHOUT_VALUE, /* 41 */
-    XML_ERR_ATTRIBUTE_REDEFINED, /* 42 */
-    XML_ERR_LITERAL_NOT_STARTED, /* 43 */
-    XML_ERR_LITERAL_NOT_FINISHED, /* 44 */
-    XML_ERR_COMMENT_NOT_FINISHED, /* 45 */
-    XML_ERR_PI_NOT_STARTED, /* 46 */
-    XML_ERR_PI_NOT_FINISHED, /* 47 */
-    XML_ERR_NOTATION_NOT_STARTED, /* 48 */
-    XML_ERR_NOTATION_NOT_FINISHED, /* 49 */
-    XML_ERR_ATTLIST_NOT_STARTED, /* 50 */
-    XML_ERR_ATTLIST_NOT_FINISHED, /* 51 */
-    XML_ERR_MIXED_NOT_STARTED, /* 52 */
-    XML_ERR_MIXED_NOT_FINISHED, /* 53 */
-    XML_ERR_ELEMCONTENT_NOT_STARTED, /* 54 */
-    XML_ERR_ELEMCONTENT_NOT_FINISHED, /* 55 */
-    XML_ERR_XMLDECL_NOT_STARTED, /* 56 */
-    XML_ERR_XMLDECL_NOT_FINISHED, /* 57 */
-    XML_ERR_CONDSEC_NOT_STARTED, /* 58 */
-    XML_ERR_CONDSEC_NOT_FINISHED, /* 59 */
-    XML_ERR_EXT_SUBSET_NOT_FINISHED, /* 60 */
-    XML_ERR_DOCTYPE_NOT_FINISHED, /* 61 */
-    XML_ERR_MISPLACED_CDATA_END, /* 62 */
-    XML_ERR_CDATA_NOT_FINISHED, /* 63 */
-    XML_ERR_RESERVED_XML_NAME, /* 64 */
-    XML_ERR_SPACE_REQUIRED, /* 65 */
-    XML_ERR_SEPARATOR_REQUIRED, /* 66 */
-    XML_ERR_NMTOKEN_REQUIRED, /* 67 */
-    XML_ERR_NAME_REQUIRED, /* 68 */
-    XML_ERR_PCDATA_REQUIRED, /* 69 */
-    XML_ERR_URI_REQUIRED, /* 70 */
-    XML_ERR_PUBID_REQUIRED, /* 71 */
-    XML_ERR_LT_REQUIRED, /* 72 */
-    XML_ERR_GT_REQUIRED, /* 73 */
-    XML_ERR_LTSLASH_REQUIRED, /* 74 */
-    XML_ERR_EQUAL_REQUIRED, /* 75 */
-    XML_ERR_TAG_NAME_MISMATCH, /* 76 */
-    XML_ERR_TAG_NOT_FINISHED, /* 77 */
-    XML_ERR_STANDALONE_VALUE, /* 78 */
-    XML_ERR_ENCODING_NAME, /* 79 */
-    XML_ERR_HYPHEN_IN_COMMENT, /* 80 */
-    XML_ERR_INVALID_ENCODING, /* 81 */
-    XML_ERR_EXT_ENTITY_STANDALONE, /* 82 */
-    XML_ERR_CONDSEC_INVALID, /* 83 */
-    XML_ERR_VALUE_REQUIRED, /* 84 */
-    XML_ERR_NOT_WELL_BALANCED, /* 85 */
-    XML_ERR_EXTRA_CONTENT, /* 86 */
-    XML_ERR_ENTITY_CHAR_ERROR, /* 87 */
-    XML_ERR_ENTITY_PE_INTERNAL, /* 88 */
-    XML_ERR_ENTITY_LOOP, /* 89 */
-    XML_ERR_ENTITY_BOUNDARY, /* 90 */
-    XML_ERR_INVALID_URI, /* 91 */
-    XML_ERR_URI_FRAGMENT, /* 92 */
-    XML_WAR_CATALOG_PI, /* 93 */
-    XML_ERR_NO_DTD, /* 94 */
-    XML_ERR_CONDSEC_INVALID_KEYWORD, /* 95 */
-    XML_ERR_VERSION_MISSING, /* 96 */
-    XML_WAR_UNKNOWN_VERSION, /* 97 */
-    XML_WAR_LANG_VALUE, /* 98 */
-    XML_WAR_NS_URI, /* 99 */
-    XML_WAR_NS_URI_RELATIVE, /* 100 */
-    XML_ERR_MISSING_ENCODING, /* 101 */
-    XML_WAR_SPACE_VALUE, /* 102 */
-    XML_ERR_NOT_STANDALONE, /* 103 */
-    XML_ERR_ENTITY_PROCESSING, /* 104 */
-    XML_ERR_NOTATION_PROCESSING, /* 105 */
-    XML_WAR_NS_COLUMN, /* 106 */
-    XML_WAR_ENTITY_REDEFINED, /* 107 */
-    XML_ERR_UNKNOWN_VERSION, /* 108 */
-    XML_ERR_VERSION_MISMATCH, /* 109 */
-    XML_ERR_NAME_TOO_LONG, /* 110 */
-    XML_ERR_USER_STOP, /* 111 */
-    XML_ERR_COMMENT_ABRUPTLY_ENDED, /* 112 */
-    XML_NS_ERR_XML_NAMESPACE = 200,
-    XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */
-    XML_NS_ERR_QNAME, /* 202 */
-    XML_NS_ERR_ATTRIBUTE_REDEFINED, /* 203 */
-    XML_NS_ERR_EMPTY, /* 204 */
-    XML_NS_ERR_COLON, /* 205 */
-    XML_DTD_ATTRIBUTE_DEFAULT = 500,
-    XML_DTD_ATTRIBUTE_REDEFINED, /* 501 */
-    XML_DTD_ATTRIBUTE_VALUE, /* 502 */
-    XML_DTD_CONTENT_ERROR, /* 503 */
-    XML_DTD_CONTENT_MODEL, /* 504 */
-    XML_DTD_CONTENT_NOT_DETERMINIST, /* 505 */
-    XML_DTD_DIFFERENT_PREFIX, /* 506 */
-    XML_DTD_ELEM_DEFAULT_NAMESPACE, /* 507 */
-    XML_DTD_ELEM_NAMESPACE, /* 508 */
-    XML_DTD_ELEM_REDEFINED, /* 509 */
-    XML_DTD_EMPTY_NOTATION, /* 510 */
-    XML_DTD_ENTITY_TYPE, /* 511 */
-    XML_DTD_ID_FIXED, /* 512 */
-    XML_DTD_ID_REDEFINED, /* 513 */
-    XML_DTD_ID_SUBSET, /* 514 */
-    XML_DTD_INVALID_CHILD, /* 515 */
-    XML_DTD_INVALID_DEFAULT, /* 516 */
-    XML_DTD_LOAD_ERROR, /* 517 */
-    XML_DTD_MISSING_ATTRIBUTE, /* 518 */
-    XML_DTD_MIXED_CORRUPT, /* 519 */
-    XML_DTD_MULTIPLE_ID, /* 520 */
-    XML_DTD_NO_DOC, /* 521 */
-    XML_DTD_NO_DTD, /* 522 */
-    XML_DTD_NO_ELEM_NAME, /* 523 */
-    XML_DTD_NO_PREFIX, /* 524 */
-    XML_DTD_NO_ROOT, /* 525 */
-    XML_DTD_NOTATION_REDEFINED, /* 526 */
-    XML_DTD_NOTATION_VALUE, /* 527 */
-    XML_DTD_NOT_EMPTY, /* 528 */
-    XML_DTD_NOT_PCDATA, /* 529 */
-    XML_DTD_NOT_STANDALONE, /* 530 */
-    XML_DTD_ROOT_NAME, /* 531 */
-    XML_DTD_STANDALONE_WHITE_SPACE, /* 532 */
-    XML_DTD_UNKNOWN_ATTRIBUTE, /* 533 */
-    XML_DTD_UNKNOWN_ELEM, /* 534 */
-    XML_DTD_UNKNOWN_ENTITY, /* 535 */
-    XML_DTD_UNKNOWN_ID, /* 536 */
-    XML_DTD_UNKNOWN_NOTATION, /* 537 */
-    XML_DTD_STANDALONE_DEFAULTED, /* 538 */
-    XML_DTD_XMLID_VALUE, /* 539 */
-    XML_DTD_XMLID_TYPE, /* 540 */
-    XML_DTD_DUP_TOKEN, /* 541 */
-    XML_HTML_STRUCURE_ERROR = 800,
-    XML_HTML_UNKNOWN_TAG, /* 801 */
-    XML_HTML_INCORRECTLY_OPENED_COMMENT, /* 802 */
-    XML_RNGP_ANYNAME_ATTR_ANCESTOR = 1000,
-    XML_RNGP_ATTR_CONFLICT, /* 1001 */
-    XML_RNGP_ATTRIBUTE_CHILDREN, /* 1002 */
-    XML_RNGP_ATTRIBUTE_CONTENT, /* 1003 */
-    XML_RNGP_ATTRIBUTE_EMPTY, /* 1004 */
-    XML_RNGP_ATTRIBUTE_NOOP, /* 1005 */
-    XML_RNGP_CHOICE_CONTENT, /* 1006 */
-    XML_RNGP_CHOICE_EMPTY, /* 1007 */
-    XML_RNGP_CREATE_FAILURE, /* 1008 */
-    XML_RNGP_DATA_CONTENT, /* 1009 */
-    XML_RNGP_DEF_CHOICE_AND_INTERLEAVE, /* 1010 */
-    XML_RNGP_DEFINE_CREATE_FAILED, /* 1011 */
-    XML_RNGP_DEFINE_EMPTY, /* 1012 */
-    XML_RNGP_DEFINE_MISSING, /* 1013 */
-    XML_RNGP_DEFINE_NAME_MISSING, /* 1014 */
-    XML_RNGP_ELEM_CONTENT_EMPTY, /* 1015 */
-    XML_RNGP_ELEM_CONTENT_ERROR, /* 1016 */
-    XML_RNGP_ELEMENT_EMPTY, /* 1017 */
-    XML_RNGP_ELEMENT_CONTENT, /* 1018 */
-    XML_RNGP_ELEMENT_NAME, /* 1019 */
-    XML_RNGP_ELEMENT_NO_CONTENT, /* 1020 */
-    XML_RNGP_ELEM_TEXT_CONFLICT, /* 1021 */
-    XML_RNGP_EMPTY, /* 1022 */
-    XML_RNGP_EMPTY_CONSTRUCT, /* 1023 */
-    XML_RNGP_EMPTY_CONTENT, /* 1024 */
-    XML_RNGP_EMPTY_NOT_EMPTY, /* 1025 */
-    XML_RNGP_ERROR_TYPE_LIB, /* 1026 */
-    XML_RNGP_EXCEPT_EMPTY, /* 1027 */
-    XML_RNGP_EXCEPT_MISSING, /* 1028 */
-    XML_RNGP_EXCEPT_MULTIPLE, /* 1029 */
-    XML_RNGP_EXCEPT_NO_CONTENT, /* 1030 */
-    XML_RNGP_EXTERNALREF_EMTPY, /* 1031 */
-    XML_RNGP_EXTERNAL_REF_FAILURE, /* 1032 */
-    XML_RNGP_EXTERNALREF_RECURSE, /* 1033 */
-    XML_RNGP_FORBIDDEN_ATTRIBUTE, /* 1034 */
-    XML_RNGP_FOREIGN_ELEMENT, /* 1035 */
-    XML_RNGP_GRAMMAR_CONTENT, /* 1036 */
-    XML_RNGP_GRAMMAR_EMPTY, /* 1037 */
-    XML_RNGP_GRAMMAR_MISSING, /* 1038 */
-    XML_RNGP_GRAMMAR_NO_START, /* 1039 */
-    XML_RNGP_GROUP_ATTR_CONFLICT, /* 1040 */
-    XML_RNGP_HREF_ERROR, /* 1041 */
-    XML_RNGP_INCLUDE_EMPTY, /* 1042 */
-    XML_RNGP_INCLUDE_FAILURE, /* 1043 */
-    XML_RNGP_INCLUDE_RECURSE, /* 1044 */
-    XML_RNGP_INTERLEAVE_ADD, /* 1045 */
-    XML_RNGP_INTERLEAVE_CREATE_FAILED, /* 1046 */
-    XML_RNGP_INTERLEAVE_EMPTY, /* 1047 */
-    XML_RNGP_INTERLEAVE_NO_CONTENT, /* 1048 */
-    XML_RNGP_INVALID_DEFINE_NAME, /* 1049 */
-    XML_RNGP_INVALID_URI, /* 1050 */
-    XML_RNGP_INVALID_VALUE, /* 1051 */
-    XML_RNGP_MISSING_HREF, /* 1052 */
-    XML_RNGP_NAME_MISSING, /* 1053 */
-    XML_RNGP_NEED_COMBINE, /* 1054 */
-    XML_RNGP_NOTALLOWED_NOT_EMPTY, /* 1055 */
-    XML_RNGP_NSNAME_ATTR_ANCESTOR, /* 1056 */
-    XML_RNGP_NSNAME_NO_NS, /* 1057 */
-    XML_RNGP_PARAM_FORBIDDEN, /* 1058 */
-    XML_RNGP_PARAM_NAME_MISSING, /* 1059 */
-    XML_RNGP_PARENTREF_CREATE_FAILED, /* 1060 */
-    XML_RNGP_PARENTREF_NAME_INVALID, /* 1061 */
-    XML_RNGP_PARENTREF_NO_NAME, /* 1062 */
-    XML_RNGP_PARENTREF_NO_PARENT, /* 1063 */
-    XML_RNGP_PARENTREF_NOT_EMPTY, /* 1064 */
-    XML_RNGP_PARSE_ERROR, /* 1065 */
-    XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME, /* 1066 */
-    XML_RNGP_PAT_ATTR_ATTR, /* 1067 */
-    XML_RNGP_PAT_ATTR_ELEM, /* 1068 */
-    XML_RNGP_PAT_DATA_EXCEPT_ATTR, /* 1069 */
-    XML_RNGP_PAT_DATA_EXCEPT_ELEM, /* 1070 */
-    XML_RNGP_PAT_DATA_EXCEPT_EMPTY, /* 1071 */
-    XML_RNGP_PAT_DATA_EXCEPT_GROUP, /* 1072 */
-    XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE, /* 1073 */
-    XML_RNGP_PAT_DATA_EXCEPT_LIST, /* 1074 */
-    XML_RNGP_PAT_DATA_EXCEPT_ONEMORE, /* 1075 */
-    XML_RNGP_PAT_DATA_EXCEPT_REF, /* 1076 */
-    XML_RNGP_PAT_DATA_EXCEPT_TEXT, /* 1077 */
-    XML_RNGP_PAT_LIST_ATTR, /* 1078 */
-    XML_RNGP_PAT_LIST_ELEM, /* 1079 */
-    XML_RNGP_PAT_LIST_INTERLEAVE, /* 1080 */
-    XML_RNGP_PAT_LIST_LIST, /* 1081 */
-    XML_RNGP_PAT_LIST_REF, /* 1082 */
-    XML_RNGP_PAT_LIST_TEXT, /* 1083 */
-    XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME, /* 1084 */
-    XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME, /* 1085 */
-    XML_RNGP_PAT_ONEMORE_GROUP_ATTR, /* 1086 */
-    XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR, /* 1087 */
-    XML_RNGP_PAT_START_ATTR, /* 1088 */
-    XML_RNGP_PAT_START_DATA, /* 1089 */
-    XML_RNGP_PAT_START_EMPTY, /* 1090 */
-    XML_RNGP_PAT_START_GROUP, /* 1091 */
-    XML_RNGP_PAT_START_INTERLEAVE, /* 1092 */
-    XML_RNGP_PAT_START_LIST, /* 1093 */
-    XML_RNGP_PAT_START_ONEMORE, /* 1094 */
-    XML_RNGP_PAT_START_TEXT, /* 1095 */
-    XML_RNGP_PAT_START_VALUE, /* 1096 */
-    XML_RNGP_PREFIX_UNDEFINED, /* 1097 */
-    XML_RNGP_REF_CREATE_FAILED, /* 1098 */
-    XML_RNGP_REF_CYCLE, /* 1099 */
-    XML_RNGP_REF_NAME_INVALID, /* 1100 */
-    XML_RNGP_REF_NO_DEF, /* 1101 */
-    XML_RNGP_REF_NO_NAME, /* 1102 */
-    XML_RNGP_REF_NOT_EMPTY, /* 1103 */
-    XML_RNGP_START_CHOICE_AND_INTERLEAVE, /* 1104 */
-    XML_RNGP_START_CONTENT, /* 1105 */
-    XML_RNGP_START_EMPTY, /* 1106 */
-    XML_RNGP_START_MISSING, /* 1107 */
-    XML_RNGP_TEXT_EXPECTED, /* 1108 */
-    XML_RNGP_TEXT_HAS_CHILD, /* 1109 */
-    XML_RNGP_TYPE_MISSING, /* 1110 */
-    XML_RNGP_TYPE_NOT_FOUND, /* 1111 */
-    XML_RNGP_TYPE_VALUE, /* 1112 */
-    XML_RNGP_UNKNOWN_ATTRIBUTE, /* 1113 */
-    XML_RNGP_UNKNOWN_COMBINE, /* 1114 */
-    XML_RNGP_UNKNOWN_CONSTRUCT, /* 1115 */
-    XML_RNGP_UNKNOWN_TYPE_LIB, /* 1116 */
-    XML_RNGP_URI_FRAGMENT, /* 1117 */
-    XML_RNGP_URI_NOT_ABSOLUTE, /* 1118 */
-    XML_RNGP_VALUE_EMPTY, /* 1119 */
-    XML_RNGP_VALUE_NO_CONTENT, /* 1120 */
-    XML_RNGP_XMLNS_NAME, /* 1121 */
-    XML_RNGP_XML_NS, /* 1122 */
-    XML_XPATH_EXPRESSION_OK = 1200,
-    XML_XPATH_NUMBER_ERROR, /* 1201 */
-    XML_XPATH_UNFINISHED_LITERAL_ERROR, /* 1202 */
-    XML_XPATH_START_LITERAL_ERROR, /* 1203 */
-    XML_XPATH_VARIABLE_REF_ERROR, /* 1204 */
-    XML_XPATH_UNDEF_VARIABLE_ERROR, /* 1205 */
-    XML_XPATH_INVALID_PREDICATE_ERROR, /* 1206 */
-    XML_XPATH_EXPR_ERROR, /* 1207 */
-    XML_XPATH_UNCLOSED_ERROR, /* 1208 */
-    XML_XPATH_UNKNOWN_FUNC_ERROR, /* 1209 */
-    XML_XPATH_INVALID_OPERAND, /* 1210 */
-    XML_XPATH_INVALID_TYPE, /* 1211 */
-    XML_XPATH_INVALID_ARITY, /* 1212 */
-    XML_XPATH_INVALID_CTXT_SIZE, /* 1213 */
-    XML_XPATH_INVALID_CTXT_POSITION, /* 1214 */
-    XML_XPATH_MEMORY_ERROR, /* 1215 */
-    XML_XPTR_SYNTAX_ERROR, /* 1216 */
-    XML_XPTR_RESOURCE_ERROR, /* 1217 */
-    XML_XPTR_SUB_RESOURCE_ERROR, /* 1218 */
-    XML_XPATH_UNDEF_PREFIX_ERROR, /* 1219 */
-    XML_XPATH_ENCODING_ERROR, /* 1220 */
-    XML_XPATH_INVALID_CHAR_ERROR, /* 1221 */
-    XML_TREE_INVALID_HEX = 1300,
-    XML_TREE_INVALID_DEC, /* 1301 */
-    XML_TREE_UNTERMINATED_ENTITY, /* 1302 */
-    XML_TREE_NOT_UTF8, /* 1303 */
-    XML_SAVE_NOT_UTF8 = 1400,
-    XML_SAVE_CHAR_INVALID, /* 1401 */
-    XML_SAVE_NO_DOCTYPE, /* 1402 */
-    XML_SAVE_UNKNOWN_ENCODING, /* 1403 */
-    XML_REGEXP_COMPILE_ERROR = 1450,
-    XML_IO_UNKNOWN = 1500,
-    XML_IO_EACCES, /* 1501 */
-    XML_IO_EAGAIN, /* 1502 */
-    XML_IO_EBADF, /* 1503 */
-    XML_IO_EBADMSG, /* 1504 */
-    XML_IO_EBUSY, /* 1505 */
-    XML_IO_ECANCELED, /* 1506 */
-    XML_IO_ECHILD, /* 1507 */
-    XML_IO_EDEADLK, /* 1508 */
-    XML_IO_EDOM, /* 1509 */
-    XML_IO_EEXIST, /* 1510 */
-    XML_IO_EFAULT, /* 1511 */
-    XML_IO_EFBIG, /* 1512 */
-    XML_IO_EINPROGRESS, /* 1513 */
-    XML_IO_EINTR, /* 1514 */
-    XML_IO_EINVAL, /* 1515 */
-    XML_IO_EIO, /* 1516 */
-    XML_IO_EISDIR, /* 1517 */
-    XML_IO_EMFILE, /* 1518 */
-    XML_IO_EMLINK, /* 1519 */
-    XML_IO_EMSGSIZE, /* 1520 */
-    XML_IO_ENAMETOOLONG, /* 1521 */
-    XML_IO_ENFILE, /* 1522 */
-    XML_IO_ENODEV, /* 1523 */
-    XML_IO_ENOENT, /* 1524 */
-    XML_IO_ENOEXEC, /* 1525 */
-    XML_IO_ENOLCK, /* 1526 */
-    XML_IO_ENOMEM, /* 1527 */
-    XML_IO_ENOSPC, /* 1528 */
-    XML_IO_ENOSYS, /* 1529 */
-    XML_IO_ENOTDIR, /* 1530 */
-    XML_IO_ENOTEMPTY, /* 1531 */
-    XML_IO_ENOTSUP, /* 1532 */
-    XML_IO_ENOTTY, /* 1533 */
-    XML_IO_ENXIO, /* 1534 */
-    XML_IO_EPERM, /* 1535 */
-    XML_IO_EPIPE, /* 1536 */
-    XML_IO_ERANGE, /* 1537 */
-    XML_IO_EROFS, /* 1538 */
-    XML_IO_ESPIPE, /* 1539 */
-    XML_IO_ESRCH, /* 1540 */
-    XML_IO_ETIMEDOUT, /* 1541 */
-    XML_IO_EXDEV, /* 1542 */
-    XML_IO_NETWORK_ATTEMPT, /* 1543 */
-    XML_IO_ENCODER, /* 1544 */
-    XML_IO_FLUSH, /* 1545 */
-    XML_IO_WRITE, /* 1546 */
-    XML_IO_NO_INPUT, /* 1547 */
-    XML_IO_BUFFER_FULL, /* 1548 */
-    XML_IO_LOAD_ERROR, /* 1549 */
-    XML_IO_ENOTSOCK, /* 1550 */
-    XML_IO_EISCONN, /* 1551 */
-    XML_IO_ECONNREFUSED, /* 1552 */
-    XML_IO_ENETUNREACH, /* 1553 */
-    XML_IO_EADDRINUSE, /* 1554 */
-    XML_IO_EALREADY, /* 1555 */
-    XML_IO_EAFNOSUPPORT, /* 1556 */
-    XML_XINCLUDE_RECURSION=1600,
-    XML_XINCLUDE_PARSE_VALUE, /* 1601 */
-    XML_XINCLUDE_ENTITY_DEF_MISMATCH, /* 1602 */
-    XML_XINCLUDE_NO_HREF, /* 1603 */
-    XML_XINCLUDE_NO_FALLBACK, /* 1604 */
-    XML_XINCLUDE_HREF_URI, /* 1605 */
-    XML_XINCLUDE_TEXT_FRAGMENT, /* 1606 */
-    XML_XINCLUDE_TEXT_DOCUMENT, /* 1607 */
-    XML_XINCLUDE_INVALID_CHAR, /* 1608 */
-    XML_XINCLUDE_BUILD_FAILED, /* 1609 */
-    XML_XINCLUDE_UNKNOWN_ENCODING, /* 1610 */
-    XML_XINCLUDE_MULTIPLE_ROOT, /* 1611 */
-    XML_XINCLUDE_XPTR_FAILED, /* 1612 */
-    XML_XINCLUDE_XPTR_RESULT, /* 1613 */
-    XML_XINCLUDE_INCLUDE_IN_INCLUDE, /* 1614 */
-    XML_XINCLUDE_FALLBACKS_IN_INCLUDE, /* 1615 */
-    XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE, /* 1616 */
-    XML_XINCLUDE_DEPRECATED_NS, /* 1617 */
-    XML_XINCLUDE_FRAGMENT_ID, /* 1618 */
-    XML_CATALOG_MISSING_ATTR = 1650,
-    XML_CATALOG_ENTRY_BROKEN, /* 1651 */
-    XML_CATALOG_PREFER_VALUE, /* 1652 */
-    XML_CATALOG_NOT_CATALOG, /* 1653 */
-    XML_CATALOG_RECURSION, /* 1654 */
-    XML_SCHEMAP_PREFIX_UNDEFINED = 1700,
-    XML_SCHEMAP_ATTRFORMDEFAULT_VALUE, /* 1701 */
-    XML_SCHEMAP_ATTRGRP_NONAME_NOREF, /* 1702 */
-    XML_SCHEMAP_ATTR_NONAME_NOREF, /* 1703 */
-    XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF, /* 1704 */
-    XML_SCHEMAP_ELEMFORMDEFAULT_VALUE, /* 1705 */
-    XML_SCHEMAP_ELEM_NONAME_NOREF, /* 1706 */
-    XML_SCHEMAP_EXTENSION_NO_BASE, /* 1707 */
-    XML_SCHEMAP_FACET_NO_VALUE, /* 1708 */
-    XML_SCHEMAP_FAILED_BUILD_IMPORT, /* 1709 */
-    XML_SCHEMAP_GROUP_NONAME_NOREF, /* 1710 */
-    XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI, /* 1711 */
-    XML_SCHEMAP_IMPORT_REDEFINE_NSNAME, /* 1712 */
-    XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI, /* 1713 */
-    XML_SCHEMAP_INVALID_BOOLEAN, /* 1714 */
-    XML_SCHEMAP_INVALID_ENUM, /* 1715 */
-    XML_SCHEMAP_INVALID_FACET, /* 1716 */
-    XML_SCHEMAP_INVALID_FACET_VALUE, /* 1717 */
-    XML_SCHEMAP_INVALID_MAXOCCURS, /* 1718 */
-    XML_SCHEMAP_INVALID_MINOCCURS, /* 1719 */
-    XML_SCHEMAP_INVALID_REF_AND_SUBTYPE, /* 1720 */
-    XML_SCHEMAP_INVALID_WHITE_SPACE, /* 1721 */
-    XML_SCHEMAP_NOATTR_NOREF, /* 1722 */
-    XML_SCHEMAP_NOTATION_NO_NAME, /* 1723 */
-    XML_SCHEMAP_NOTYPE_NOREF, /* 1724 */
-    XML_SCHEMAP_REF_AND_SUBTYPE, /* 1725 */
-    XML_SCHEMAP_RESTRICTION_NONAME_NOREF, /* 1726 */
-    XML_SCHEMAP_SIMPLETYPE_NONAME, /* 1727 */
-    XML_SCHEMAP_TYPE_AND_SUBTYPE, /* 1728 */
-    XML_SCHEMAP_UNKNOWN_ALL_CHILD, /* 1729 */
-    XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD, /* 1730 */
-    XML_SCHEMAP_UNKNOWN_ATTR_CHILD, /* 1731 */
-    XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD, /* 1732 */
-    XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP, /* 1733 */
-    XML_SCHEMAP_UNKNOWN_BASE_TYPE, /* 1734 */
-    XML_SCHEMAP_UNKNOWN_CHOICE_CHILD, /* 1735 */
-    XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD, /* 1736 */
-    XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD, /* 1737 */
-    XML_SCHEMAP_UNKNOWN_ELEM_CHILD, /* 1738 */
-    XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD, /* 1739 */
-    XML_SCHEMAP_UNKNOWN_FACET_CHILD, /* 1740 */
-    XML_SCHEMAP_UNKNOWN_FACET_TYPE, /* 1741 */
-    XML_SCHEMAP_UNKNOWN_GROUP_CHILD, /* 1742 */
-    XML_SCHEMAP_UNKNOWN_IMPORT_CHILD, /* 1743 */
-    XML_SCHEMAP_UNKNOWN_LIST_CHILD, /* 1744 */
-    XML_SCHEMAP_UNKNOWN_NOTATION_CHILD, /* 1745 */
-    XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD, /* 1746 */
-    XML_SCHEMAP_UNKNOWN_REF, /* 1747 */
-    XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD, /* 1748 */
-    XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD, /* 1749 */
-    XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD, /* 1750 */
-    XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD, /* 1751 */
-    XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD, /* 1752 */
-    XML_SCHEMAP_UNKNOWN_TYPE, /* 1753 */
-    XML_SCHEMAP_UNKNOWN_UNION_CHILD, /* 1754 */
-    XML_SCHEMAP_ELEM_DEFAULT_FIXED, /* 1755 */
-    XML_SCHEMAP_REGEXP_INVALID, /* 1756 */
-    XML_SCHEMAP_FAILED_LOAD, /* 1757 */
-    XML_SCHEMAP_NOTHING_TO_PARSE, /* 1758 */
-    XML_SCHEMAP_NOROOT, /* 1759 */
-    XML_SCHEMAP_REDEFINED_GROUP, /* 1760 */
-    XML_SCHEMAP_REDEFINED_TYPE, /* 1761 */
-    XML_SCHEMAP_REDEFINED_ELEMENT, /* 1762 */
-    XML_SCHEMAP_REDEFINED_ATTRGROUP, /* 1763 */
-    XML_SCHEMAP_REDEFINED_ATTR, /* 1764 */
-    XML_SCHEMAP_REDEFINED_NOTATION, /* 1765 */
-    XML_SCHEMAP_FAILED_PARSE, /* 1766 */
-    XML_SCHEMAP_UNKNOWN_PREFIX, /* 1767 */
-    XML_SCHEMAP_DEF_AND_PREFIX, /* 1768 */
-    XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD, /* 1769 */
-    XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI, /* 1770 */
-    XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI, /* 1771 */
-    XML_SCHEMAP_NOT_SCHEMA, /* 1772 */
-    XML_SCHEMAP_UNKNOWN_MEMBER_TYPE, /* 1773 */
-    XML_SCHEMAP_INVALID_ATTR_USE, /* 1774 */
-    XML_SCHEMAP_RECURSIVE, /* 1775 */
-    XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE, /* 1776 */
-    XML_SCHEMAP_INVALID_ATTR_COMBINATION, /* 1777 */
-    XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION, /* 1778 */
-    XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD, /* 1779 */
-    XML_SCHEMAP_INVALID_ATTR_NAME, /* 1780 */
-    XML_SCHEMAP_REF_AND_CONTENT, /* 1781 */
-    XML_SCHEMAP_CT_PROPS_CORRECT_1, /* 1782 */
-    XML_SCHEMAP_CT_PROPS_CORRECT_2, /* 1783 */
-    XML_SCHEMAP_CT_PROPS_CORRECT_3, /* 1784 */
-    XML_SCHEMAP_CT_PROPS_CORRECT_4, /* 1785 */
-    XML_SCHEMAP_CT_PROPS_CORRECT_5, /* 1786 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, /* 1787 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, /* 1788 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, /* 1789 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2, /* 1790 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3, /* 1791 */
-    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER, /* 1792 */
-    XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE, /* 1793 */
-    XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, /* 1794 */
-    XML_SCHEMAP_SRC_IMPORT_3_1, /* 1795 */
-    XML_SCHEMAP_SRC_IMPORT_3_2, /* 1796 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, /* 1797 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, /* 1798 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, /* 1799 */
-    XML_SCHEMAP_COS_CT_EXTENDS_1_3, /* 1800 */
-    XML_SCHEMAV_NOROOT = 1801,
-    XML_SCHEMAV_UNDECLAREDELEM, /* 1802 */
-    XML_SCHEMAV_NOTTOPLEVEL, /* 1803 */
-    XML_SCHEMAV_MISSING, /* 1804 */
-    XML_SCHEMAV_WRONGELEM, /* 1805 */
-    XML_SCHEMAV_NOTYPE, /* 1806 */
-    XML_SCHEMAV_NOROLLBACK, /* 1807 */
-    XML_SCHEMAV_ISABSTRACT, /* 1808 */
-    XML_SCHEMAV_NOTEMPTY, /* 1809 */
-    XML_SCHEMAV_ELEMCONT, /* 1810 */
-    XML_SCHEMAV_HAVEDEFAULT, /* 1811 */
-    XML_SCHEMAV_NOTNILLABLE, /* 1812 */
-    XML_SCHEMAV_EXTRACONTENT, /* 1813 */
-    XML_SCHEMAV_INVALIDATTR, /* 1814 */
-    XML_SCHEMAV_INVALIDELEM, /* 1815 */
-    XML_SCHEMAV_NOTDETERMINIST, /* 1816 */
-    XML_SCHEMAV_CONSTRUCT, /* 1817 */
-    XML_SCHEMAV_INTERNAL, /* 1818 */
-    XML_SCHEMAV_NOTSIMPLE, /* 1819 */
-    XML_SCHEMAV_ATTRUNKNOWN, /* 1820 */
-    XML_SCHEMAV_ATTRINVALID, /* 1821 */
-    XML_SCHEMAV_VALUE, /* 1822 */
-    XML_SCHEMAV_FACET, /* 1823 */
-    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, /* 1824 */
-    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2, /* 1825 */
-    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3, /* 1826 */
-    XML_SCHEMAV_CVC_TYPE_3_1_1, /* 1827 */
-    XML_SCHEMAV_CVC_TYPE_3_1_2, /* 1828 */
-    XML_SCHEMAV_CVC_FACET_VALID, /* 1829 */
-    XML_SCHEMAV_CVC_LENGTH_VALID, /* 1830 */
-    XML_SCHEMAV_CVC_MINLENGTH_VALID, /* 1831 */
-    XML_SCHEMAV_CVC_MAXLENGTH_VALID, /* 1832 */
-    XML_SCHEMAV_CVC_MININCLUSIVE_VALID, /* 1833 */
-    XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID, /* 1834 */
-    XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID, /* 1835 */
-    XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID, /* 1836 */
-    XML_SCHEMAV_CVC_TOTALDIGITS_VALID, /* 1837 */
-    XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID, /* 1838 */
-    XML_SCHEMAV_CVC_PATTERN_VALID, /* 1839 */
-    XML_SCHEMAV_CVC_ENUMERATION_VALID, /* 1840 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, /* 1841 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2, /* 1842 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, /* 1843 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_2_4, /* 1844 */
-    XML_SCHEMAV_CVC_ELT_1, /* 1845 */
-    XML_SCHEMAV_CVC_ELT_2, /* 1846 */
-    XML_SCHEMAV_CVC_ELT_3_1, /* 1847 */
-    XML_SCHEMAV_CVC_ELT_3_2_1, /* 1848 */
-    XML_SCHEMAV_CVC_ELT_3_2_2, /* 1849 */
-    XML_SCHEMAV_CVC_ELT_4_1, /* 1850 */
-    XML_SCHEMAV_CVC_ELT_4_2, /* 1851 */
-    XML_SCHEMAV_CVC_ELT_4_3, /* 1852 */
-    XML_SCHEMAV_CVC_ELT_5_1_1, /* 1853 */
-    XML_SCHEMAV_CVC_ELT_5_1_2, /* 1854 */
-    XML_SCHEMAV_CVC_ELT_5_2_1, /* 1855 */
-    XML_SCHEMAV_CVC_ELT_5_2_2_1, /* 1856 */
-    XML_SCHEMAV_CVC_ELT_5_2_2_2_1, /* 1857 */
-    XML_SCHEMAV_CVC_ELT_5_2_2_2_2, /* 1858 */
-    XML_SCHEMAV_CVC_ELT_6, /* 1859 */
-    XML_SCHEMAV_CVC_ELT_7, /* 1860 */
-    XML_SCHEMAV_CVC_ATTRIBUTE_1, /* 1861 */
-    XML_SCHEMAV_CVC_ATTRIBUTE_2, /* 1862 */
-    XML_SCHEMAV_CVC_ATTRIBUTE_3, /* 1863 */
-    XML_SCHEMAV_CVC_ATTRIBUTE_4, /* 1864 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_3_1, /* 1865 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, /* 1866 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, /* 1867 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_4, /* 1868 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_5_1, /* 1869 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_5_2, /* 1870 */
-    XML_SCHEMAV_ELEMENT_CONTENT, /* 1871 */
-    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, /* 1872 */
-    XML_SCHEMAV_CVC_COMPLEX_TYPE_1, /* 1873 */
-    XML_SCHEMAV_CVC_AU, /* 1874 */
-    XML_SCHEMAV_CVC_TYPE_1, /* 1875 */
-    XML_SCHEMAV_CVC_TYPE_2, /* 1876 */
-    XML_SCHEMAV_CVC_IDC, /* 1877 */
-    XML_SCHEMAV_CVC_WILDCARD, /* 1878 */
-    XML_SCHEMAV_MISC, /* 1879 */
-    XML_XPTR_UNKNOWN_SCHEME = 1900,
-    XML_XPTR_CHILDSEQ_START, /* 1901 */
-    XML_XPTR_EVAL_FAILED, /* 1902 */
-    XML_XPTR_EXTRA_OBJECTS, /* 1903 */
-    XML_C14N_CREATE_CTXT = 1950,
-    XML_C14N_REQUIRES_UTF8, /* 1951 */
-    XML_C14N_CREATE_STACK, /* 1952 */
-    XML_C14N_INVALID_NODE, /* 1953 */
-    XML_C14N_UNKNOW_NODE, /* 1954 */
-    XML_C14N_RELATIVE_NAMESPACE, /* 1955 */
-    XML_FTP_PASV_ANSWER = 2000,
-    XML_FTP_EPSV_ANSWER, /* 2001 */
-    XML_FTP_ACCNT, /* 2002 */
-    XML_FTP_URL_SYNTAX, /* 2003 */
-    XML_HTTP_URL_SYNTAX = 2020,
-    XML_HTTP_USE_IP, /* 2021 */
-    XML_HTTP_UNKNOWN_HOST, /* 2022 */
-    XML_SCHEMAP_SRC_SIMPLE_TYPE_1 = 3000,
-    XML_SCHEMAP_SRC_SIMPLE_TYPE_2, /* 3001 */
-    XML_SCHEMAP_SRC_SIMPLE_TYPE_3, /* 3002 */
-    XML_SCHEMAP_SRC_SIMPLE_TYPE_4, /* 3003 */
-    XML_SCHEMAP_SRC_RESOLVE, /* 3004 */
-    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, /* 3005 */
-    XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE, /* 3006 */
-    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, /* 3007 */
-    XML_SCHEMAP_ST_PROPS_CORRECT_1, /* 3008 */
-    XML_SCHEMAP_ST_PROPS_CORRECT_2, /* 3009 */
-    XML_SCHEMAP_ST_PROPS_CORRECT_3, /* 3010 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_1_1, /* 3011 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_1_2, /* 3012 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1, /* 3013 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_1_3_2, /* 3014 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_2_1, /* 3015 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1, /* 3016 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2, /* 3017 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1, /* 3018 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2, /* 3019 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, /* 3020 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4, /* 3021 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_5, /* 3022 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_3_1, /* 3023 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1, /* 3024 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2, /* 3025 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2, /* 3026 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1, /* 3027 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, /* 3028 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4, /* 3029 */
-    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_5, /* 3030 */
-    XML_SCHEMAP_COS_ST_DERIVED_OK_2_1, /* 3031 */
-    XML_SCHEMAP_COS_ST_DERIVED_OK_2_2, /* 3032 */
-    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, /* 3033 */
-    XML_SCHEMAP_S4S_ELEM_MISSING, /* 3034 */
-    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, /* 3035 */
-    XML_SCHEMAP_S4S_ATTR_MISSING, /* 3036 */
-    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, /* 3037 */
-    XML_SCHEMAP_SRC_ELEMENT_1, /* 3038 */
-    XML_SCHEMAP_SRC_ELEMENT_2_1, /* 3039 */
-    XML_SCHEMAP_SRC_ELEMENT_2_2, /* 3040 */
-    XML_SCHEMAP_SRC_ELEMENT_3, /* 3041 */
-    XML_SCHEMAP_P_PROPS_CORRECT_1, /* 3042 */
-    XML_SCHEMAP_P_PROPS_CORRECT_2_1, /* 3043 */
-    XML_SCHEMAP_P_PROPS_CORRECT_2_2, /* 3044 */
-    XML_SCHEMAP_E_PROPS_CORRECT_2, /* 3045 */
-    XML_SCHEMAP_E_PROPS_CORRECT_3, /* 3046 */
-    XML_SCHEMAP_E_PROPS_CORRECT_4, /* 3047 */
-    XML_SCHEMAP_E_PROPS_CORRECT_5, /* 3048 */
-    XML_SCHEMAP_E_PROPS_CORRECT_6, /* 3049 */
-    XML_SCHEMAP_SRC_INCLUDE, /* 3050 */
-    XML_SCHEMAP_SRC_ATTRIBUTE_1, /* 3051 */
-    XML_SCHEMAP_SRC_ATTRIBUTE_2, /* 3052 */
-    XML_SCHEMAP_SRC_ATTRIBUTE_3_1, /* 3053 */
-    XML_SCHEMAP_SRC_ATTRIBUTE_3_2, /* 3054 */
-    XML_SCHEMAP_SRC_ATTRIBUTE_4, /* 3055 */
-    XML_SCHEMAP_NO_XMLNS, /* 3056 */
-    XML_SCHEMAP_NO_XSI, /* 3057 */
-    XML_SCHEMAP_COS_VALID_DEFAULT_1, /* 3058 */
-    XML_SCHEMAP_COS_VALID_DEFAULT_2_1, /* 3059 */
-    XML_SCHEMAP_COS_VALID_DEFAULT_2_2_1, /* 3060 */
-    XML_SCHEMAP_COS_VALID_DEFAULT_2_2_2, /* 3061 */
-    XML_SCHEMAP_CVC_SIMPLE_TYPE, /* 3062 */
-    XML_SCHEMAP_COS_CT_EXTENDS_1_1, /* 3063 */
-    XML_SCHEMAP_SRC_IMPORT_1_1, /* 3064 */
-    XML_SCHEMAP_SRC_IMPORT_1_2, /* 3065 */
-    XML_SCHEMAP_SRC_IMPORT_2, /* 3066 */
-    XML_SCHEMAP_SRC_IMPORT_2_1, /* 3067 */
-    XML_SCHEMAP_SRC_IMPORT_2_2, /* 3068 */
-    XML_SCHEMAP_INTERNAL, /* 3069 non-W3C */
-    XML_SCHEMAP_NOT_DETERMINISTIC, /* 3070 non-W3C */
-    XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_1, /* 3071 */
-    XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_2, /* 3072 */
-    XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3, /* 3073 */
-    XML_SCHEMAP_MG_PROPS_CORRECT_1, /* 3074 */
-    XML_SCHEMAP_MG_PROPS_CORRECT_2, /* 3075 */
-    XML_SCHEMAP_SRC_CT_1, /* 3076 */
-    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, /* 3077 */
-    XML_SCHEMAP_AU_PROPS_CORRECT_2, /* 3078 */
-    XML_SCHEMAP_A_PROPS_CORRECT_2, /* 3079 */
-    XML_SCHEMAP_C_PROPS_CORRECT, /* 3080 */
-    XML_SCHEMAP_SRC_REDEFINE, /* 3081 */
-    XML_SCHEMAP_SRC_IMPORT, /* 3082 */
-    XML_SCHEMAP_WARN_SKIP_SCHEMA, /* 3083 */
-    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA, /* 3084 */
-    XML_SCHEMAP_WARN_ATTR_REDECL_PROH, /* 3085 */
-    XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, /* 3085 */
-    XML_SCHEMAP_AG_PROPS_CORRECT, /* 3086 */
-    XML_SCHEMAP_COS_CT_EXTENDS_1_2, /* 3087 */
-    XML_SCHEMAP_AU_PROPS_CORRECT, /* 3088 */
-    XML_SCHEMAP_A_PROPS_CORRECT_3, /* 3089 */
-    XML_SCHEMAP_COS_ALL_LIMITED, /* 3090 */
-    XML_SCHEMATRONV_ASSERT = 4000, /* 4000 */
-    XML_SCHEMATRONV_REPORT,
-    XML_MODULE_OPEN = 4900, /* 4900 */
-    XML_MODULE_CLOSE, /* 4901 */
-    XML_CHECK_FOUND_ELEMENT = 5000,
-    XML_CHECK_FOUND_ATTRIBUTE, /* 5001 */
-    XML_CHECK_FOUND_TEXT, /* 5002 */
-    XML_CHECK_FOUND_CDATA, /* 5003 */
-    XML_CHECK_FOUND_ENTITYREF, /* 5004 */
-    XML_CHECK_FOUND_ENTITY, /* 5005 */
-    XML_CHECK_FOUND_PI, /* 5006 */
-    XML_CHECK_FOUND_COMMENT, /* 5007 */
-    XML_CHECK_FOUND_DOCTYPE, /* 5008 */
-    XML_CHECK_FOUND_FRAGMENT, /* 5009 */
-    XML_CHECK_FOUND_NOTATION, /* 5010 */
-    XML_CHECK_UNKNOWN_NODE, /* 5011 */
-    XML_CHECK_ENTITY_TYPE, /* 5012 */
-    XML_CHECK_NO_PARENT, /* 5013 */
-    XML_CHECK_NO_DOC, /* 5014 */
-    XML_CHECK_NO_NAME, /* 5015 */
-    XML_CHECK_NO_ELEM, /* 5016 */
-    XML_CHECK_WRONG_DOC, /* 5017 */
-    XML_CHECK_NO_PREV, /* 5018 */
-    XML_CHECK_WRONG_PREV, /* 5019 */
-    XML_CHECK_NO_NEXT, /* 5020 */
-    XML_CHECK_WRONG_NEXT, /* 5021 */
-    XML_CHECK_NOT_DTD, /* 5022 */
-    XML_CHECK_NOT_ATTR, /* 5023 */
-    XML_CHECK_NOT_ATTR_DECL, /* 5024 */
-    XML_CHECK_NOT_ELEM_DECL, /* 5025 */
-    XML_CHECK_NOT_ENTITY_DECL, /* 5026 */
-    XML_CHECK_NOT_NS_DECL, /* 5027 */
-    XML_CHECK_NO_HREF, /* 5028 */
-    XML_CHECK_WRONG_PARENT,/* 5029 */
-    XML_CHECK_NS_SCOPE, /* 5030 */
-    XML_CHECK_NS_ANCESTOR, /* 5031 */
-    XML_CHECK_NOT_UTF8, /* 5032 */
-    XML_CHECK_NO_DICT, /* 5033 */
-    XML_CHECK_NOT_NCNAME, /* 5034 */
-    XML_CHECK_OUTSIDE_DICT, /* 5035 */
-    XML_CHECK_WRONG_NAME, /* 5036 */
-    XML_CHECK_NAME_NOT_NULL, /* 5037 */
-    XML_I18N_NO_NAME = 6000,
-    XML_I18N_NO_HANDLER, /* 6001 */
-    XML_I18N_EXCESS_HANDLER, /* 6002 */
-    XML_I18N_CONV_FAILED, /* 6003 */
-    XML_I18N_NO_OUTPUT, /* 6004 */
-    XML_BUF_OVERFLOW = 7000
+  XML_ERR_OK = 0,
+  XML_ERR_INTERNAL_ERROR,            /* 1 */
+  XML_ERR_NO_MEMORY,                 /* 2 */
+  XML_ERR_DOCUMENT_START,            /* 3 */
+  XML_ERR_DOCUMENT_EMPTY,            /* 4 */
+  XML_ERR_DOCUMENT_END,              /* 5 */
+  XML_ERR_INVALID_HEX_CHARREF,       /* 6 */
+  XML_ERR_INVALID_DEC_CHARREF,       /* 7 */
+  XML_ERR_INVALID_CHARREF,           /* 8 */
+  XML_ERR_INVALID_CHAR,              /* 9 */
+  XML_ERR_CHARREF_AT_EOF,            /* 10 */
+  XML_ERR_CHARREF_IN_PROLOG,         /* 11 */
+  XML_ERR_CHARREF_IN_EPILOG,         /* 12 */
+  XML_ERR_CHARREF_IN_DTD,            /* 13 */
+  XML_ERR_ENTITYREF_AT_EOF,          /* 14 */
+  XML_ERR_ENTITYREF_IN_PROLOG,       /* 15 */
+  XML_ERR_ENTITYREF_IN_EPILOG,       /* 16 */
+  XML_ERR_ENTITYREF_IN_DTD,          /* 17 */
+  XML_ERR_PEREF_AT_EOF,              /* 18 */
+  XML_ERR_PEREF_IN_PROLOG,           /* 19 */
+  XML_ERR_PEREF_IN_EPILOG,           /* 20 */
+  XML_ERR_PEREF_IN_INT_SUBSET,       /* 21 */
+  XML_ERR_ENTITYREF_NO_NAME,         /* 22 */
+  XML_ERR_ENTITYREF_SEMICOL_MISSING, /* 23 */
+  XML_ERR_PEREF_NO_NAME,             /* 24 */
+  XML_ERR_PEREF_SEMICOL_MISSING,     /* 25 */
+  XML_ERR_UNDECLARED_ENTITY,         /* 26 */
+  XML_WAR_UNDECLARED_ENTITY,         /* 27 */
+  XML_ERR_UNPARSED_ENTITY,           /* 28 */
+  XML_ERR_ENTITY_IS_EXTERNAL,        /* 29 */
+  XML_ERR_ENTITY_IS_PARAMETER,       /* 30 */
+  XML_ERR_UNKNOWN_ENCODING,          /* 31 */
+  XML_ERR_UNSUPPORTED_ENCODING,      /* 32 */
+  XML_ERR_STRING_NOT_STARTED,        /* 33 */
+  XML_ERR_STRING_NOT_CLOSED,         /* 34 */
+  XML_ERR_NS_DECL_ERROR,             /* 35 */
+  XML_ERR_ENTITY_NOT_STARTED,        /* 36 */
+  XML_ERR_ENTITY_NOT_FINISHED,       /* 37 */
+  XML_ERR_LT_IN_ATTRIBUTE,           /* 38 */
+  XML_ERR_ATTRIBUTE_NOT_STARTED,     /* 39 */
+  XML_ERR_ATTRIBUTE_NOT_FINISHED,    /* 40 */
+  XML_ERR_ATTRIBUTE_WITHOUT_VALUE,   /* 41 */
+  XML_ERR_ATTRIBUTE_REDEFINED,       /* 42 */
+  XML_ERR_LITERAL_NOT_STARTED,       /* 43 */
+  XML_ERR_LITERAL_NOT_FINISHED,      /* 44 */
+  XML_ERR_COMMENT_NOT_FINISHED,      /* 45 */
+  XML_ERR_PI_NOT_STARTED,            /* 46 */
+  XML_ERR_PI_NOT_FINISHED,           /* 47 */
+  XML_ERR_NOTATION_NOT_STARTED,      /* 48 */
+  XML_ERR_NOTATION_NOT_FINISHED,     /* 49 */
+  XML_ERR_ATTLIST_NOT_STARTED,       /* 50 */
+  XML_ERR_ATTLIST_NOT_FINISHED,      /* 51 */
+  XML_ERR_MIXED_NOT_STARTED,         /* 52 */
+  XML_ERR_MIXED_NOT_FINISHED,        /* 53 */
+  XML_ERR_ELEMCONTENT_NOT_STARTED,   /* 54 */
+  XML_ERR_ELEMCONTENT_NOT_FINISHED,  /* 55 */
+  XML_ERR_XMLDECL_NOT_STARTED,       /* 56 */
+  XML_ERR_XMLDECL_NOT_FINISHED,      /* 57 */
+  XML_ERR_CONDSEC_NOT_STARTED,       /* 58 */
+  XML_ERR_CONDSEC_NOT_FINISHED,      /* 59 */
+  XML_ERR_EXT_SUBSET_NOT_FINISHED,   /* 60 */
+  XML_ERR_DOCTYPE_NOT_FINISHED,      /* 61 */
+  XML_ERR_MISPLACED_CDATA_END,       /* 62 */
+  XML_ERR_CDATA_NOT_FINISHED,        /* 63 */
+  XML_ERR_RESERVED_XML_NAME,         /* 64 */
+  XML_ERR_SPACE_REQUIRED,            /* 65 */
+  XML_ERR_SEPARATOR_REQUIRED,        /* 66 */
+  XML_ERR_NMTOKEN_REQUIRED,          /* 67 */
+  XML_ERR_NAME_REQUIRED,             /* 68 */
+  XML_ERR_PCDATA_REQUIRED,           /* 69 */
+  XML_ERR_URI_REQUIRED,              /* 70 */
+  XML_ERR_PUBID_REQUIRED,            /* 71 */
+  XML_ERR_LT_REQUIRED,               /* 72 */
+  XML_ERR_GT_REQUIRED,               /* 73 */
+  XML_ERR_LTSLASH_REQUIRED,          /* 74 */
+  XML_ERR_EQUAL_REQUIRED,            /* 75 */
+  XML_ERR_TAG_NAME_MISMATCH,         /* 76 */
+  XML_ERR_TAG_NOT_FINISHED,          /* 77 */
+  XML_ERR_STANDALONE_VALUE,          /* 78 */
+  XML_ERR_ENCODING_NAME,             /* 79 */
+  XML_ERR_HYPHEN_IN_COMMENT,         /* 80 */
+  XML_ERR_INVALID_ENCODING,          /* 81 */
+  XML_ERR_EXT_ENTITY_STANDALONE,     /* 82 */
+  XML_ERR_CONDSEC_INVALID,           /* 83 */
+  XML_ERR_VALUE_REQUIRED,            /* 84 */
+  XML_ERR_NOT_WELL_BALANCED,         /* 85 */
+  XML_ERR_EXTRA_CONTENT,             /* 86 */
+  XML_ERR_ENTITY_CHAR_ERROR,         /* 87 */
+  XML_ERR_ENTITY_PE_INTERNAL,        /* 88 */
+  XML_ERR_ENTITY_LOOP,               /* 89 */
+  XML_ERR_ENTITY_BOUNDARY,           /* 90 */
+  XML_ERR_INVALID_URI,               /* 91 */
+  XML_ERR_URI_FRAGMENT,              /* 92 */
+  XML_WAR_CATALOG_PI,                /* 93 */
+  XML_ERR_NO_DTD,                    /* 94 */
+  XML_ERR_CONDSEC_INVALID_KEYWORD,   /* 95 */
+  XML_ERR_VERSION_MISSING,           /* 96 */
+  XML_WAR_UNKNOWN_VERSION,           /* 97 */
+  XML_WAR_LANG_VALUE,                /* 98 */
+  XML_WAR_NS_URI,                    /* 99 */
+  XML_WAR_NS_URI_RELATIVE,           /* 100 */
+  XML_ERR_MISSING_ENCODING,          /* 101 */
+  XML_WAR_SPACE_VALUE,               /* 102 */
+  XML_ERR_NOT_STANDALONE,            /* 103 */
+  XML_ERR_ENTITY_PROCESSING,         /* 104 */
+  XML_ERR_NOTATION_PROCESSING,       /* 105 */
+  XML_WAR_NS_COLUMN,                 /* 106 */
+  XML_WAR_ENTITY_REDEFINED,          /* 107 */
+  XML_ERR_UNKNOWN_VERSION,           /* 108 */
+  XML_ERR_VERSION_MISMATCH,          /* 109 */
+  XML_ERR_NAME_TOO_LONG,             /* 110 */
+  XML_ERR_USER_STOP,                 /* 111 */
+  XML_ERR_COMMENT_ABRUPTLY_ENDED,    /* 112 */
+  XML_WAR_ENCODING_MISMATCH,         /* 113 */
+  XML_NS_ERR_XML_NAMESPACE = 200,
+  XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */
+  XML_NS_ERR_QNAME,               /* 202 */
+  XML_NS_ERR_ATTRIBUTE_REDEFINED, /* 203 */
+  XML_NS_ERR_EMPTY,               /* 204 */
+  XML_NS_ERR_COLON,               /* 205 */
+  XML_DTD_ATTRIBUTE_DEFAULT = 500,
+  XML_DTD_ATTRIBUTE_REDEFINED,     /* 501 */
+  XML_DTD_ATTRIBUTE_VALUE,         /* 502 */
+  XML_DTD_CONTENT_ERROR,           /* 503 */
+  XML_DTD_CONTENT_MODEL,           /* 504 */
+  XML_DTD_CONTENT_NOT_DETERMINIST, /* 505 */
+  XML_DTD_DIFFERENT_PREFIX,        /* 506 */
+  XML_DTD_ELEM_DEFAULT_NAMESPACE,  /* 507 */
+  XML_DTD_ELEM_NAMESPACE,          /* 508 */
+  XML_DTD_ELEM_REDEFINED,          /* 509 */
+  XML_DTD_EMPTY_NOTATION,          /* 510 */
+  XML_DTD_ENTITY_TYPE,             /* 511 */
+  XML_DTD_ID_FIXED,                /* 512 */
+  XML_DTD_ID_REDEFINED,            /* 513 */
+  XML_DTD_ID_SUBSET,               /* 514 */
+  XML_DTD_INVALID_CHILD,           /* 515 */
+  XML_DTD_INVALID_DEFAULT,         /* 516 */
+  XML_DTD_LOAD_ERROR,              /* 517 */
+  XML_DTD_MISSING_ATTRIBUTE,       /* 518 */
+  XML_DTD_MIXED_CORRUPT,           /* 519 */
+  XML_DTD_MULTIPLE_ID,             /* 520 */
+  XML_DTD_NO_DOC,                  /* 521 */
+  XML_DTD_NO_DTD,                  /* 522 */
+  XML_DTD_NO_ELEM_NAME,            /* 523 */
+  XML_DTD_NO_PREFIX,               /* 524 */
+  XML_DTD_NO_ROOT,                 /* 525 */
+  XML_DTD_NOTATION_REDEFINED,      /* 526 */
+  XML_DTD_NOTATION_VALUE,          /* 527 */
+  XML_DTD_NOT_EMPTY,               /* 528 */
+  XML_DTD_NOT_PCDATA,              /* 529 */
+  XML_DTD_NOT_STANDALONE,          /* 530 */
+  XML_DTD_ROOT_NAME,               /* 531 */
+  XML_DTD_STANDALONE_WHITE_SPACE,  /* 532 */
+  XML_DTD_UNKNOWN_ATTRIBUTE,       /* 533 */
+  XML_DTD_UNKNOWN_ELEM,            /* 534 */
+  XML_DTD_UNKNOWN_ENTITY,          /* 535 */
+  XML_DTD_UNKNOWN_ID,              /* 536 */
+  XML_DTD_UNKNOWN_NOTATION,        /* 537 */
+  XML_DTD_STANDALONE_DEFAULTED,    /* 538 */
+  XML_DTD_XMLID_VALUE,             /* 539 */
+  XML_DTD_XMLID_TYPE,              /* 540 */
+  XML_DTD_DUP_TOKEN,               /* 541 */
+  XML_HTML_STRUCURE_ERROR = 800,
+  XML_HTML_UNKNOWN_TAG,                /* 801 */
+  XML_HTML_INCORRECTLY_OPENED_COMMENT, /* 802 */
+  XML_RNGP_ANYNAME_ATTR_ANCESTOR = 1000,
+  XML_RNGP_ATTR_CONFLICT,               /* 1001 */
+  XML_RNGP_ATTRIBUTE_CHILDREN,          /* 1002 */
+  XML_RNGP_ATTRIBUTE_CONTENT,           /* 1003 */
+  XML_RNGP_ATTRIBUTE_EMPTY,             /* 1004 */
+  XML_RNGP_ATTRIBUTE_NOOP,              /* 1005 */
+  XML_RNGP_CHOICE_CONTENT,              /* 1006 */
+  XML_RNGP_CHOICE_EMPTY,                /* 1007 */
+  XML_RNGP_CREATE_FAILURE,              /* 1008 */
+  XML_RNGP_DATA_CONTENT,                /* 1009 */
+  XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,   /* 1010 */
+  XML_RNGP_DEFINE_CREATE_FAILED,        /* 1011 */
+  XML_RNGP_DEFINE_EMPTY,                /* 1012 */
+  XML_RNGP_DEFINE_MISSING,              /* 1013 */
+  XML_RNGP_DEFINE_NAME_MISSING,         /* 1014 */
+  XML_RNGP_ELEM_CONTENT_EMPTY,          /* 1015 */
+  XML_RNGP_ELEM_CONTENT_ERROR,          /* 1016 */
+  XML_RNGP_ELEMENT_EMPTY,               /* 1017 */
+  XML_RNGP_ELEMENT_CONTENT,             /* 1018 */
+  XML_RNGP_ELEMENT_NAME,                /* 1019 */
+  XML_RNGP_ELEMENT_NO_CONTENT,          /* 1020 */
+  XML_RNGP_ELEM_TEXT_CONFLICT,          /* 1021 */
+  XML_RNGP_EMPTY,                       /* 1022 */
+  XML_RNGP_EMPTY_CONSTRUCT,             /* 1023 */
+  XML_RNGP_EMPTY_CONTENT,               /* 1024 */
+  XML_RNGP_EMPTY_NOT_EMPTY,             /* 1025 */
+  XML_RNGP_ERROR_TYPE_LIB,              /* 1026 */
+  XML_RNGP_EXCEPT_EMPTY,                /* 1027 */
+  XML_RNGP_EXCEPT_MISSING,              /* 1028 */
+  XML_RNGP_EXCEPT_MULTIPLE,             /* 1029 */
+  XML_RNGP_EXCEPT_NO_CONTENT,           /* 1030 */
+  XML_RNGP_EXTERNALREF_EMTPY,           /* 1031 */
+  XML_RNGP_EXTERNAL_REF_FAILURE,        /* 1032 */
+  XML_RNGP_EXTERNALREF_RECURSE,         /* 1033 */
+  XML_RNGP_FORBIDDEN_ATTRIBUTE,         /* 1034 */
+  XML_RNGP_FOREIGN_ELEMENT,             /* 1035 */
+  XML_RNGP_GRAMMAR_CONTENT,             /* 1036 */
+  XML_RNGP_GRAMMAR_EMPTY,               /* 1037 */
+  XML_RNGP_GRAMMAR_MISSING,             /* 1038 */
+  XML_RNGP_GRAMMAR_NO_START,            /* 1039 */
+  XML_RNGP_GROUP_ATTR_CONFLICT,         /* 1040 */
+  XML_RNGP_HREF_ERROR,                  /* 1041 */
+  XML_RNGP_INCLUDE_EMPTY,               /* 1042 */
+  XML_RNGP_INCLUDE_FAILURE,             /* 1043 */
+  XML_RNGP_INCLUDE_RECURSE,             /* 1044 */
+  XML_RNGP_INTERLEAVE_ADD,              /* 1045 */
+  XML_RNGP_INTERLEAVE_CREATE_FAILED,    /* 1046 */
+  XML_RNGP_INTERLEAVE_EMPTY,            /* 1047 */
+  XML_RNGP_INTERLEAVE_NO_CONTENT,       /* 1048 */
+  XML_RNGP_INVALID_DEFINE_NAME,         /* 1049 */
+  XML_RNGP_INVALID_URI,                 /* 1050 */
+  XML_RNGP_INVALID_VALUE,               /* 1051 */
+  XML_RNGP_MISSING_HREF,                /* 1052 */
+  XML_RNGP_NAME_MISSING,                /* 1053 */
+  XML_RNGP_NEED_COMBINE,                /* 1054 */
+  XML_RNGP_NOTALLOWED_NOT_EMPTY,        /* 1055 */
+  XML_RNGP_NSNAME_ATTR_ANCESTOR,        /* 1056 */
+  XML_RNGP_NSNAME_NO_NS,                /* 1057 */
+  XML_RNGP_PARAM_FORBIDDEN,             /* 1058 */
+  XML_RNGP_PARAM_NAME_MISSING,          /* 1059 */
+  XML_RNGP_PARENTREF_CREATE_FAILED,     /* 1060 */
+  XML_RNGP_PARENTREF_NAME_INVALID,      /* 1061 */
+  XML_RNGP_PARENTREF_NO_NAME,           /* 1062 */
+  XML_RNGP_PARENTREF_NO_PARENT,         /* 1063 */
+  XML_RNGP_PARENTREF_NOT_EMPTY,         /* 1064 */
+  XML_RNGP_PARSE_ERROR,                 /* 1065 */
+  XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME,  /* 1066 */
+  XML_RNGP_PAT_ATTR_ATTR,               /* 1067 */
+  XML_RNGP_PAT_ATTR_ELEM,               /* 1068 */
+  XML_RNGP_PAT_DATA_EXCEPT_ATTR,        /* 1069 */
+  XML_RNGP_PAT_DATA_EXCEPT_ELEM,        /* 1070 */
+  XML_RNGP_PAT_DATA_EXCEPT_EMPTY,       /* 1071 */
+  XML_RNGP_PAT_DATA_EXCEPT_GROUP,       /* 1072 */
+  XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,  /* 1073 */
+  XML_RNGP_PAT_DATA_EXCEPT_LIST,        /* 1074 */
+  XML_RNGP_PAT_DATA_EXCEPT_ONEMORE,     /* 1075 */
+  XML_RNGP_PAT_DATA_EXCEPT_REF,         /* 1076 */
+  XML_RNGP_PAT_DATA_EXCEPT_TEXT,        /* 1077 */
+  XML_RNGP_PAT_LIST_ATTR,               /* 1078 */
+  XML_RNGP_PAT_LIST_ELEM,               /* 1079 */
+  XML_RNGP_PAT_LIST_INTERLEAVE,         /* 1080 */
+  XML_RNGP_PAT_LIST_LIST,               /* 1081 */
+  XML_RNGP_PAT_LIST_REF,                /* 1082 */
+  XML_RNGP_PAT_LIST_TEXT,               /* 1083 */
+  XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME,   /* 1084 */
+  XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME,    /* 1085 */
+  XML_RNGP_PAT_ONEMORE_GROUP_ATTR,      /* 1086 */
+  XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR, /* 1087 */
+  XML_RNGP_PAT_START_ATTR,              /* 1088 */
+  XML_RNGP_PAT_START_DATA,              /* 1089 */
+  XML_RNGP_PAT_START_EMPTY,             /* 1090 */
+  XML_RNGP_PAT_START_GROUP,             /* 1091 */
+  XML_RNGP_PAT_START_INTERLEAVE,        /* 1092 */
+  XML_RNGP_PAT_START_LIST,              /* 1093 */
+  XML_RNGP_PAT_START_ONEMORE,           /* 1094 */
+  XML_RNGP_PAT_START_TEXT,              /* 1095 */
+  XML_RNGP_PAT_START_VALUE,             /* 1096 */
+  XML_RNGP_PREFIX_UNDEFINED,            /* 1097 */
+  XML_RNGP_REF_CREATE_FAILED,           /* 1098 */
+  XML_RNGP_REF_CYCLE,                   /* 1099 */
+  XML_RNGP_REF_NAME_INVALID,            /* 1100 */
+  XML_RNGP_REF_NO_DEF,                  /* 1101 */
+  XML_RNGP_REF_NO_NAME,                 /* 1102 */
+  XML_RNGP_REF_NOT_EMPTY,               /* 1103 */
+  XML_RNGP_START_CHOICE_AND_INTERLEAVE, /* 1104 */
+  XML_RNGP_START_CONTENT,               /* 1105 */
+  XML_RNGP_START_EMPTY,                 /* 1106 */
+  XML_RNGP_START_MISSING,               /* 1107 */
+  XML_RNGP_TEXT_EXPECTED,               /* 1108 */
+  XML_RNGP_TEXT_HAS_CHILD,              /* 1109 */
+  XML_RNGP_TYPE_MISSING,                /* 1110 */
+  XML_RNGP_TYPE_NOT_FOUND,              /* 1111 */
+  XML_RNGP_TYPE_VALUE,                  /* 1112 */
+  XML_RNGP_UNKNOWN_ATTRIBUTE,           /* 1113 */
+  XML_RNGP_UNKNOWN_COMBINE,             /* 1114 */
+  XML_RNGP_UNKNOWN_CONSTRUCT,           /* 1115 */
+  XML_RNGP_UNKNOWN_TYPE_LIB,            /* 1116 */
+  XML_RNGP_URI_FRAGMENT,                /* 1117 */
+  XML_RNGP_URI_NOT_ABSOLUTE,            /* 1118 */
+  XML_RNGP_VALUE_EMPTY,                 /* 1119 */
+  XML_RNGP_VALUE_NO_CONTENT,            /* 1120 */
+  XML_RNGP_XMLNS_NAME,                  /* 1121 */
+  XML_RNGP_XML_NS,                      /* 1122 */
+  XML_XPATH_EXPRESSION_OK = 1200,
+  XML_XPATH_NUMBER_ERROR,             /* 1201 */
+  XML_XPATH_UNFINISHED_LITERAL_ERROR, /* 1202 */
+  XML_XPATH_START_LITERAL_ERROR,      /* 1203 */
+  XML_XPATH_VARIABLE_REF_ERROR,       /* 1204 */
+  XML_XPATH_UNDEF_VARIABLE_ERROR,     /* 1205 */
+  XML_XPATH_INVALID_PREDICATE_ERROR,  /* 1206 */
+  XML_XPATH_EXPR_ERROR,               /* 1207 */
+  XML_XPATH_UNCLOSED_ERROR,           /* 1208 */
+  XML_XPATH_UNKNOWN_FUNC_ERROR,       /* 1209 */
+  XML_XPATH_INVALID_OPERAND,          /* 1210 */
+  XML_XPATH_INVALID_TYPE,             /* 1211 */
+  XML_XPATH_INVALID_ARITY,            /* 1212 */
+  XML_XPATH_INVALID_CTXT_SIZE,        /* 1213 */
+  XML_XPATH_INVALID_CTXT_POSITION,    /* 1214 */
+  XML_XPATH_MEMORY_ERROR,             /* 1215 */
+  XML_XPTR_SYNTAX_ERROR,              /* 1216 */
+  XML_XPTR_RESOURCE_ERROR,            /* 1217 */
+  XML_XPTR_SUB_RESOURCE_ERROR,        /* 1218 */
+  XML_XPATH_UNDEF_PREFIX_ERROR,       /* 1219 */
+  XML_XPATH_ENCODING_ERROR,           /* 1220 */
+  XML_XPATH_INVALID_CHAR_ERROR,       /* 1221 */
+  XML_TREE_INVALID_HEX = 1300,
+  XML_TREE_INVALID_DEC,         /* 1301 */
+  XML_TREE_UNTERMINATED_ENTITY, /* 1302 */
+  XML_TREE_NOT_UTF8,            /* 1303 */
+  XML_SAVE_NOT_UTF8 = 1400,
+  XML_SAVE_CHAR_INVALID,     /* 1401 */
+  XML_SAVE_NO_DOCTYPE,       /* 1402 */
+  XML_SAVE_UNKNOWN_ENCODING, /* 1403 */
+  XML_REGEXP_COMPILE_ERROR = 1450,
+  XML_IO_UNKNOWN = 1500,
+  XML_IO_EACCES,          /* 1501 */
+  XML_IO_EAGAIN,          /* 1502 */
+  XML_IO_EBADF,           /* 1503 */
+  XML_IO_EBADMSG,         /* 1504 */
+  XML_IO_EBUSY,           /* 1505 */
+  XML_IO_ECANCELED,       /* 1506 */
+  XML_IO_ECHILD,          /* 1507 */
+  XML_IO_EDEADLK,         /* 1508 */
+  XML_IO_EDOM,            /* 1509 */
+  XML_IO_EEXIST,          /* 1510 */
+  XML_IO_EFAULT,          /* 1511 */
+  XML_IO_EFBIG,           /* 1512 */
+  XML_IO_EINPROGRESS,     /* 1513 */
+  XML_IO_EINTR,           /* 1514 */
+  XML_IO_EINVAL,          /* 1515 */
+  XML_IO_EIO,             /* 1516 */
+  XML_IO_EISDIR,          /* 1517 */
+  XML_IO_EMFILE,          /* 1518 */
+  XML_IO_EMLINK,          /* 1519 */
+  XML_IO_EMSGSIZE,        /* 1520 */
+  XML_IO_ENAMETOOLONG,    /* 1521 */
+  XML_IO_ENFILE,          /* 1522 */
+  XML_IO_ENODEV,          /* 1523 */
+  XML_IO_ENOENT,          /* 1524 */
+  XML_IO_ENOEXEC,         /* 1525 */
+  XML_IO_ENOLCK,          /* 1526 */
+  XML_IO_ENOMEM,          /* 1527 */
+  XML_IO_ENOSPC,          /* 1528 */
+  XML_IO_ENOSYS,          /* 1529 */
+  XML_IO_ENOTDIR,         /* 1530 */
+  XML_IO_ENOTEMPTY,       /* 1531 */
+  XML_IO_ENOTSUP,         /* 1532 */
+  XML_IO_ENOTTY,          /* 1533 */
+  XML_IO_ENXIO,           /* 1534 */
+  XML_IO_EPERM,           /* 1535 */
+  XML_IO_EPIPE,           /* 1536 */
+  XML_IO_ERANGE,          /* 1537 */
+  XML_IO_EROFS,           /* 1538 */
+  XML_IO_ESPIPE,          /* 1539 */
+  XML_IO_ESRCH,           /* 1540 */
+  XML_IO_ETIMEDOUT,       /* 1541 */
+  XML_IO_EXDEV,           /* 1542 */
+  XML_IO_NETWORK_ATTEMPT, /* 1543 */
+  XML_IO_ENCODER,         /* 1544 */
+  XML_IO_FLUSH,           /* 1545 */
+  XML_IO_WRITE,           /* 1546 */
+  XML_IO_NO_INPUT,        /* 1547 */
+  XML_IO_BUFFER_FULL,     /* 1548 */
+  XML_IO_LOAD_ERROR,      /* 1549 */
+  XML_IO_ENOTSOCK,        /* 1550 */
+  XML_IO_EISCONN,         /* 1551 */
+  XML_IO_ECONNREFUSED,    /* 1552 */
+  XML_IO_ENETUNREACH,     /* 1553 */
+  XML_IO_EADDRINUSE,      /* 1554 */
+  XML_IO_EALREADY,        /* 1555 */
+  XML_IO_EAFNOSUPPORT,    /* 1556 */
+  XML_XINCLUDE_RECURSION = 1600,
+  XML_XINCLUDE_PARSE_VALUE,             /* 1601 */
+  XML_XINCLUDE_ENTITY_DEF_MISMATCH,     /* 1602 */
+  XML_XINCLUDE_NO_HREF,                 /* 1603 */
+  XML_XINCLUDE_NO_FALLBACK,             /* 1604 */
+  XML_XINCLUDE_HREF_URI,                /* 1605 */
+  XML_XINCLUDE_TEXT_FRAGMENT,           /* 1606 */
+  XML_XINCLUDE_TEXT_DOCUMENT,           /* 1607 */
+  XML_XINCLUDE_INVALID_CHAR,            /* 1608 */
+  XML_XINCLUDE_BUILD_FAILED,            /* 1609 */
+  XML_XINCLUDE_UNKNOWN_ENCODING,        /* 1610 */
+  XML_XINCLUDE_MULTIPLE_ROOT,           /* 1611 */
+  XML_XINCLUDE_XPTR_FAILED,             /* 1612 */
+  XML_XINCLUDE_XPTR_RESULT,             /* 1613 */
+  XML_XINCLUDE_INCLUDE_IN_INCLUDE,      /* 1614 */
+  XML_XINCLUDE_FALLBACKS_IN_INCLUDE,    /* 1615 */
+  XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE, /* 1616 */
+  XML_XINCLUDE_DEPRECATED_NS,           /* 1617 */
+  XML_XINCLUDE_FRAGMENT_ID,             /* 1618 */
+  XML_CATALOG_MISSING_ATTR = 1650,
+  XML_CATALOG_ENTRY_BROKEN, /* 1651 */
+  XML_CATALOG_PREFER_VALUE, /* 1652 */
+  XML_CATALOG_NOT_CATALOG,  /* 1653 */
+  XML_CATALOG_RECURSION,    /* 1654 */
+  XML_SCHEMAP_PREFIX_UNDEFINED = 1700,
+  XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,           /* 1701 */
+  XML_SCHEMAP_ATTRGRP_NONAME_NOREF,            /* 1702 */
+  XML_SCHEMAP_ATTR_NONAME_NOREF,               /* 1703 */
+  XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF,        /* 1704 */
+  XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,           /* 1705 */
+  XML_SCHEMAP_ELEM_NONAME_NOREF,               /* 1706 */
+  XML_SCHEMAP_EXTENSION_NO_BASE,               /* 1707 */
+  XML_SCHEMAP_FACET_NO_VALUE,                  /* 1708 */
+  XML_SCHEMAP_FAILED_BUILD_IMPORT,             /* 1709 */
+  XML_SCHEMAP_GROUP_NONAME_NOREF,              /* 1710 */
+  XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,        /* 1711 */
+  XML_SCHEMAP_IMPORT_REDEFINE_NSNAME,          /* 1712 */
+  XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,           /* 1713 */
+  XML_SCHEMAP_INVALID_BOOLEAN,                 /* 1714 */
+  XML_SCHEMAP_INVALID_ENUM,                    /* 1715 */
+  XML_SCHEMAP_INVALID_FACET,                   /* 1716 */
+  XML_SCHEMAP_INVALID_FACET_VALUE,             /* 1717 */
+  XML_SCHEMAP_INVALID_MAXOCCURS,               /* 1718 */
+  XML_SCHEMAP_INVALID_MINOCCURS,               /* 1719 */
+  XML_SCHEMAP_INVALID_REF_AND_SUBTYPE,         /* 1720 */
+  XML_SCHEMAP_INVALID_WHITE_SPACE,             /* 1721 */
+  XML_SCHEMAP_NOATTR_NOREF,                    /* 1722 */
+  XML_SCHEMAP_NOTATION_NO_NAME,                /* 1723 */
+  XML_SCHEMAP_NOTYPE_NOREF,                    /* 1724 */
+  XML_SCHEMAP_REF_AND_SUBTYPE,                 /* 1725 */
+  XML_SCHEMAP_RESTRICTION_NONAME_NOREF,        /* 1726 */
+  XML_SCHEMAP_SIMPLETYPE_NONAME,               /* 1727 */
+  XML_SCHEMAP_TYPE_AND_SUBTYPE,                /* 1728 */
+  XML_SCHEMAP_UNKNOWN_ALL_CHILD,               /* 1729 */
+  XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD,      /* 1730 */
+  XML_SCHEMAP_UNKNOWN_ATTR_CHILD,              /* 1731 */
+  XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD,           /* 1732 */
+  XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP,         /* 1733 */
+  XML_SCHEMAP_UNKNOWN_BASE_TYPE,               /* 1734 */
+  XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,            /* 1735 */
+  XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD,    /* 1736 */
+  XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD,       /* 1737 */
+  XML_SCHEMAP_UNKNOWN_ELEM_CHILD,              /* 1738 */
+  XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,         /* 1739 */
+  XML_SCHEMAP_UNKNOWN_FACET_CHILD,             /* 1740 */
+  XML_SCHEMAP_UNKNOWN_FACET_TYPE,              /* 1741 */
+  XML_SCHEMAP_UNKNOWN_GROUP_CHILD,             /* 1742 */
+  XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,            /* 1743 */
+  XML_SCHEMAP_UNKNOWN_LIST_CHILD,              /* 1744 */
+  XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,          /* 1745 */
+  XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,    /* 1746 */
+  XML_SCHEMAP_UNKNOWN_REF,                     /* 1747 */
+  XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,       /* 1748 */
+  XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,           /* 1749 */
+  XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,          /* 1750 */
+  XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,     /* 1751 */
+  XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD,        /* 1752 */
+  XML_SCHEMAP_UNKNOWN_TYPE,                    /* 1753 */
+  XML_SCHEMAP_UNKNOWN_UNION_CHILD,             /* 1754 */
+  XML_SCHEMAP_ELEM_DEFAULT_FIXED,              /* 1755 */
+  XML_SCHEMAP_REGEXP_INVALID,                  /* 1756 */
+  XML_SCHEMAP_FAILED_LOAD,                     /* 1757 */
+  XML_SCHEMAP_NOTHING_TO_PARSE,                /* 1758 */
+  XML_SCHEMAP_NOROOT,                          /* 1759 */
+  XML_SCHEMAP_REDEFINED_GROUP,                 /* 1760 */
+  XML_SCHEMAP_REDEFINED_TYPE,                  /* 1761 */
+  XML_SCHEMAP_REDEFINED_ELEMENT,               /* 1762 */
+  XML_SCHEMAP_REDEFINED_ATTRGROUP,             /* 1763 */
+  XML_SCHEMAP_REDEFINED_ATTR,                  /* 1764 */
+  XML_SCHEMAP_REDEFINED_NOTATION,              /* 1765 */
+  XML_SCHEMAP_FAILED_PARSE,                    /* 1766 */
+  XML_SCHEMAP_UNKNOWN_PREFIX,                  /* 1767 */
+  XML_SCHEMAP_DEF_AND_PREFIX,                  /* 1768 */
+  XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,           /* 1769 */
+  XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI,          /* 1770 */
+  XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,           /* 1771 */
+  XML_SCHEMAP_NOT_SCHEMA,                      /* 1772 */
+  XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,             /* 1773 */
+  XML_SCHEMAP_INVALID_ATTR_USE,                /* 1774 */
+  XML_SCHEMAP_RECURSIVE,                       /* 1775 */
+  XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE,    /* 1776 */
+  XML_SCHEMAP_INVALID_ATTR_COMBINATION,        /* 1777 */
+  XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION, /* 1778 */
+  XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD,        /* 1779 */
+  XML_SCHEMAP_INVALID_ATTR_NAME,               /* 1780 */
+  XML_SCHEMAP_REF_AND_CONTENT,                 /* 1781 */
+  XML_SCHEMAP_CT_PROPS_CORRECT_1,              /* 1782 */
+  XML_SCHEMAP_CT_PROPS_CORRECT_2,              /* 1783 */
+  XML_SCHEMAP_CT_PROPS_CORRECT_3,              /* 1784 */
+  XML_SCHEMAP_CT_PROPS_CORRECT_4,              /* 1785 */
+  XML_SCHEMAP_CT_PROPS_CORRECT_5,              /* 1786 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,     /* 1787 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, /* 1788 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, /* 1789 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,   /* 1790 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,     /* 1791 */
+  XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,      /* 1792 */
+  XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,    /* 1793 */
+  XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,           /* 1794 */
+  XML_SCHEMAP_SRC_IMPORT_3_1,                  /* 1795 */
+  XML_SCHEMAP_SRC_IMPORT_3_2,                  /* 1796 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,   /* 1797 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,   /* 1798 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,   /* 1799 */
+  XML_SCHEMAP_COS_CT_EXTENDS_1_3,              /* 1800 */
+  XML_SCHEMAV_NOROOT = 1801,
+  XML_SCHEMAV_UNDECLAREDELEM,           /* 1802 */
+  XML_SCHEMAV_NOTTOPLEVEL,              /* 1803 */
+  XML_SCHEMAV_MISSING,                  /* 1804 */
+  XML_SCHEMAV_WRONGELEM,                /* 1805 */
+  XML_SCHEMAV_NOTYPE,                   /* 1806 */
+  XML_SCHEMAV_NOROLLBACK,               /* 1807 */
+  XML_SCHEMAV_ISABSTRACT,               /* 1808 */
+  XML_SCHEMAV_NOTEMPTY,                 /* 1809 */
+  XML_SCHEMAV_ELEMCONT,                 /* 1810 */
+  XML_SCHEMAV_HAVEDEFAULT,              /* 1811 */
+  XML_SCHEMAV_NOTNILLABLE,              /* 1812 */
+  XML_SCHEMAV_EXTRACONTENT,             /* 1813 */
+  XML_SCHEMAV_INVALIDATTR,              /* 1814 */
+  XML_SCHEMAV_INVALIDELEM,              /* 1815 */
+  XML_SCHEMAV_NOTDETERMINIST,           /* 1816 */
+  XML_SCHEMAV_CONSTRUCT,                /* 1817 */
+  XML_SCHEMAV_INTERNAL,                 /* 1818 */
+  XML_SCHEMAV_NOTSIMPLE,                /* 1819 */
+  XML_SCHEMAV_ATTRUNKNOWN,              /* 1820 */
+  XML_SCHEMAV_ATTRINVALID,              /* 1821 */
+  XML_SCHEMAV_VALUE,                    /* 1822 */
+  XML_SCHEMAV_FACET,                    /* 1823 */
+  XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, /* 1824 */
+  XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2, /* 1825 */
+  XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3, /* 1826 */
+  XML_SCHEMAV_CVC_TYPE_3_1_1,           /* 1827 */
+  XML_SCHEMAV_CVC_TYPE_3_1_2,           /* 1828 */
+  XML_SCHEMAV_CVC_FACET_VALID,          /* 1829 */
+  XML_SCHEMAV_CVC_LENGTH_VALID,         /* 1830 */
+  XML_SCHEMAV_CVC_MINLENGTH_VALID,      /* 1831 */
+  XML_SCHEMAV_CVC_MAXLENGTH_VALID,      /* 1832 */
+  XML_SCHEMAV_CVC_MININCLUSIVE_VALID,   /* 1833 */
+  XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID,   /* 1834 */
+  XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID,   /* 1835 */
+  XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID,   /* 1836 */
+  XML_SCHEMAV_CVC_TOTALDIGITS_VALID,    /* 1837 */
+  XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID, /* 1838 */
+  XML_SCHEMAV_CVC_PATTERN_VALID,        /* 1839 */
+  XML_SCHEMAV_CVC_ENUMERATION_VALID,    /* 1840 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,     /* 1841 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,     /* 1842 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,     /* 1843 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_2_4,     /* 1844 */
+  XML_SCHEMAV_CVC_ELT_1,                /* 1845 */
+  XML_SCHEMAV_CVC_ELT_2,                /* 1846 */
+  XML_SCHEMAV_CVC_ELT_3_1,              /* 1847 */
+  XML_SCHEMAV_CVC_ELT_3_2_1,            /* 1848 */
+  XML_SCHEMAV_CVC_ELT_3_2_2,            /* 1849 */
+  XML_SCHEMAV_CVC_ELT_4_1,              /* 1850 */
+  XML_SCHEMAV_CVC_ELT_4_2,              /* 1851 */
+  XML_SCHEMAV_CVC_ELT_4_3,              /* 1852 */
+  XML_SCHEMAV_CVC_ELT_5_1_1,            /* 1853 */
+  XML_SCHEMAV_CVC_ELT_5_1_2,            /* 1854 */
+  XML_SCHEMAV_CVC_ELT_5_2_1,            /* 1855 */
+  XML_SCHEMAV_CVC_ELT_5_2_2_1,          /* 1856 */
+  XML_SCHEMAV_CVC_ELT_5_2_2_2_1,        /* 1857 */
+  XML_SCHEMAV_CVC_ELT_5_2_2_2_2,        /* 1858 */
+  XML_SCHEMAV_CVC_ELT_6,                /* 1859 */
+  XML_SCHEMAV_CVC_ELT_7,                /* 1860 */
+  XML_SCHEMAV_CVC_ATTRIBUTE_1,          /* 1861 */
+  XML_SCHEMAV_CVC_ATTRIBUTE_2,          /* 1862 */
+  XML_SCHEMAV_CVC_ATTRIBUTE_3,          /* 1863 */
+  XML_SCHEMAV_CVC_ATTRIBUTE_4,          /* 1864 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_3_1,     /* 1865 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1,   /* 1866 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2,   /* 1867 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_4,       /* 1868 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_5_1,     /* 1869 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_5_2,     /* 1870 */
+  XML_SCHEMAV_ELEMENT_CONTENT,          /* 1871 */
+  XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, /* 1872 */
+  XML_SCHEMAV_CVC_COMPLEX_TYPE_1,       /* 1873 */
+  XML_SCHEMAV_CVC_AU,                   /* 1874 */
+  XML_SCHEMAV_CVC_TYPE_1,               /* 1875 */
+  XML_SCHEMAV_CVC_TYPE_2,               /* 1876 */
+  XML_SCHEMAV_CVC_IDC,                  /* 1877 */
+  XML_SCHEMAV_CVC_WILDCARD,             /* 1878 */
+  XML_SCHEMAV_MISC,                     /* 1879 */
+  XML_XPTR_UNKNOWN_SCHEME = 1900,
+  XML_XPTR_CHILDSEQ_START, /* 1901 */
+  XML_XPTR_EVAL_FAILED,    /* 1902 */
+  XML_XPTR_EXTRA_OBJECTS,  /* 1903 */
+  XML_C14N_CREATE_CTXT = 1950,
+  XML_C14N_REQUIRES_UTF8,      /* 1951 */
+  XML_C14N_CREATE_STACK,       /* 1952 */
+  XML_C14N_INVALID_NODE,       /* 1953 */
+  XML_C14N_UNKNOW_NODE,        /* 1954 */
+  XML_C14N_RELATIVE_NAMESPACE, /* 1955 */
+  XML_FTP_PASV_ANSWER = 2000,
+  XML_FTP_EPSV_ANSWER, /* 2001 */
+  XML_FTP_ACCNT,       /* 2002 */
+  XML_FTP_URL_SYNTAX,  /* 2003 */
+  XML_HTTP_URL_SYNTAX = 2020,
+  XML_HTTP_USE_IP,       /* 2021 */
+  XML_HTTP_UNKNOWN_HOST, /* 2022 */
+  XML_SCHEMAP_SRC_SIMPLE_TYPE_1 = 3000,
+  XML_SCHEMAP_SRC_SIMPLE_TYPE_2,                    /* 3001 */
+  XML_SCHEMAP_SRC_SIMPLE_TYPE_3,                    /* 3002 */
+  XML_SCHEMAP_SRC_SIMPLE_TYPE_4,                    /* 3003 */
+  XML_SCHEMAP_SRC_RESOLVE,                          /* 3004 */
+  XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,   /* 3005 */
+  XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,      /* 3006 */
+  XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, /* 3007 */
+  XML_SCHEMAP_ST_PROPS_CORRECT_1,                   /* 3008 */
+  XML_SCHEMAP_ST_PROPS_CORRECT_2,                   /* 3009 */
+  XML_SCHEMAP_ST_PROPS_CORRECT_3,                   /* 3010 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_1_1,                 /* 3011 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_1_2,                 /* 3012 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,               /* 3013 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_1_3_2,               /* 3014 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_2_1,                 /* 3015 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,             /* 3016 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,             /* 3017 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,             /* 3018 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,             /* 3019 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,             /* 3020 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,             /* 3021 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_5,             /* 3022 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_3_1,                 /* 3023 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,               /* 3024 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,             /* 3025 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,             /* 3026 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,             /* 3027 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,             /* 3028 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,             /* 3029 */
+  XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_5,             /* 3030 */
+  XML_SCHEMAP_COS_ST_DERIVED_OK_2_1,                /* 3031 */
+  XML_SCHEMAP_COS_ST_DERIVED_OK_2_2,                /* 3032 */
+  XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,                 /* 3033 */
+  XML_SCHEMAP_S4S_ELEM_MISSING,                     /* 3034 */
+  XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,                 /* 3035 */
+  XML_SCHEMAP_S4S_ATTR_MISSING,                     /* 3036 */
+  XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,               /* 3037 */
+  XML_SCHEMAP_SRC_ELEMENT_1,                        /* 3038 */
+  XML_SCHEMAP_SRC_ELEMENT_2_1,                      /* 3039 */
+  XML_SCHEMAP_SRC_ELEMENT_2_2,                      /* 3040 */
+  XML_SCHEMAP_SRC_ELEMENT_3,                        /* 3041 */
+  XML_SCHEMAP_P_PROPS_CORRECT_1,                    /* 3042 */
+  XML_SCHEMAP_P_PROPS_CORRECT_2_1,                  /* 3043 */
+  XML_SCHEMAP_P_PROPS_CORRECT_2_2,                  /* 3044 */
+  XML_SCHEMAP_E_PROPS_CORRECT_2,                    /* 3045 */
+  XML_SCHEMAP_E_PROPS_CORRECT_3,                    /* 3046 */
+  XML_SCHEMAP_E_PROPS_CORRECT_4,                    /* 3047 */
+  XML_SCHEMAP_E_PROPS_CORRECT_5,                    /* 3048 */
+  XML_SCHEMAP_E_PROPS_CORRECT_6,                    /* 3049 */
+  XML_SCHEMAP_SRC_INCLUDE,                          /* 3050 */
+  XML_SCHEMAP_SRC_ATTRIBUTE_1,                      /* 3051 */
+  XML_SCHEMAP_SRC_ATTRIBUTE_2,                      /* 3052 */
+  XML_SCHEMAP_SRC_ATTRIBUTE_3_1,                    /* 3053 */
+  XML_SCHEMAP_SRC_ATTRIBUTE_3_2,                    /* 3054 */
+  XML_SCHEMAP_SRC_ATTRIBUTE_4,                      /* 3055 */
+  XML_SCHEMAP_NO_XMLNS,                             /* 3056 */
+  XML_SCHEMAP_NO_XSI,                               /* 3057 */
+  XML_SCHEMAP_COS_VALID_DEFAULT_1,                  /* 3058 */
+  XML_SCHEMAP_COS_VALID_DEFAULT_2_1,                /* 3059 */
+  XML_SCHEMAP_COS_VALID_DEFAULT_2_2_1,              /* 3060 */
+  XML_SCHEMAP_COS_VALID_DEFAULT_2_2_2,              /* 3061 */
+  XML_SCHEMAP_CVC_SIMPLE_TYPE,                      /* 3062 */
+  XML_SCHEMAP_COS_CT_EXTENDS_1_1,                   /* 3063 */
+  XML_SCHEMAP_SRC_IMPORT_1_1,                       /* 3064 */
+  XML_SCHEMAP_SRC_IMPORT_1_2,                       /* 3065 */
+  XML_SCHEMAP_SRC_IMPORT_2,                         /* 3066 */
+  XML_SCHEMAP_SRC_IMPORT_2_1,                       /* 3067 */
+  XML_SCHEMAP_SRC_IMPORT_2_2,                       /* 3068 */
+  XML_SCHEMAP_INTERNAL,                             /* 3069 non-W3C */
+  XML_SCHEMAP_NOT_DETERMINISTIC,                    /* 3070 non-W3C */
+  XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_1,                /* 3071 */
+  XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_2,                /* 3072 */
+  XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,                /* 3073 */
+  XML_SCHEMAP_MG_PROPS_CORRECT_1,                   /* 3074 */
+  XML_SCHEMAP_MG_PROPS_CORRECT_2,                   /* 3075 */
+  XML_SCHEMAP_SRC_CT_1,                             /* 3076 */
+  XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,      /* 3077 */
+  XML_SCHEMAP_AU_PROPS_CORRECT_2,                   /* 3078 */
+  XML_SCHEMAP_A_PROPS_CORRECT_2,                    /* 3079 */
+  XML_SCHEMAP_C_PROPS_CORRECT,                      /* 3080 */
+  XML_SCHEMAP_SRC_REDEFINE,                         /* 3081 */
+  XML_SCHEMAP_SRC_IMPORT,                           /* 3082 */
+  XML_SCHEMAP_WARN_SKIP_SCHEMA,                     /* 3083 */
+  XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,                /* 3084 */
+  XML_SCHEMAP_WARN_ATTR_REDECL_PROH,                /* 3085 */
+  XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,             /* 3085 */
+  XML_SCHEMAP_AG_PROPS_CORRECT,                     /* 3086 */
+  XML_SCHEMAP_COS_CT_EXTENDS_1_2,                   /* 3087 */
+  XML_SCHEMAP_AU_PROPS_CORRECT,                     /* 3088 */
+  XML_SCHEMAP_A_PROPS_CORRECT_3,                    /* 3089 */
+  XML_SCHEMAP_COS_ALL_LIMITED,                      /* 3090 */
+  XML_SCHEMATRONV_ASSERT = 4000,                    /* 4000 */
+  XML_SCHEMATRONV_REPORT,
+  XML_MODULE_OPEN = 4900, /* 4900 */
+  XML_MODULE_CLOSE,       /* 4901 */
+  XML_CHECK_FOUND_ELEMENT = 5000,
+  XML_CHECK_FOUND_ATTRIBUTE, /* 5001 */
+  XML_CHECK_FOUND_TEXT,      /* 5002 */
+  XML_CHECK_FOUND_CDATA,     /* 5003 */
+  XML_CHECK_FOUND_ENTITYREF, /* 5004 */
+  XML_CHECK_FOUND_ENTITY,    /* 5005 */
+  XML_CHECK_FOUND_PI,        /* 5006 */
+  XML_CHECK_FOUND_COMMENT,   /* 5007 */
+  XML_CHECK_FOUND_DOCTYPE,   /* 5008 */
+  XML_CHECK_FOUND_FRAGMENT,  /* 5009 */
+  XML_CHECK_FOUND_NOTATION,  /* 5010 */
+  XML_CHECK_UNKNOWN_NODE,    /* 5011 */
+  XML_CHECK_ENTITY_TYPE,     /* 5012 */
+  XML_CHECK_NO_PARENT,       /* 5013 */
+  XML_CHECK_NO_DOC,          /* 5014 */
+  XML_CHECK_NO_NAME,         /* 5015 */
+  XML_CHECK_NO_ELEM,         /* 5016 */
+  XML_CHECK_WRONG_DOC,       /* 5017 */
+  XML_CHECK_NO_PREV,         /* 5018 */
+  XML_CHECK_WRONG_PREV,      /* 5019 */
+  XML_CHECK_NO_NEXT,         /* 5020 */
+  XML_CHECK_WRONG_NEXT,      /* 5021 */
+  XML_CHECK_NOT_DTD,         /* 5022 */
+  XML_CHECK_NOT_ATTR,        /* 5023 */
+  XML_CHECK_NOT_ATTR_DECL,   /* 5024 */
+  XML_CHECK_NOT_ELEM_DECL,   /* 5025 */
+  XML_CHECK_NOT_ENTITY_DECL, /* 5026 */
+  XML_CHECK_NOT_NS_DECL,     /* 5027 */
+  XML_CHECK_NO_HREF,         /* 5028 */
+  XML_CHECK_WRONG_PARENT,    /* 5029 */
+  XML_CHECK_NS_SCOPE,        /* 5030 */
+  XML_CHECK_NS_ANCESTOR,     /* 5031 */
+  XML_CHECK_NOT_UTF8,        /* 5032 */
+  XML_CHECK_NO_DICT,         /* 5033 */
+  XML_CHECK_NOT_NCNAME,      /* 5034 */
+  XML_CHECK_OUTSIDE_DICT,    /* 5035 */
+  XML_CHECK_WRONG_NAME,      /* 5036 */
+  XML_CHECK_NAME_NOT_NULL,   /* 5037 */
+  XML_I18N_NO_NAME = 6000,
+  XML_I18N_NO_HANDLER,     /* 6001 */
+  XML_I18N_EXCESS_HANDLER, /* 6002 */
+  XML_I18N_CONV_FAILED,    /* 6003 */
+  XML_I18N_NO_OUTPUT,      /* 6004 */
+  XML_BUF_OVERFLOW = 7000
 } xmlParserErrors;
 
 /**
@@ -857,6 +858,27 @@
  */
 typedef void (*xmlStructuredErrorFunc) (void *userData, xmlErrorPtr error);
 
+/** DOC_DISABLE */
+#define XML_GLOBALS_ERROR                                       \
+  XML_OP(xmlLastError, xmlError, XML_DEPRECATED)                \
+  XML_OP(xmlGenericError, xmlGenericErrorFunc, XML_EMPTY)       \
+  XML_OP(xmlGenericErrorContext, void*, XML_EMPTY)              \
+  XML_OP(xmlStructuredError, xmlStructuredErrorFunc, XML_EMPTY) \
+  XML_OP(xmlStructuredErrorContext, void*, XML_EMPTY)
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_ERROR
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+#define xmlLastError XML_GLOBAL_MACRO(xmlLastError)
+#define xmlGenericError XML_GLOBAL_MACRO(xmlGenericError)
+#define xmlGenericErrorContext XML_GLOBAL_MACRO(xmlGenericErrorContext)
+#define xmlStructuredError XML_GLOBAL_MACRO(xmlStructuredError)
+#define xmlStructuredErrorContext XML_GLOBAL_MACRO(xmlStructuredErrorContext)
+#endif
+/** DOC_ENABLE */
+
 /*
  * Use the following function to reset the two global variables
  * xmlGenericError and xmlGenericErrorContext.
@@ -864,6 +886,8 @@
 XMLPUBFUN void
     xmlSetGenericErrorFunc	(void *ctx,
 				 xmlGenericErrorFunc handler);
+XMLPUBFUN void xmlThrDefSetGenericErrorFunc(void* ctx,
+                                            xmlGenericErrorFunc handler);
 XML_DEPRECATED
 XMLPUBFUN void
     initGenericErrorDefaultFunc	(xmlGenericErrorFunc *handler);
@@ -871,6 +895,8 @@
 XMLPUBFUN void
     xmlSetStructuredErrorFunc	(void *ctx,
 				 xmlStructuredErrorFunc handler);
+XMLPUBFUN void xmlThrDefSetStructuredErrorFunc(void* ctx,
+                                               xmlStructuredErrorFunc handler);
 /*
  * Default message routines used by SAX and Valid context for error
  * and warning reporting.
@@ -891,10 +917,9 @@
     xmlParserValidityWarning	(void *ctx,
 				 const char *msg,
 				 ...) LIBXML_ATTR_FORMAT(2,3);
-XMLPUBFUN void
-    xmlParserPrintFileInfo	(xmlParserInputPtr input);
-XMLPUBFUN void
-    xmlParserPrintFileContext	(xmlParserInputPtr input);
+struct _xmlParserInput;
+XMLPUBFUN void xmlParserPrintFileInfo(struct _xmlParserInput* input);
+XMLPUBFUN void xmlParserPrintFileContext(struct _xmlParserInput* input);
 
 /*
  * Extended error information routines
diff --git a/third_party/libxml/src/include/libxml/xmlmemory.h b/third_party/libxml/src/include/libxml/xmlmemory.h
index 830933a7..87401737 100644
--- a/third_party/libxml/src/include/libxml/xmlmemory.h
+++ b/third_party/libxml/src/include/libxml/xmlmemory.h
@@ -15,32 +15,6 @@
 #include <stdio.h>
 #include <libxml/xmlversion.h>
 
-/**
- * DEBUG_MEMORY:
- *
- * DEBUG_MEMORY replaces the allocator with a collect and debug
- * shell to the libc allocator.
- * DEBUG_MEMORY should only be activated when debugging
- * libxml i.e. if libxml has been configured with --with-debug-mem too.
- */
-/* #define DEBUG_MEMORY_FREED */
-/* #define DEBUG_MEMORY_LOCATION */
-
-#ifdef DEBUG
-#ifndef DEBUG_MEMORY
-#define DEBUG_MEMORY
-#endif
-#endif
-
-/**
- * DEBUG_MEMORY_LOCATION:
- *
- * DEBUG_MEMORY_LOCATION should be activated only when debugging
- * libxml i.e. if libxml has been configured with --with-debug-mem too.
- */
-#ifdef DEBUG_MEMORY_LOCATION
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -87,13 +61,41 @@
 typedef char *(*xmlStrdupFunc)(const char *str);
 
 /*
- * The 4 interfaces used for all memory handling within libxml.
-LIBXML_DLL_IMPORT xmlFreeFunc xmlFree;
-LIBXML_DLL_IMPORT xmlMallocFunc xmlMalloc;
-LIBXML_DLL_IMPORT xmlMallocFunc xmlMallocAtomic;
-LIBXML_DLL_IMPORT xmlReallocFunc xmlRealloc;
-LIBXML_DLL_IMPORT xmlStrdupFunc xmlMemStrdup;
+ * In general the memory allocation entry points are not kept
+ * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED
+ *    - xmlMalloc
+ *    - xmlMallocAtomic
+ *    - xmlRealloc
+ *    - xmlMemStrdup
+ *    - xmlFree
  */
+/** DOC_DISABLE */
+#ifdef LIBXML_THREAD_ALLOC_ENABLED
+#define XML_GLOBALS_ALLOC                           \
+  XML_OP(xmlMalloc, xmlMallocFunc, XML_EMPTY)       \
+  XML_OP(xmlMallocAtomic, xmlMallocFunc, XML_EMPTY) \
+  XML_OP(xmlRealloc, xmlReallocFunc, XML_EMPTY)     \
+  XML_OP(xmlFree, xmlFreeFunc, XML_EMPTY)           \
+  XML_OP(xmlMemStrdup, xmlStrdupFunc, XML_EMPTY)
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_ALLOC
+#undef XML_OP
+#ifdef LIBXML_THREAD_ENABLED
+#define xmlMalloc XML_GLOBAL_MACRO(xmlMalloc)
+#define xmlMallocAtomic XML_GLOBAL_MACRO(xmlMallocAtomic)
+#define xmlRealloc XML_GLOBAL_MACRO(xmlRealloc)
+#define xmlFree XML_GLOBAL_MACRO(xmlFree)
+#define xmlMemStrdup XML_GLOBAL_MACRO(xmlMemStrdup)
+#endif
+#else
+#define XML_GLOBALS_ALLOC
+/** DOC_ENABLE */
+XMLPUBVAR xmlMallocFunc xmlMalloc;
+XMLPUBVAR xmlMallocFunc xmlMallocAtomic;
+XMLPUBVAR xmlReallocFunc xmlRealloc;
+XMLPUBVAR xmlFreeFunc xmlFree;
+XMLPUBVAR xmlStrdupFunc xmlMemStrdup;
+#endif
 
 /*
  * The way to overload the existing functions.
@@ -170,7 +172,7 @@
 XMLPUBFUN char *
 	xmlMemStrdupLoc	(const char *str, const char *file, int line);
 
-
+/** DOC_DISABLE */
 #ifdef DEBUG_MEMORY_LOCATION
 /**
  * xmlMalloc:
@@ -212,17 +214,11 @@
 #define xmlMemStrdup(str) xmlMemStrdupLoc((str), __FILE__, __LINE__)
 
 #endif /* DEBUG_MEMORY_LOCATION */
+/** DOC_ENABLE */
 
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
 
-#ifndef __XML_GLOBALS_H
-#ifndef __XML_THREADS_H__
-#include <libxml/threads.h>
-#include <libxml/globals.h>
-#endif
-#endif
-
 #endif  /* __DEBUG_MEMORY_ALLOC__ */
 
diff --git a/third_party/libxml/src/include/libxml/xmlreader.h b/third_party/libxml/src/include/libxml/xmlreader.h
index 1ac1510..38e1781 100644
--- a/third_party/libxml/src/include/libxml/xmlreader.h
+++ b/third_party/libxml/src/include/libxml/xmlreader.h
@@ -10,13 +10,16 @@
 #ifndef __XML_XMLREADER_H__
 #define __XML_XMLREADER_H__
 
-#include <libxml/xmlversion.h>
 #include <libxml/tree.h>
 #include <libxml/xmlIO.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xmlversion.h>
 #ifdef LIBXML_SCHEMAS_ENABLED
 #include <libxml/relaxng.h>
 #include <libxml/xmlschemas.h>
 #endif
+/* for compatibility */
+#include <libxml/parser.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -121,6 +124,8 @@
             xmlTextReaderSetup(xmlTextReaderPtr reader,
                    xmlParserInputBufferPtr input, const char *URL,
                    const char *encoding, int options);
+XMLPUBFUN void xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader,
+                                                unsigned maxAmpl);
 
 /*
  * Iterators
diff --git a/third_party/libxml/src/include/libxml/xmlregexp.h b/third_party/libxml/src/include/libxml/xmlregexp.h
index 39a72ab33..dbc0f22 100644
--- a/third_party/libxml/src/include/libxml/xmlregexp.h
+++ b/third_party/libxml/src/include/libxml/xmlregexp.h
@@ -11,6 +11,7 @@
 #ifndef __XML_REGEXP_H__
 #define __XML_REGEXP_H__
 
+#include <libxml/xmlstring.h>
 #include <libxml/xmlversion.h>
 
 #ifdef LIBXML_REGEXP_ENABLED
@@ -36,15 +37,6 @@
 typedef struct _xmlRegExecCtxt xmlRegExecCtxt;
 typedef xmlRegExecCtxt *xmlRegExecCtxtPtr;
 
-#ifdef __cplusplus
-}
-#endif
-#include <libxml/tree.h>
-#include <libxml/dict.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*
  * The POSIX like API
  */
diff --git a/third_party/libxml/src/include/libxml/xmlsave.h b/third_party/libxml/src/include/libxml/xmlsave.h
index a744b7a..f74db25 100644
--- a/third_party/libxml/src/include/libxml/xmlsave.h
+++ b/third_party/libxml/src/include/libxml/xmlsave.h
@@ -41,6 +41,23 @@
 typedef struct _xmlSaveCtxt xmlSaveCtxt;
 typedef xmlSaveCtxt *xmlSaveCtxtPtr;
 
+/** DOC_DISABLE */
+#define XML_GLOBALS_SAVE                              \
+  XML_OP(xmlIndentTreeOutput, int, XML_EMPTY)         \
+  XML_OP(xmlTreeIndentString, const char*, XML_EMPTY) \
+  XML_OP(xmlSaveNoEmptyTags, int, XML_EMPTY)
+
+#define XML_OP XML_DECLARE_GLOBAL
+XML_GLOBALS_SAVE
+#undef XML_OP
+
+#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION)
+#define xmlIndentTreeOutput XML_GLOBAL_MACRO(xmlIndentTreeOutput)
+#define xmlTreeIndentString XML_GLOBAL_MACRO(xmlTreeIndentString)
+#define xmlSaveNoEmptyTags XML_GLOBAL_MACRO(xmlSaveNoEmptyTags)
+#endif
+/** DOC_ENABLE */
+
 XMLPUBFUN xmlSaveCtxtPtr
 		xmlSaveToFd		(int fd,
 					 const char *encoding,
@@ -79,9 +96,21 @@
 XMLPUBFUN int
 		xmlSaveSetAttrEscape	(xmlSaveCtxtPtr ctxt,
 					 xmlCharEncodingOutputFunc escape);
+
+XMLPUBFUN int xmlThrDefIndentTreeOutput(int v);
+XMLPUBFUN const char* xmlThrDefTreeIndentString(const char* v);
+XMLPUBFUN int xmlThrDefSaveNoEmptyTags(int v);
+
 #ifdef __cplusplus
 }
 #endif
+
+#else /* LIBXML_OUTPUT_ENABLED */
+
+/** DOC_DISABLE */
+#define XML_GLOBALS_SAVE
+/** DOC_ENABLE */
+
 #endif /* LIBXML_OUTPUT_ENABLED */
 #endif /* __XML_XMLSAVE_H__ */
 
diff --git a/third_party/libxml/src/include/libxml/xmlschemas.h b/third_party/libxml/src/include/libxml/xmlschemas.h
index 4d61ad0..1ad5be90 100644
--- a/third_party/libxml/src/include/libxml/xmlschemas.h
+++ b/third_party/libxml/src/include/libxml/xmlschemas.h
@@ -16,7 +16,9 @@
 
 #ifdef LIBXML_SCHEMAS_ENABLED
 
+#include <libxml/encoding.h>
 #include <libxml/tree.h>
+#include <libxml/xmlerror.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/libxml/src/include/libxml/xmlversion.h.in b/third_party/libxml/src/include/libxml/xmlversion.h.in
index db4f01b..821bbd1 100644
--- a/third_party/libxml/src/include/libxml/xmlversion.h.in
+++ b/third_party/libxml/src/include/libxml/xmlversion.h.in
@@ -524,6 +524,19 @@
 #endif
 #endif /* __GNUC__ */
 
+/** DOC_DISABLE */
+#define XML_EMPTY
+
+#ifdef LIBXML_THREAD_ENABLED
+  #define XML_DECLARE_GLOBAL(name, type, attrs) \
+    attrs XMLPUBFUN type *__##name(void);
+  #define XML_GLOBAL_MACRO(name) (*__##name())
+#else
+  #define XML_DECLARE_GLOBAL(name, type, attrs) \
+    attrs XMLPUBVAR type name;
+#endif
+/** DOC_ENABLE */
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/third_party/libxml/src/include/libxml/xpointer.h b/third_party/libxml/src/include/libxml/xpointer.h
index 12ce9edd..a526000 100644
--- a/third_party/libxml/src/include/libxml/xpointer.h
+++ b/third_party/libxml/src/include/libxml/xpointer.h
@@ -28,7 +28,7 @@
 extern "C" {
 #endif
 
-#ifdef LIBXML_XPTR_LOCS_ENABLED
+#if defined(LIBXML_XPTR_LOCS_ENABLED)
 /*
  * A Location Set
  */
@@ -105,7 +105,7 @@
 XMLPUBFUN void
 		    xmlXPtrLocationSetRemove	(xmlLocationSetPtr cur,
 						 int val);
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
+#endif /* defined(LIBXML_XPTR_LOCS_ENABLED) */
 
 /*
  * Functions.
@@ -117,7 +117,8 @@
 XMLPUBFUN xmlXPathObjectPtr
 		    xmlXPtrEval			(const xmlChar *str,
 						 xmlXPathContextPtr ctx);
-#ifdef LIBXML_XPTR_LOCS_ENABLED
+
+#if defined(LIBXML_XPTR_LOCS_ENABLED)
 XML_DEPRECATED
 XMLPUBFUN void
 		    xmlXPtrRangeToFunction	(xmlXPathParserContextPtr ctxt,
@@ -128,7 +129,7 @@
 XML_DEPRECATED
 XMLPUBFUN void
 		    xmlXPtrEvalRangePredicate	(xmlXPathParserContextPtr ctxt);
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
+#endif /* defined(LIBXML_XPTR_LOCS_ENABLED) */
 #ifdef __cplusplus
 }
 #endif
diff --git a/third_party/libxml/src/include/private/buf.h b/third_party/libxml/src/include/private/buf.h
index c18eed4..a0496e5b 100644
--- a/third_party/libxml/src/include/private/buf.h
+++ b/third_party/libxml/src/include/private/buf.h
@@ -61,10 +61,8 @@
 
 XML_HIDDEN int
 xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input);
-XML_HIDDEN size_t
-xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input);
-XML_HIDDEN int
-xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
-                      size_t base, size_t cur);
+XML_HIDDEN int xmlBufUpdateInput(xmlBufPtr buf,
+                                 xmlParserInputPtr input,
+                                 size_t pos);
 
 #endif /* XML_BUF_H_PRIVATE__ */
diff --git a/third_party/libxml/src/include/private/dict.h b/third_party/libxml/src/include/private/dict.h
index fcc10ba..ae88f37e 100644
--- a/third_party/libxml/src/include/private/dict.h
+++ b/third_party/libxml/src/include/private/dict.h
@@ -1,11 +1,54 @@
 #ifndef XML_DICT_H_PRIVATE__
 #define XML_DICT_H_PRIVATE__
 
-XML_HIDDEN int
-__xmlInitializeDict(void);
+/*
+ * Values are ANDed with 0xFFFFFFFF to support platforms where
+ * unsigned is larger than 32 bits. With 32-bit unsigned values,
+ * modern compilers should optimize the operation away.
+ */
+
+#define HASH_ROL(x, n) ((x) << (n) | ((x) & 0xFFFFFFFF) >> (32 - (n)))
+#define HASH_ROR(x, n) (((x) & 0xFFFFFFFF) >> (n) | (x) << (32 - (n)))
+
+/*
+ * GoodOAAT: One of a smallest non-multiplicative One-At-a-Time functions
+ * that passes SMHasher.
+ *
+ * Author: Sokolov Yura aka funny-falcon
+ */
+
+#define HASH_INIT(h1, h2, seed) \
+  do {                          \
+    h1 = seed ^ 0x3b00;         \
+    h2 = HASH_ROL(seed, 15);    \
+  } while (0)
+
+#define HASH_UPDATE(h1, h2, ch) \
+  do {                          \
+    h1 += ch;                   \
+    h1 += h1 << 3;              \
+    h2 += h1;                   \
+    h2 = HASH_ROL(h2, 7);       \
+    h2 += h2 << 2;              \
+  } while (0)
+
+/* Result is in h2 */
+#define HASH_FINISH(h1, h2) \
+  do {                      \
+    h1 ^= h2;               \
+    h1 += HASH_ROL(h2, 14); \
+    h2 ^= h1;               \
+    h2 += HASH_ROR(h1, 6);  \
+    h1 ^= h2;               \
+    h1 += HASH_ROL(h2, 5);  \
+    h2 ^= h1;               \
+    h2 += HASH_ROR(h1, 8);  \
+    h2 &= 0xFFFFFFFF;       \
+  } while (0)
+
+XML_HIDDEN void xmlInitDictInternal(void);
 XML_HIDDEN void
 xmlCleanupDictInternal(void);
-XML_HIDDEN int
-__xmlRandom(void);
+XML_HIDDEN unsigned xmlRandom(void);
 
 #endif /* XML_DICT_H_PRIVATE__ */
diff --git a/third_party/libxml/src/include/private/enc.h b/third_party/libxml/src/include/private/enc.h
index cbdc2b33..5a391bc5 100644
--- a/third_party/libxml/src/include/private/enc.h
+++ b/third_party/libxml/src/include/private/enc.h
@@ -7,11 +7,12 @@
 XML_HIDDEN void
 xmlInitEncodingInternal(void);
 
-XML_HIDDEN int
-xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
-                 int *outlen, const unsigned char *in, int *inlen, int flush);
-XML_HIDDEN int
-xmlCharEncInput(xmlParserInputBufferPtr input, int flush);
+XML_HIDDEN int xmlEncInputChunk(xmlCharEncodingHandler* handler,
+                                unsigned char* out,
+                                int* outlen,
+                                const unsigned char* in,
+                                int* inlen);
+XML_HIDDEN int xmlCharEncInput(xmlParserInputBufferPtr input);
 XML_HIDDEN int
 xmlCharEncOutput(xmlOutputBufferPtr output, int init);
 
diff --git a/third_party/libxml/src/include/private/error.h b/third_party/libxml/src/include/private/error.h
index 7f284f98..f88f33c 100644
--- a/third_party/libxml/src/include/private/error.h
+++ b/third_party/libxml/src/include/private/error.h
@@ -4,6 +4,8 @@
 #include <libxml/xmlerror.h>
 #include <libxml/xmlversion.h>
 
+struct _xmlNode;
+
 XML_HIDDEN void
 __xmlRaiseError(xmlStructuredErrorFunc schannel,
                 xmlGenericErrorFunc channel, void *data, void *ctx,
@@ -11,9 +13,11 @@
                 const char *file, int line, const char *str1,
                 const char *str2, const char *str3, int int1, int col,
 	        const char *msg, ...) LIBXML_ATTR_FORMAT(16,17);
-XML_HIDDEN void
-__xmlSimpleError(int domain, int code, xmlNodePtr node,
-                 const char *msg, const char *extra) LIBXML_ATTR_FORMAT(4,0);
+XML_HIDDEN void __xmlSimpleError(int domain,
+                                 int code,
+                                 struct _xmlNode* node,
+                                 const char* msg,
+                                 const char* extra) LIBXML_ATTR_FORMAT(4, 0);
 XML_HIDDEN void
 xmlGenericErrorDefaultFunc(void *ctx, const char *msg,
                            ...) LIBXML_ATTR_FORMAT(2,3);
diff --git a/third_party/libxml/src/include/private/io.h b/third_party/libxml/src/include/private/io.h
index 86a72e1..18f6938 100644
--- a/third_party/libxml/src/include/private/io.h
+++ b/third_party/libxml/src/include/private/io.h
@@ -11,6 +11,8 @@
 __xmlLoaderErr(void *ctx, const char *msg,
                const char *filename) LIBXML_ATTR_FORMAT(2,0);
 
+xmlParserInputBufferPtr xmlParserInputBufferCreateString(const xmlChar* str);
+
 #ifdef LIBXML_OUTPUT_ENABLED
 XML_HIDDEN xmlOutputBufferPtr
 xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
diff --git a/third_party/libxml/src/include/private/parser.h b/third_party/libxml/src/include/private/parser.h
index bf933f7..881900ac 100644
--- a/third_party/libxml/src/include/private/parser.h
+++ b/third_party/libxml/src/include/private/parser.h
@@ -17,10 +17,24 @@
  */
 #define XML_VCTXT_USE_PCTXT (1u << 1)
 
+#define XML_INPUT_HAS_ENCODING (1u << 0)
+#define XML_INPUT_AUTO_ENCODING (7u << 1)
+#define XML_INPUT_AUTO_UTF8 (1u << 1)
+#define XML_INPUT_AUTO_UTF16LE (2u << 1)
+#define XML_INPUT_AUTO_UTF16BE (3u << 1)
+#define XML_INPUT_AUTO_OTHER (4u << 1)
+#define XML_INPUT_USES_ENC_DECL (1u << 4)
+#define XML_INPUT_8_BIT (1u << 5)
+
 XML_HIDDEN void
 xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra);
 XML_HIDDEN void
 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
+XML_HIDDEN void LIBXML_ATTR_FORMAT(3, 0) xmlWarningMsg(xmlParserCtxtPtr ctxt,
+                                                       xmlParserErrors error,
+                                                       const char* msg,
+                                                       const xmlChar* str1,
+                                                       const xmlChar* str2);
 XML_HIDDEN void
 __xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr,
                  const char *msg, const xmlChar *str1,
@@ -32,4 +46,8 @@
 XML_HIDDEN void
 xmlParserShrink(xmlParserCtxtPtr ctxt);
 
+XML_HIDDEN void xmlDetectEncoding(xmlParserCtxtPtr ctxt);
+XML_HIDDEN void xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt,
+                                       xmlChar* encoding);
+
 #endif /* XML_PARSER_H_PRIVATE__ */
diff --git a/third_party/libxml/src/include/private/threads.h b/third_party/libxml/src/include/private/threads.h
index b337bfa..473bc7c0 100644
--- a/third_party/libxml/src/include/private/threads.h
+++ b/third_party/libxml/src/include/private/threads.h
@@ -10,9 +10,6 @@
   #elif defined(_WIN32)
     #define WIN32_LEAN_AND_MEAN
     #include <windows.h>
-    #ifndef HAVE_COMPILER_TLS
-      #include <process.h>
-    #endif
     #define HAVE_WIN32_THREADS
   #endif
 #endif
@@ -31,18 +28,6 @@
 };
 
 XML_HIDDEN void
-__xmlGlobalInitMutexLock(void);
-XML_HIDDEN void
-__xmlGlobalInitMutexUnlock(void);
-XML_HIDDEN void
-__xmlGlobalInitMutexDestroy(void);
-
-XML_HIDDEN void
-xmlInitThreadsInternal(void);
-XML_HIDDEN void
-xmlCleanupThreadsInternal(void);
-
-XML_HIDDEN void
 xmlInitMutex(xmlMutexPtr mutex);
 XML_HIDDEN void
 xmlCleanupMutex(xmlMutexPtr mutex);
diff --git a/third_party/libxml/src/libxml-2.0-uninstalled.pc.in b/third_party/libxml/src/libxml-2.0-uninstalled.pc.in
index 0c3186f..a7b81fa 100644
--- a/third_party/libxml/src/libxml-2.0-uninstalled.pc.in
+++ b/third_party/libxml/src/libxml-2.0-uninstalled.pc.in
@@ -7,7 +7,6 @@
 Name: libXML
 Version: @VERSION@
 Description: libXML library version2.
-Requires:
-Libs: -L${libdir} @XML_LIBS@
-Libs.private: @XML_PRIVATE_LIBS@ @LIBS@
+Requires@XML_PC_PRIVATE@: @XML_PC_REQUIRES@
+Libs: -L${libdir} @XML_LIBS@ @XML_PC_LIBS_PRIVATE@ @XML_PC_LIBS@ @LIBS@
 Cflags: @XML_INCLUDEDIR@ @XML_CFLAGS@
diff --git a/third_party/libxml/src/libxml-2.0.pc.in b/third_party/libxml/src/libxml-2.0.pc.in
index 88e3963..6d7b62f 100644
--- a/third_party/libxml/src/libxml-2.0.pc.in
+++ b/third_party/libxml/src/libxml-2.0.pc.in
@@ -7,7 +7,6 @@
 Name: libXML
 Version: @VERSION@
 Description: libXML library version2.
-Requires:
-Libs: -L${libdir} @XML_LIBS@
-Libs.private: @XML_PRIVATE_LIBS@ @LIBS@
+Requires@XML_PC_PRIVATE@: @XML_PC_REQUIRES@
+Libs: -L${libdir} @XML_LIBS@ @XML_PC_LIBS_PRIVATE@ @XML_PC_LIBS@ @LIBS@
 Cflags: @XML_INCLUDEDIR@ @XML_CFLAGS@
diff --git a/third_party/libxml/src/libxml2-config.cmake.cmake.in b/third_party/libxml/src/libxml2-config.cmake.cmake.in
index 27586aa..6feddfd 100644
--- a/third_party/libxml/src/libxml2-config.cmake.cmake.in
+++ b/third_party/libxml/src/libxml2-config.cmake.cmake.in
@@ -35,6 +35,7 @@
     foreach(property IN ITEMS IMPORTED_LOCATION IMPORTED_IMPLIB)
       get_target_property(${basename}_${property}_DEBUG ${target} ${property}_DEBUG)
       get_target_property(${basename}_${property}_MINSIZEREL ${target} ${property}_MINSIZEREL)
+      get_target_property(${basename}_${property}_NOCONFIG ${target} ${property}_NOCONFIG)
       get_target_property(${basename}_${property}_RELEASE ${target} ${property}_RELEASE)
       get_target_property(${basename}_${property}_RELWITHDEBINFO ${target} ${property}_RELWITHDEBINFO)
 
@@ -52,6 +53,8 @@
         set(${basename}_LIBRARY ${${basename}_${property}_MINSIZEREL})
       elseif(${basename}_${property}_DEBUG)
         set(${basename}_LIBRARY ${${basename}_${property}_DEBUG})
+      elseif(${basename}_${property}_NOCONFIG)
+        set(${basename}_LIBRARY ${${basename}_${property}_NOCONFIG})
       endif()
     endforeach()
   endif()
@@ -61,6 +64,7 @@
   if(TARGET ${target})
     get_target_property(${basename}_IMPORTED_LOCATION_DEBUG ${target} IMPORTED_LOCATION_DEBUG)
     get_target_property(${basename}_IMPORTED_LOCATION_MINSIZEREL ${target} IMPORTED_LOCATION_MINSIZEREL)
+    get_target_property(${basename}_IMPORTED_LOCATION_NOCONFIG ${target} IMPORTED_LOCATION_NOCONFIG)
     get_target_property(${basename}_IMPORTED_LOCATION_RELEASE ${target} IMPORTED_LOCATION_RELEASE)
     get_target_property(${basename}_IMPORTED_LOCATION_RELWITHDEBINFO ${target} IMPORTED_LOCATION_RELWITHDEBINFO)
 
@@ -72,6 +76,8 @@
       set(${basename}_EXECUTABLE ${${basename}_IMPORTED_LOCATION_MINSIZEREL})
     elseif(${basename}_IMPORTED_LOCATION_DEBUG)
       set(${basename}_EXECUTABLE ${${basename}_IMPORTED_LOCATION_DEBUG})
+    elseif(${basename}_IMPORTED_LOCATION_NOCONFIG)
+      set(${basename}_EXECUTABLE ${${basename}_IMPORTED_LOCATION_NOCONFIG})
     endif()
   endif()
 endmacro()
diff --git a/third_party/libxml/src/list.c b/third_party/libxml/src/list.c
index 12a7c00..4927a263 100644
--- a/third_party/libxml/src/list.c
+++ b/third_party/libxml/src/list.c
@@ -21,8 +21,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <libxml/xmlmemory.h>
+#include <libxml/xmlerror.h>
 #include <libxml/list.h>
-#include <libxml/globals.h>
 
 /*
  * Type definition are kept internal
diff --git a/third_party/libxml/src/nanoftp.c b/third_party/libxml/src/nanoftp.c
index f4e8c25..8fbe7aa 100644
--- a/third_party/libxml/src/nanoftp.c
+++ b/third_party/libxml/src/nanoftp.c
@@ -56,19 +56,10 @@
 #include <libxml/xmlerror.h>
 #include <libxml/uri.h>
 #include <libxml/nanoftp.h>
-#include <libxml/globals.h>
 
 #include "private/error.h"
 #include "private/io.h"
 
-/* #define DEBUG_FTP 1  */
-#ifdef STANDALONE
-#ifndef DEBUG_FTP
-#define DEBUG_FTP 1
-#endif
-#endif
-
-
 #if defined(_WIN32)
 #include <wsockcompat.h>
 #endif
@@ -408,14 +399,6 @@
     }
     proxyPort = 0;
 
-#ifdef DEBUG_FTP
-    if (URL == NULL)
-	xmlGenericError(xmlGenericErrorContext,
-		"Removing FTP proxy info\n");
-    else
-	xmlGenericError(xmlGenericErrorContext,
-		"Using FTP proxy %s\n", URL);
-#endif
     if (URL == NULL) return;
 
     uri = xmlParseURIRaw(URL, 1);
@@ -548,28 +531,13 @@
     if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
 
     if ((ctxt->controlBufIndex < 0) || (ctxt->controlBufIndex > FTP_BUF_SIZE)) {
-#ifdef DEBUG_FTP
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetMore : controlBufIndex = %d\n",
-		ctxt->controlBufIndex);
-#endif
 	return(-1);
     }
 
     if ((ctxt->controlBufUsed < 0) || (ctxt->controlBufUsed > FTP_BUF_SIZE)) {
-#ifdef DEBUG_FTP
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetMore : controlBufUsed = %d\n",
-		ctxt->controlBufUsed);
-#endif
 	return(-1);
     }
     if (ctxt->controlBufIndex > ctxt->controlBufUsed) {
-#ifdef DEBUG_FTP
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetMore : controlBufIndex > controlBufUsed %d > %d\n",
-	       ctxt->controlBufIndex, ctxt->controlBufUsed);
-#endif
 	return(-1);
     }
 
@@ -584,10 +552,6 @@
     }
     size = FTP_BUF_SIZE - ctxt->controlBufUsed;
     if (size == 0) {
-#ifdef DEBUG_FTP
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPGetMore : buffer full %d \n", ctxt->controlBufUsed);
-#endif
 	return(0);
     }
 
@@ -601,11 +565,6 @@
         ctxt->controlFd = INVALID_SOCKET;
         return(-1);
     }
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext,
-	    "xmlNanoFTPGetMore : read %d [%d - %d]\n", len,
-	   ctxt->controlBufUsed, ctxt->controlBufUsed + len);
-#endif
     ctxt->controlBufUsed += len;
     ctxt->controlBuf[ctxt->controlBufUsed] = 0;
 
@@ -643,10 +602,6 @@
     ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
     end = &ctxt->controlBuf[ctxt->controlBufUsed];
 
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext,
-	    "\n<<<\n%s\n--\n", ptr);
-#endif
     while (ptr < end) {
         cur = xmlNanoFTPParseResponse(ptr, end - ptr);
 	if (cur > 0) {
@@ -673,14 +628,7 @@
 
     if (res < 0) goto get_more;
     ctxt->controlBufIndex = ptr - ctxt->controlBuf;
-#ifdef DEBUG_FTP
-    ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
-    xmlGenericError(xmlGenericErrorContext, "\n---\n%s\n--\n", ptr);
-#endif
 
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "Got %d\n", res);
-#endif
     return(res / 100);
 }
 
@@ -749,9 +697,6 @@
 	snprintf(buf, sizeof(buf), "USER %s\r\n", ctxt->user);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -777,9 +722,6 @@
 	snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -808,9 +750,6 @@
 
     snprintf(buf, sizeof(buf), "QUIT\r\n");
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf); /* Just to be consistent, even though we know it can't have a % in it */
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1004,9 +943,6 @@
 	    snprintf(buf, sizeof(buf), "USER %s\r\n", proxyUser);
             buf[sizeof(buf) - 1] = 0;
             len = strlen(buf);
-#ifdef DEBUG_FTP
-	    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 	    res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 	    if (res < 0) {
 		__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1027,9 +963,6 @@
 			snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");
                     buf[sizeof(buf) - 1] = 0;
                     len = strlen(buf);
-#ifdef DEBUG_FTP
-		    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 		    res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 		    if (res < 0) {
 			__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1068,9 +1001,6 @@
 		snprintf(buf, sizeof(buf), "SITE %s\r\n", ctxt->hostname);
                 buf[sizeof(buf) - 1] = 0;
                 len = strlen(buf);
-#ifdef DEBUG_FTP
-		xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 		res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 		if (res < 0) {
 		    __xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1100,9 +1030,6 @@
 			           ctxt->user, ctxt->hostname);
                 buf[sizeof(buf) - 1] = 0;
                 len = strlen(buf);
-#ifdef DEBUG_FTP
-		xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 		res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 		if (res < 0) {
 		    __xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1122,9 +1049,6 @@
 		    snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);
                 buf[sizeof(buf) - 1] = 0;
                 len = strlen(buf);
-#ifdef DEBUG_FTP
-		xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 		res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 		if (res < 0) {
 		    __xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1273,9 +1197,6 @@
     snprintf(buf, sizeof(buf), "CWD %s\r\n", directory);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1324,9 +1245,6 @@
     snprintf(buf, sizeof(buf), "DELE %s\r\n", file);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1396,9 +1314,6 @@
 #endif
 	    snprintf (buf, sizeof(buf), "PASV\r\n");
         len = strlen (buf);
-#ifdef DEBUG_FTP
-	xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 	res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 	if (res < 0) {
 	    __xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1496,9 +1411,6 @@
 
         buf[sizeof(buf) - 1] = 0;
         len = strlen(buf);
-#ifdef DEBUG_FTP
-	xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
 
 	res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
 	if (res < 0) {
@@ -1543,17 +1455,10 @@
     FD_SET(ctxt->controlFd, &efd);
     res = select(ctxt->controlFd + 1, &rfd, NULL, &efd, &tv);
     if (res < 0) {
-#ifdef DEBUG_FTP
-	perror("select");
-#endif
 	closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
 	return(-1);
     }
     if (res == 0) {
-#ifdef DEBUG_FTP
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoFTPCloseConnection: timeout\n");
-#endif
 	closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
     } else {
 	res = xmlNanoFTPGetResponse(ctxt);
@@ -1734,9 +1639,6 @@
     }
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1758,9 +1660,6 @@
 	FD_SET(ctxt->dataFd, &efd);
 	res = select(ctxt->dataFd + 1, &rfd, NULL, &efd, &tv);
 	if (res < 0) {
-#ifdef DEBUG_FTP
-	    perror("select");
-#endif
 	    closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
 	    return(-1);
 	}
@@ -1785,9 +1684,6 @@
 	    ctxt->dataFd = INVALID_SOCKET;
 	    return(-1);
 	}
-#ifdef DEBUG_FTP
-        write(1, &buf[indx], len);
-#endif
 	indx += len;
 	buf[indx] = 0;
 	base = 0;
@@ -1829,9 +1725,6 @@
 
     snprintf(buf, sizeof(buf), "TYPE I\r\n");
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1849,9 +1742,6 @@
 	snprintf(buf, sizeof(buf), "RETR %s\r\n", filename);
     buf[sizeof(buf) - 1] = 0;
     len = strlen(buf);
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "%s", buf);
-#endif
     res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
     if (res < 0) {
 	__xmlIOErr(XML_FROM_FTP, 0, "send failed");
@@ -1903,9 +1793,6 @@
 	FD_SET(ctxt->dataFd, &rfd);
 	res = select(ctxt->dataFd + 1, &rfd, NULL, NULL, &tv);
 	if (res < 0) {
-#ifdef DEBUG_FTP
-	    perror("select");
-#endif
 	    closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
 	    return(-1);
 	}
@@ -1962,9 +1849,6 @@
 	    __xmlIOErr(XML_FROM_FTP, 0, "recv failed");
 	xmlNanoFTPCloseConnection(ctxt);
     }
-#ifdef DEBUG_FTP
-    xmlGenericError(xmlGenericErrorContext, "Recvd %d bytes\n", len);
-#endif
     return(len);
 }
 
diff --git a/third_party/libxml/src/nanohttp.c b/third_party/libxml/src/nanohttp.c
index 7c63e94..0d7af489 100644
--- a/third_party/libxml/src/nanohttp.c
+++ b/third_party/libxml/src/nanohttp.c
@@ -64,12 +64,10 @@
 #include <wsockcompat.h>
 #endif
 
-#include <libxml/globals.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h> /* for xmlStr(n)casecmp() */
 #include <libxml/nanohttp.h>
-#include <libxml/globals.h>
 #include <libxml/uri.h>
 
 #include "private/error.h"
@@ -92,7 +90,6 @@
 #define SEND_ARG2_CAST (char *)
 
 #ifdef STANDALONE
-#define DEBUG_HTTP
 #define xmlStrncasecmp(a, b, n) strncasecmp((char *)a, (char *)b, n)
 #define xmlStrcasecmpi(a, b) strcasecmp((char *)a, (char *)b)
 #endif
@@ -328,14 +325,6 @@
     }
     proxyPort = 0;
 
-#ifdef DEBUG_HTTP
-    if (URL == NULL)
-	xmlGenericError(xmlGenericErrorContext,
-		"Removing HTTP proxy info\n");
-    else
-	xmlGenericError(xmlGenericErrorContext,
-		"Using HTTP proxy %s\n", URL);
-#endif
     if (URL == NULL) return;
 
     uri = xmlParseURIRaw(URL, 1);
@@ -854,9 +843,6 @@
         addrlen = sizeof(struct sockaddr_in);
     }
     if (s == INVALID_SOCKET) {
-#ifdef DEBUG_HTTP
-        perror("socket");
-#endif
         __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n");
         return INVALID_SOCKET;
     }
@@ -885,9 +871,6 @@
         status = fcntl(s, F_SETFL, status);
     }
     if (status < 0) {
-#ifdef DEBUG_HTTP
-        perror("nonblocking");
-#endif
         __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n");
         closesocket(s);
         return INVALID_SOCKET;
@@ -1137,11 +1120,6 @@
     }
 #endif
 
-#ifdef DEBUG_HTTP
-    xmlGenericError(xmlGenericErrorContext,
-                    "xmlNanoHTTPConnectHost:  unable to connect to '%s'.\n",
-                    host);
-#endif
     return INVALID_SOCKET;
 }
 
@@ -1392,9 +1370,6 @@
     int nbRedirects = 0;
     int use_proxy;
     char *redirURL = NULL;
-#ifdef DEBUG_HTTP
-    int xmt_bytes;
-#endif
 
     if (URL == NULL) return(NULL);
     if (method == NULL) method = "GET";
@@ -1514,41 +1489,13 @@
     else
 	snprintf(p, blen - (p - bp), "\r\n");
 
-#ifdef DEBUG_HTTP
-    xmlGenericError(xmlGenericErrorContext,
-	    "-> %s%s", use_proxy ? "(Proxy) " : "", bp);
-    if ((blen -= strlen(bp)+1) < 0)
-	xmlGenericError(xmlGenericErrorContext,
-		"ERROR: overflowed buffer by %d bytes\n", -blen);
-#endif
     ctxt->outptr = ctxt->out = bp;
     ctxt->state = XML_NANO_HTTP_WRITE;
     blen = strlen( ctxt->out );
-#ifdef DEBUG_HTTP
-    xmt_bytes = xmlNanoHTTPSend(ctxt, ctxt->out, blen );
-    if ( xmt_bytes != blen )
-        xmlGenericError( xmlGenericErrorContext,
-			"xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
-			xmt_bytes, blen,
-			"bytes of HTTP headers sent to host",
-			ctxt->hostname );
-#else
     xmlNanoHTTPSend(ctxt, ctxt->out, blen );
-#endif
 
     if ( input != NULL ) {
-#ifdef DEBUG_HTTP
-        xmt_bytes = xmlNanoHTTPSend( ctxt, input, ilen );
-
-	if ( xmt_bytes != ilen )
-	    xmlGenericError( xmlGenericErrorContext,
-			"xmlNanoHTTPMethodRedir:  Only %d of %d %s %s\n",
-			xmt_bytes, ilen,
-			"bytes of HTTP content sent to host",
-			ctxt->hostname );
-#else
 	xmlNanoHTTPSend( ctxt, input, ilen );
-#endif
     }
 
     ctxt->state = XML_NANO_HTTP_READ;
@@ -1561,18 +1508,11 @@
 	}
 	xmlNanoHTTPScanAnswer(ctxt, p);
 
-#ifdef DEBUG_HTTP
-	xmlGenericError(xmlGenericErrorContext, "<- %s\n", p);
-#endif
         xmlFree(p);
     }
 
     if ((ctxt->location != NULL) && (ctxt->returnValue >= 300) &&
         (ctxt->returnValue < 400)) {
-#ifdef DEBUG_HTTP
-	xmlGenericError(xmlGenericErrorContext,
-		"\nRedirect to: %s\n", ctxt->location);
-#endif
 	while ( xmlNanoHTTPRecv(ctxt) > 0 )
             ;
         if (nbRedirects < XML_NANO_HTTP_MAX_REDIR) {
@@ -1585,10 +1525,6 @@
 	}
 	xmlNanoHTTPFreeCtxt(ctxt);
 	if (redirURL != NULL) xmlFree(redirURL);
-#ifdef DEBUG_HTTP
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlNanoHTTPMethodRedir: Too many redirects, aborting ...\n");
-#endif
 	return(NULL);
     }
 
@@ -1608,17 +1544,6 @@
 	    *redir = NULL;
     }
 
-#ifdef DEBUG_HTTP
-    if (ctxt->contentType != NULL)
-	xmlGenericError(xmlGenericErrorContext,
-		"\nCode %d, content-type '%s'\n\n",
-	       ctxt->returnValue, ctxt->contentType);
-    else
-	xmlGenericError(xmlGenericErrorContext,
-		"\nCode %d, no content-type\n\n",
-	       ctxt->returnValue);
-#endif
-
     return((void *) ctxt);
 }
 
diff --git a/third_party/libxml/src/parser.c b/third_party/libxml/src/parser.c
index 0f225fb..e3e93ea7 100644
--- a/third_party/libxml/src/parser.c
+++ b/third_party/libxml/src/parser.c
@@ -51,42 +51,27 @@
 #include <stddef.h>
 #include <ctype.h>
 #include <stdlib.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/threads.h>
-#include <libxml/globals.h>
-#include <libxml/tree.h>
 #include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
 #include <libxml/parserInternals.h>
-#include <libxml/HTMLparser.h>
 #include <libxml/valid.h>
 #include <libxml/entities.h>
 #include <libxml/xmlerror.h>
 #include <libxml/encoding.h>
 #include <libxml/xmlIO.h>
 #include <libxml/uri.h>
+#include <libxml/SAX2.h>
 #ifdef LIBXML_CATALOG_ENABLED
 #include <libxml/catalog.h>
 #endif
-#ifdef LIBXML_SCHEMAS_ENABLED
-#include <libxml/xmlschemastypes.h>
-#include <libxml/relaxng.h>
-#endif
-#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-#include <libxml/xpath.h>
-#endif
 
 #include "private/buf.h"
-#include "private/dict.h"
-#include "private/enc.h"
 #include "private/entities.h"
 #include "private/error.h"
-#include "private/globals.h"
 #include "private/html.h"
 #include "private/io.h"
-#include "private/memory.h"
 #include "private/parser.h"
-#include "private/threads.h"
-#include "private/xpath.h"
 
 struct _xmlStartTag {
     const xmlChar *prefix;
@@ -121,13 +106,7 @@
  */
 
 /*
- * XML_PARSER_NON_LINEAR is roughly the maximum allowed amplification factor
- * of serialized output after entity expansion.
- */
-#define XML_PARSER_NON_LINEAR 5
-
-/*
- * A certain amount is always allowed.
+ * A certain amount of entity expansion which is always allowed.
  */
 #define XML_PARSER_ALLOWED_EXPANSION 1000000
 
@@ -166,6 +145,14 @@
  */
 #define XML_PARSER_CHUNK_SIZE 100
 
+/**
+ * xmlParserVersion:
+ *
+ * Constant string describing the internal version of the library
+ */
+const char *const
+xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA;
+
 /*
  * List of XML prefixed PI allowed by W3C specs
  */
@@ -281,7 +268,7 @@
  *
  * Handle a warning.
  */
-static void LIBXML_ATTR_FORMAT(3,0)
+void LIBXML_ATTR_FORMAT(3,0)
 xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
@@ -590,9 +577,10 @@
      */
     if ((ctxt->sizeentcopy > XML_PARSER_ALLOWED_EXPANSION) &&
         ((ctxt->sizeentcopy >= ULONG_MAX) ||
-         (ctxt->sizeentcopy / XML_PARSER_NON_LINEAR > consumed))) {
+         (ctxt->sizeentcopy / ctxt->maxAmpl > consumed))) {
         xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP,
-                       "Maximum entity amplification factor exceeded");
+                       "Maximum entity amplification factor exceeded, see "
+                       "xmlCtxtSetMaxAmplification.\n");
         xmlHaltParser(ctxt);
         return(1);
     }
@@ -2313,6 +2301,7 @@
 	    return;
         case XML_PARSER_PROLOG:
 	case XML_PARSER_START:
+	case XML_PARSER_XML_DECL:
 	case XML_PARSER_MISC:
 	    xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
 	    return;
@@ -2901,14 +2890,6 @@
  *	Routines to parse Name, NCName and NmToken			*
  *									*
  ************************************************************************/
-#ifdef DEBUG
-static unsigned long nbParseName = 0;
-static unsigned long nbParseNmToken = 0;
-static unsigned long nbParseNCName = 0;
-static unsigned long nbParseNCNameComplex = 0;
-static unsigned long nbParseNameComplex = 0;
-static unsigned long nbParseStringName = 0;
-#endif
 
 /*
  * The two following functions are related to the change of accepted
@@ -3001,10 +2982,6 @@
                     XML_MAX_TEXT_LENGTH :
                     XML_MAX_NAME_LENGTH;
 
-#ifdef DEBUG
-    nbParseNameComplex++;
-#endif
-
     /*
      * Handler for more complex cases
      */
@@ -3135,10 +3112,6 @@
     if (ctxt->instate == XML_PARSER_EOF)
         return(NULL);
 
-#ifdef DEBUG
-    nbParseName++;
-#endif
-
     /*
      * Accelerator for simple ASCII names
      */
@@ -3180,10 +3153,6 @@
                     XML_MAX_NAME_LENGTH;
     size_t startPosition = 0;
 
-#ifdef DEBUG
-    nbParseNCNameComplex++;
-#endif
-
     /*
      * Handler for more complex cases
      */
@@ -3234,10 +3203,6 @@
                        XML_MAX_TEXT_LENGTH :
                        XML_MAX_NAME_LENGTH;
 
-#ifdef DEBUG
-    nbParseNCName++;
-#endif
-
     /*
      * Accelerator for simple ASCII names
      */
@@ -3343,10 +3308,6 @@
                     XML_MAX_TEXT_LENGTH :
                     XML_MAX_NAME_LENGTH;
 
-#ifdef DEBUG
-    nbParseStringName++;
-#endif
-
     c = CUR_SCHAR(cur, l);
     if (!xmlIsNameStartChar(ctxt, c)) {
 	return(NULL);
@@ -3432,10 +3393,6 @@
                     XML_MAX_TEXT_LENGTH :
                     XML_MAX_NAME_LENGTH;
 
-#ifdef DEBUG
-    nbParseNmToken++;
-#endif
-
     c = CUR_CHAR(l);
 
     while (xmlIsNameChar(ctxt, c)) {
@@ -4275,6 +4232,8 @@
                 line = ctxt->input->line;
                 col = ctxt->input->col;
             }
+            if (ctxt->instate == XML_PARSER_EOF)
+                return;
         }
         ctxt->input->cur = in;
         if (*in == 0xD) {
@@ -6680,7 +6639,6 @@
 void
 xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
     xmlChar *version;
-    const xmlChar *encoding;
     int oldstate;
 
     /*
@@ -6719,7 +6677,7 @@
     /*
      * We must have the encoding declaration
      */
-    encoding = xmlParseEncodingDecl(ctxt);
+    xmlParseEncodingDecl(ctxt);
     if (ctxt->instate == XML_PARSER_EOF)
         return;
     if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
@@ -6729,10 +6687,6 @@
         ctxt->instate = oldstate;
         return;
     }
-    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
-	xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
-		       "Missing encoding in text declaration\n");
-    }
 
     SKIP_BLANKS;
     if ((RAW == '?') && (NXT(1) == '>')) {
@@ -6771,21 +6725,8 @@
 xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
                        const xmlChar *SystemID) {
     xmlDetectSAX2(ctxt);
-    GROW;
 
-    if ((ctxt->encoding == NULL) &&
-        (ctxt->input->end - ctxt->input->cur >= 4)) {
-        xmlChar start[4];
-	xmlCharEncoding enc;
-
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(start, 4);
-	if (enc != XML_CHAR_ENCODING_NONE)
-	    xmlSwitchEncoding(ctxt, enc);
-    }
+    xmlDetectEncoding(ctxt);
 
     if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
 	xmlParseTextDecl(ctxt);
@@ -6865,42 +6806,19 @@
     if (NXT(1) == '#') {
 	int i = 0;
 	xmlChar out[16];
-	int hex = NXT(2);
 	int value = xmlParseCharRef(ctxt);
 
 	if (value == 0)
 	    return;
-	if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
-	    /*
-	     * So we are using non-UTF-8 buffers
-	     * Check that the char fit on 8bits, if not
-	     * generate a CharRef.
-	     */
-	    if (value <= 0xFF) {
-		out[0] = value;
-		out[1] = 0;
-		if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
-		    (!ctxt->disableSAX))
-		    ctxt->sax->characters(ctxt->userData, out, 1);
-	    } else {
-		if ((hex == 'x') || (hex == 'X'))
-		    snprintf((char *)out, sizeof(out), "#x%X", value);
-		else
-		    snprintf((char *)out, sizeof(out), "#%d", value);
-		if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
-		    (!ctxt->disableSAX))
-		    ctxt->sax->reference(ctxt->userData, out);
-	    }
-	} else {
-	    /*
-	     * Just encode the value in UTF-8
-	     */
-	    COPY_BUF(0 ,out, i, value);
-	    out[i] = 0;
-	    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
-		(!ctxt->disableSAX))
-		ctxt->sax->characters(ctxt->userData, out, i);
-	}
+
+        /*
+         * Just encode the value in UTF-8
+         */
+        COPY_BUF(0, out, i, value);
+        out[i] = 0;
+        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
+            (!ctxt->disableSAX))
+            ctxt->sax->characters(ctxt->userData, out, i);
 	return;
     }
 
@@ -7748,8 +7666,6 @@
 		  "Internal: %%%s; is not a parameter entity\n",
 			  name, NULL);
 	} else {
-            xmlChar start[4];
-            xmlCharEncoding enc;
             unsigned long parentConsumed;
             xmlEntityPtr oldEnt;
 
@@ -7790,28 +7706,7 @@
             input->parentConsumed = parentConsumed;
 
 	    if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
-                /*
-                 * Get the 4 first bytes and decode the charset
-                 * if enc != XML_CHAR_ENCODING_NONE
-                 * plug some encoding conversion routines.
-                 * Note that, since we may have some non-UTF8
-                 * encoding (like UTF16, bug 135229), the 'length'
-                 * is not known, but we can calculate based upon
-                 * the amount of data in the buffer.
-                 */
-                GROW
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return;
-                if ((ctxt->input->end - ctxt->input->cur)>=4) {
-                    start[0] = RAW;
-                    start[1] = NXT(1);
-                    start[2] = NXT(2);
-                    start[3] = NXT(3);
-                    enc = xmlDetectCharEncoding(start, 4);
-                    if (enc != XML_CHAR_ENCODING_NONE) {
-                        xmlSwitchEncoding(ctxt, enc);
-                    }
-                }
+                xmlDetectEncoding(ctxt);
 
                 if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
                     (IS_BLANK_CH(NXT(5)))) {
@@ -7836,9 +7731,11 @@
  */
 static int
 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
-    xmlParserInputPtr input;
-    xmlBufferPtr buf;
-    int l, c;
+    xmlParserInputPtr input = NULL;
+    xmlChar *content = NULL;
+    size_t length, i;
+    int ret = -1;
+    int res;
 
     if ((ctxt == NULL) || (entity == NULL) ||
         ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
@@ -7853,61 +7750,54 @@
 	xmlGenericError(xmlGenericErrorContext,
 		"Reading %s entity content input\n", entity->name);
 
-    buf = xmlBufferCreate();
-    if (buf == NULL) {
-	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-	            "xmlLoadEntityContent parameter error");
-        return(-1);
-    }
-    xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
-
-    input = xmlNewEntityInputStream(ctxt, entity);
+    input = xmlLoadExternalEntity((char *) entity->URI,
+           (char *) entity->ExternalID, ctxt);
     if (input == NULL) {
 	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
 	            "xmlLoadEntityContent input error");
-	xmlBufferFree(buf);
         return(-1);
     }
 
-    /*
-     * Push the entity as the current input, read char by char
-     * saving to the buffer until the end of the entity or an error
-     */
-    if (xmlPushInput(ctxt, input) < 0) {
-        xmlBufferFree(buf);
-	xmlFreeInputStream(input);
-	return(-1);
+    while ((res = xmlParserInputBufferGrow(input->buf, 16384)) > 0)
+        ;
+
+    if (res < 0) {
+        xmlFatalErr(ctxt, input->buf->error, NULL);
+        goto error;
     }
 
-    GROW;
-    c = CUR_CHAR(l);
-    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
-           (IS_CHAR(c))) {
-        xmlBufferAdd(buf, ctxt->input->cur, l);
-	NEXTL(l);
-	c = CUR_CHAR(l);
-    }
-    if (ctxt->instate == XML_PARSER_EOF) {
-	xmlBufferFree(buf);
-	return(-1);
+    length = xmlBufUse(input->buf->buffer);
+    content = xmlBufDetach(input->buf->buffer);
+
+    if (length > INT_MAX) {
+        xmlErrMemory(ctxt, NULL);
+        goto error;
     }
 
-    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
-        xmlSaturatedAdd(&ctxt->sizeentities, ctxt->input->consumed);
-        xmlPopInput(ctxt);
-    } else if (!IS_CHAR(c)) {
-        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
-                          "xmlLoadEntityContent: invalid char value %d\n",
-	                  c);
-	xmlBufferFree(buf);
-	return(-1);
-    }
-    entity->content = buf->content;
-    entity->length = buf->use;
-    buf->content = NULL;
-    xmlBufferFree(buf);
+    for (i = 0; i < length; ) {
+        int clen = length - i;
+        int c = xmlGetUTF8Char(content + i, &clen);
 
-    return(0);
+        if ((c < 0) || (!IS_CHAR(c))) {
+            xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+                              "xmlLoadEntityContent: invalid char value %d\n",
+                              content[i]);
+            goto error;
+        }
+        i += clen;
+    }
+
+    xmlSaturatedAdd(&ctxt->sizeentities, length);
+    entity->content = content;
+    entity->length = length;
+    content = NULL;
+    ret = 0;
+
+error:
+    xmlFree(content);
+    xmlFreeInputStream(input);
+
+    return(ret);
 }
 
 /**
@@ -9215,19 +9105,21 @@
             ctxt->attallocs[nratts++] = alloc;
             atts[nbatts++] = attname;
             atts[nbatts++] = aprefix;
-            /*
-             * The namespace URI field is used temporarily to point at the
-             * base of the current input buffer for non-alloced attributes.
-             * When the input buffer is reallocated, all the pointers become
-             * invalid, but they can be reconstructed later.
-             */
-            if (alloc)
-                atts[nbatts++] = NULL;
-            else
-                atts[nbatts++] = ctxt->input->base;
-            atts[nbatts++] = attvalue;
-            attvalue += len;
-            atts[nbatts++] = attvalue;
+            atts[nbatts++] = NULL;
+            if (alloc) {
+                atts[nbatts++] = attvalue;
+                attvalue += len;
+                atts[nbatts++] = attvalue;
+            } else {
+                /*
+                 * attvalue points into the input buffer which can be
+                 * reallocated. Store differences to input->base instead.
+                 * The pointers will be reconstructed later.
+                 */
+                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
+                attvalue += len;
+                atts[nbatts++] = (void *) (attvalue - BASE_PTR);
+            }
             /*
              * tag if some deallocation is needed
              */
@@ -9263,15 +9155,9 @@
 
     /* Reconstruct attribute value pointers. */
     for (i = 0, j = 0; j < nratts; i += 5, j++) {
-        if (atts[i+2] != NULL) {
-            /*
-             * Arithmetic on dangling pointers is technically undefined
-             * behavior, but well...
-             */
-            const xmlChar *old = atts[i+2];
-            atts[i+2]  = NULL;    /* Reset repurposed namespace URI */
-            atts[i+3] = ctxt->input->base + (atts[i+3] - old);  /* value */
-            atts[i+4] = ctxt->input->base + (atts[i+4] - old);  /* valuend */
+        if (ctxt->attallocs[j] == 0) {
+            atts[i+3] = BASE_PTR + (ptrdiff_t) atts[i+3];  /* value */
+            atts[i+4] = BASE_PTR + (ptrdiff_t) atts[i+4];  /* valuend */
         }
     }
 
@@ -9624,7 +9510,7 @@
     int nameNr = ctxt->nameNr;
 
     GROW;
-    while ((RAW != 0) &&
+    while ((ctxt->input->cur < ctxt->input->end) &&
 	   (ctxt->instate != XML_PARSER_EOF)) {
 	const xmlChar *cur = ctxt->input->cur;
 
@@ -9701,7 +9587,9 @@
 
     xmlParseContentInternal(ctxt);
 
-    if ((ctxt->instate != XML_PARSER_EOF) && (ctxt->nameNr > nameNr)) {
+    if ((ctxt->instate != XML_PARSER_EOF) &&
+        (ctxt->errNo == XML_ERR_OK) &&
+        (ctxt->nameNr > nameNr)) {
         const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
         int line = ctxt->pushTab[ctxt->nameNr - 1].line;
         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
@@ -9735,12 +9623,14 @@
     if (ctxt->instate == XML_PARSER_EOF)
 	return;
 
-    if (CUR == 0) {
-        const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
-        int line = ctxt->pushTab[ctxt->nameNr - 1].line;
-        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
-                "Premature end of data in tag %s line %d\n",
-		name, line, NULL);
+    if (ctxt->input->cur >= ctxt->input->end) {
+        if (ctxt->errNo == XML_ERR_OK) {
+            const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
+            int line = ctxt->pushTab[ctxt->nameNr - 1].line;
+            xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
+                    "Premature end of data in tag %s line %d\n",
+                    name, line, NULL);
+        }
         return;
     }
 
@@ -10115,101 +10005,45 @@
     xmlChar *encoding = NULL;
 
     SKIP_BLANKS;
-    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
-	SKIP(8);
-	SKIP_BLANKS;
-	if (RAW != '=') {
-	    xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
-	    return(NULL);
-        }
-	NEXT;
-	SKIP_BLANKS;
-	if (RAW == '"') {
-	    NEXT;
-	    encoding = xmlParseEncName(ctxt);
-	    if (RAW != '"') {
-		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
-		xmlFree((xmlChar *) encoding);
-		return(NULL);
-	    } else
-	        NEXT;
-	} else if (RAW == '\''){
-	    NEXT;
-	    encoding = xmlParseEncName(ctxt);
-	    if (RAW != '\'') {
-		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
-		xmlFree((xmlChar *) encoding);
-		return(NULL);
-	    } else
-	        NEXT;
-	} else {
-	    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
-	}
+    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g') == 0)
+        return(NULL);
 
-        /*
-         * Non standard parsing, allowing the user to ignore encoding
-         */
-        if (ctxt->options & XML_PARSE_IGNORE_ENC) {
-	    xmlFree((xmlChar *) encoding);
-            return(NULL);
-	}
-
-	/*
-	 * UTF-16 encoding switch has already taken place at this stage,
-	 * more over the little-endian/big-endian selection is already done
-	 */
-        if ((encoding != NULL) &&
-	    ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
-	     (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
-	    /*
-	     * If no encoding was passed to the parser, that we are
-	     * using UTF-16 and no decoder is present i.e. the
-	     * document is apparently UTF-8 compatible, then raise an
-	     * encoding mismatch fatal error
-	     */
-	    if ((ctxt->encoding == NULL) &&
-	        (ctxt->input->buf != NULL) &&
-	        (ctxt->input->buf->encoder == NULL)) {
-		xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
-		  "Document labelled UTF-16 but has UTF-8 content\n");
-	    }
-	    if (ctxt->encoding != NULL)
-		xmlFree((xmlChar *) ctxt->encoding);
-	    ctxt->encoding = encoding;
-	}
-	/*
-	 * UTF-8 encoding is handled natively
-	 */
-        else if ((encoding != NULL) &&
-	    ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
-	     (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
-            /* TODO: Check for encoding mismatch. */
-	    if (ctxt->encoding != NULL)
-		xmlFree((xmlChar *) ctxt->encoding);
-	    ctxt->encoding = encoding;
-	}
-	else if (encoding != NULL) {
-	    xmlCharEncodingHandlerPtr handler;
-
-	    if (ctxt->input->encoding != NULL)
-		xmlFree((xmlChar *) ctxt->input->encoding);
-	    ctxt->input->encoding = encoding;
-
-            handler = xmlFindCharEncodingHandler((const char *) encoding);
-	    if (handler != NULL) {
-		if (xmlSwitchToEncoding(ctxt, handler) < 0) {
-		    /* failed to convert */
-		    ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
-		    return(NULL);
-		}
-	    } else {
-		xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-			"Unsupported encoding %s\n", encoding);
-		return(NULL);
-	    }
-	}
+    SKIP(8);
+    SKIP_BLANKS;
+    if (RAW != '=') {
+        xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
+        return(NULL);
     }
-    return(encoding);
+    NEXT;
+    SKIP_BLANKS;
+    if (RAW == '"') {
+        NEXT;
+        encoding = xmlParseEncName(ctxt);
+        if (RAW != '"') {
+            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+            xmlFree((xmlChar *) encoding);
+            return(NULL);
+        } else
+            NEXT;
+    } else if (RAW == '\''){
+        NEXT;
+        encoding = xmlParseEncName(ctxt);
+        if (RAW != '\'') {
+            xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+            xmlFree((xmlChar *) encoding);
+            return(NULL);
+        } else
+            NEXT;
+    } else {
+        xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
+    }
+
+    if (encoding == NULL)
+        return(NULL);
+
+    xmlSetDeclaredEncoding(ctxt, encoding);
+
+    return(ctxt->encoding);
 }
 
 /**
@@ -10318,7 +10152,8 @@
      * XML declaration but it does not have a standalone attribute.
      * It will be overwritten later if a standalone attribute is found.
      */
-    ctxt->input->standalone = -2;
+
+    ctxt->standalone = -2;
 
     /*
      * We know that '<?xml' is here.
@@ -10385,7 +10220,7 @@
     /*
      * We may have the standalone status.
      */
-    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
+    if ((ctxt->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
         if ((RAW == '?') && (NXT(1) == '>')) {
 	    SKIP(2);
 	    return;
@@ -10399,7 +10234,7 @@
     GROW;
 
     SKIP_BLANKS;
-    ctxt->input->standalone = xmlParseSDDecl(ctxt);
+    ctxt->standalone = xmlParseSDDecl(ctxt);
 
     SKIP_BLANKS;
     if ((RAW == '?') && (NXT(1) == '>')) {
@@ -10463,9 +10298,6 @@
 
 int
 xmlParseDocument(xmlParserCtxtPtr ctxt) {
-    xmlChar start[4];
-    xmlCharEncoding enc;
-
     xmlInitParser();
 
     if ((ctxt == NULL) || (ctxt->input == NULL))
@@ -10486,23 +10318,7 @@
     if (ctxt->instate == XML_PARSER_EOF)
 	return(-1);
 
-    if ((ctxt->encoding == NULL) &&
-        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
-	/*
-	 * Get the 4 first bytes and decode the charset
-	 * if enc != XML_CHAR_ENCODING_NONE
-	 * plug some encoding conversion routines.
-	 */
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(&start[0], 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-    }
-
+    xmlDetectEncoding(ctxt);
 
     if (CUR == 0) {
 	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
@@ -10523,7 +10339,6 @@
 	     */
 	    return(-1);
 	}
-	ctxt->standalone = ctxt->input->standalone;
 	SKIP_BLANKS;
     } else {
 	ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
@@ -10594,9 +10409,15 @@
 	 */
 	xmlParseMisc(ctxt);
 
-	if (RAW != 0) {
-	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-	}
+        if (ctxt->input->cur < ctxt->input->end) {
+            if (ctxt->errNo == XML_ERR_OK)
+	        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+        } else if ((ctxt->input->buf != NULL) &&
+                   (ctxt->input->buf->encoder != NULL) &&
+                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
+            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
+                           "Truncated multi-byte sequence at EOF\n");
+        }
 	ctxt->instate = XML_PARSER_EOF;
     }
 
@@ -10647,38 +10468,18 @@
 
 int
 xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
-    xmlChar start[4];
-    xmlCharEncoding enc;
-
     if ((ctxt == NULL) || (ctxt->input == NULL))
         return(-1);
 
     xmlDetectSAX2(ctxt);
 
-    GROW;
-
     /*
      * SAX: beginning of the document processing.
      */
     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
 
-    /*
-     * Get the 4 first bytes and decode the charset
-     * if enc != XML_CHAR_ENCODING_NONE
-     * plug some encoding conversion routines.
-     */
-    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(start, 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-    }
-
+    xmlDetectEncoding(ctxt);
 
     if (CUR == 0) {
 	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
@@ -11089,59 +10890,6 @@
     if (ctxt->input == NULL)
         return(0);
 
-#ifdef DEBUG_PUSH
-    switch (ctxt->instate) {
-	case XML_PARSER_EOF:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try EOF\n"); break;
-	case XML_PARSER_START:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try START\n"); break;
-	case XML_PARSER_MISC:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try MISC\n");break;
-	case XML_PARSER_COMMENT:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try COMMENT\n");break;
-	case XML_PARSER_PROLOG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try PROLOG\n");break;
-	case XML_PARSER_START_TAG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try START_TAG\n");break;
-	case XML_PARSER_CONTENT:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try CONTENT\n");break;
-	case XML_PARSER_CDATA_SECTION:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try CDATA_SECTION\n");break;
-	case XML_PARSER_END_TAG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try END_TAG\n");break;
-	case XML_PARSER_ENTITY_DECL:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try ENTITY_DECL\n");break;
-	case XML_PARSER_ENTITY_VALUE:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try ENTITY_VALUE\n");break;
-	case XML_PARSER_ATTRIBUTE_VALUE:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try ATTRIBUTE_VALUE\n");break;
-	case XML_PARSER_DTD:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try DTD\n");break;
-	case XML_PARSER_EPILOG:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try EPILOG\n");break;
-	case XML_PARSER_PI:
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PP: try PI\n");break;
-        case XML_PARSER_IGNORE:
-            xmlGenericError(xmlGenericErrorContext,
-		    "PP: try IGNORE\n");break;
-    }
-#endif
-
     if ((ctxt->input != NULL) &&
         (ctxt->input->cur - ctxt->input->base > 4096)) {
         xmlParserShrink(ctxt);
@@ -11151,30 +10899,6 @@
 	if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
 	    return(0);
 
-	if (ctxt->input == NULL) break;
-	if (ctxt->input->buf != NULL) {
-	    /*
-	     * If we are operating on converted input, try to flush
-	     * remaining chars to avoid them stalling in the non-converted
-	     * buffer.
-	     */
-	    if ((ctxt->input->buf->raw != NULL) &&
-		(xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
-                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
-                                                 ctxt->input);
-		size_t current = ctxt->input->cur - ctxt->input->base;
-                int res;
-
-		res = xmlParserInputBufferPush(ctxt->input->buf, 0, "");
-                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
-                                      base, current);
-                if (res < 0) {
-                    xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
-                    xmlHaltParser(ctxt);
-                    return(0);
-                }
-	    }
-	}
         avail = ctxt->input->end - ctxt->input->cur;
         if (avail < 1)
 	    goto done;
@@ -11185,75 +10909,41 @@
 		 */
 	        goto done;
             case XML_PARSER_START:
-		if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
-		    xmlChar start[4];
-		    xmlCharEncoding enc;
+                /*
+                 * Very first chars read from the document flow.
+                 */
+                if ((!terminate) && (avail < 4))
+                    goto done;
 
-		    /*
-		     * Very first chars read from the document flow.
-		     */
-		    if (avail < 4)
-			goto done;
+                /*
+                 * We need more bytes to detect EBCDIC code pages.
+                 * See xmlDetectEBCDIC.
+                 */
+                if ((CMP4(CUR_PTR, 0x4C, 0x6F, 0xA7, 0x94)) &&
+                    (!terminate) && (avail < 200))
+                    goto done;
 
-		    /*
-		     * Get the 4 first bytes and decode the charset
-		     * if enc != XML_CHAR_ENCODING_NONE
-		     * plug some encoding conversion routines,
-		     * else xmlSwitchEncoding will set to (default)
-		     * UTF8.
-		     */
-		    start[0] = RAW;
-		    start[1] = NXT(1);
-		    start[2] = NXT(2);
-		    start[3] = NXT(3);
-		    enc = xmlDetectCharEncoding(start, 4);
-                    /*
-                     * We need more bytes to detect EBCDIC code pages.
-                     * See xmlDetectEBCDIC.
-                     */
-                    if ((enc == XML_CHAR_ENCODING_EBCDIC) &&
-                        (!terminate) && (avail < 200))
-                        goto done;
-		    xmlSwitchEncoding(ctxt, enc);
-		    break;
-		}
+                xmlDetectEncoding(ctxt);
+                if (ctxt->instate == XML_PARSER_EOF)
+                    goto done;
+                ctxt->instate = XML_PARSER_XML_DECL;
+		break;
 
-		if (avail < 2)
+            case XML_PARSER_XML_DECL:
+		if ((!terminate) && (avail < 2))
 		    goto done;
 		cur = ctxt->input->cur[0];
 		next = ctxt->input->cur[1];
-		if (cur == 0) {
-		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-			ctxt->sax->setDocumentLocator(ctxt->userData,
-						      &xmlDefaultSAXLocator);
-		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
-		    xmlHaltParser(ctxt);
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering EOF\n");
-#endif
-		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-			ctxt->sax->endDocument(ctxt->userData);
-		    goto done;
-		}
 	        if ((cur == '<') && (next == '?')) {
 		    /* PI or XML decl */
-		    if (avail < 5) goto done;
 		    if ((!terminate) &&
                         (!xmlParseLookupString(ctxt, 2, "?>", 2)))
 			goto done;
-		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-			ctxt->sax->setDocumentLocator(ctxt->userData,
-						      &xmlDefaultSAXLocator);
 		    if ((ctxt->input->cur[2] == 'x') &&
 			(ctxt->input->cur[3] == 'm') &&
 			(ctxt->input->cur[4] == 'l') &&
 			(IS_BLANK_CH(ctxt->input->cur[5]))) {
 			ret += 5;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: Parsing XML Decl\n");
-#endif
 			xmlParseXMLDecl(ctxt);
 			if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
 			    /*
@@ -11263,47 +10953,25 @@
 			    xmlHaltParser(ctxt);
 			    return(0);
 			}
-			ctxt->standalone = ctxt->input->standalone;
-			if ((ctxt->encoding == NULL) &&
-			    (ctxt->input->encoding != NULL))
-			    ctxt->encoding = xmlStrdup(ctxt->input->encoding);
-			if ((ctxt->sax) && (ctxt->sax->startDocument) &&
-			    (!ctxt->disableSAX))
-			    ctxt->sax->startDocument(ctxt->userData);
-			ctxt->instate = XML_PARSER_MISC;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: entering MISC\n");
-#endif
 		    } else {
 			ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
-			if ((ctxt->sax) && (ctxt->sax->startDocument) &&
-			    (!ctxt->disableSAX))
-			    ctxt->sax->startDocument(ctxt->userData);
-			ctxt->instate = XML_PARSER_MISC;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: entering MISC\n");
-#endif
 		    }
 		} else {
-		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
-			ctxt->sax->setDocumentLocator(ctxt->userData,
-						      &xmlDefaultSAXLocator);
 		    ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
 		    if (ctxt->version == NULL) {
 		        xmlErrMemory(ctxt, NULL);
 			break;
 		    }
-		    if ((ctxt->sax) && (ctxt->sax->startDocument) &&
-		        (!ctxt->disableSAX))
-			ctxt->sax->startDocument(ctxt->userData);
-		    ctxt->instate = XML_PARSER_MISC;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering MISC\n");
-#endif
 		}
+                if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
+                    ctxt->sax->setDocumentLocator(ctxt->userData,
+                                                  &xmlDefaultSAXLocator);
+                if ((ctxt->sax) && (ctxt->sax->startDocument) &&
+                    (!ctxt->disableSAX))
+                    ctxt->sax->startDocument(ctxt->userData);
+                if (ctxt->instate == XML_PARSER_EOF)
+                    goto done;
+                ctxt->instate = XML_PARSER_MISC;
 		break;
             case XML_PARSER_START_TAG: {
 	        const xmlChar *name;
@@ -11312,11 +10980,12 @@
                 int line = ctxt->input->line;
 		int nsNr = ctxt->nsNr;
 
-		if ((avail < 2) && (ctxt->inputNr == 1))
+		if ((!terminate) && (avail < 2))
 		    goto done;
 		cur = ctxt->input->cur[0];
 	        if (cur != '<') {
-		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+		    xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
+                                   "Start tag expected, '<' not found");
 		    xmlHaltParser(ctxt);
 		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 			ctxt->sax->endDocument(ctxt->userData);
@@ -11401,57 +11070,70 @@
 		}
                 nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
 
+                if (ctxt->instate == XML_PARSER_EOF)
+                    goto done;
 		ctxt->instate = XML_PARSER_CONTENT;
                 break;
 	    }
             case XML_PARSER_CONTENT: {
-		if ((avail < 2) && (ctxt->inputNr == 1))
-		    goto done;
 		cur = ctxt->input->cur[0];
-		next = ctxt->input->cur[1];
 
-		if ((cur == '<') && (next == '/')) {
-		    ctxt->instate = XML_PARSER_END_TAG;
-		    break;
-	        } else if ((cur == '<') && (next == '?')) {
-		    if ((!terminate) &&
-		        (!xmlParseLookupString(ctxt, 2, "?>", 2)))
-			goto done;
-		    xmlParsePI(ctxt);
-		    ctxt->instate = XML_PARSER_CONTENT;
-		} else if ((cur == '<') && (next != '!')) {
-		    ctxt->instate = XML_PARSER_START_TAG;
-		    break;
-		} else if ((cur == '<') && (next == '!') &&
-		           (ctxt->input->cur[2] == '-') &&
-			   (ctxt->input->cur[3] == '-')) {
-		    if ((!terminate) &&
-		        (!xmlParseLookupString(ctxt, 4, "-->", 3)))
-			goto done;
-		    xmlParseComment(ctxt);
-		    ctxt->instate = XML_PARSER_CONTENT;
-		} else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
-		    (ctxt->input->cur[2] == '[') &&
-		    (ctxt->input->cur[3] == 'C') &&
-		    (ctxt->input->cur[4] == 'D') &&
-		    (ctxt->input->cur[5] == 'A') &&
-		    (ctxt->input->cur[6] == 'T') &&
-		    (ctxt->input->cur[7] == 'A') &&
-		    (ctxt->input->cur[8] == '[')) {
-		    SKIP(9);
-		    ctxt->instate = XML_PARSER_CDATA_SECTION;
-		    break;
-		} else if ((cur == '<') && (next == '!') &&
-		           (avail < 9)) {
-		    goto done;
-		} else if (cur == '<') {
-		    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		                "detected an error in element content\n");
-                    SKIP(1);
+		if (cur == '<') {
+                    if ((!terminate) && (avail < 2))
+                        goto done;
+		    next = ctxt->input->cur[1];
+
+                    if (next == '/') {
+                        ctxt->instate = XML_PARSER_END_TAG;
+                        break;
+                    } else if (next == '?') {
+                        if ((!terminate) &&
+                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
+                            goto done;
+                        xmlParsePI(ctxt);
+                        if (ctxt->instate == XML_PARSER_EOF)
+                            goto done;
+                        ctxt->instate = XML_PARSER_CONTENT;
+                        break;
+                    } else if (next == '!') {
+                        if ((!terminate) && (avail < 3))
+                            goto done;
+                        next = ctxt->input->cur[2];
+
+                        if (next == '-') {
+                            if ((!terminate) && (avail < 4))
+                                goto done;
+                            if (ctxt->input->cur[3] == '-') {
+                                if ((!terminate) &&
+                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
+                                    goto done;
+                                xmlParseComment(ctxt);
+                                if (ctxt->instate == XML_PARSER_EOF)
+                                    goto done;
+                                ctxt->instate = XML_PARSER_CONTENT;
+                                break;
+                            }
+                        } else if (next == '[') {
+                            if ((!terminate) && (avail < 9))
+                                goto done;
+                            if ((ctxt->input->cur[2] == '[') &&
+                                (ctxt->input->cur[3] == 'C') &&
+                                (ctxt->input->cur[4] == 'D') &&
+                                (ctxt->input->cur[5] == 'A') &&
+                                (ctxt->input->cur[6] == 'T') &&
+                                (ctxt->input->cur[7] == 'A') &&
+                                (ctxt->input->cur[8] == '[')) {
+                                SKIP(9);
+                                ctxt->instate = XML_PARSER_CDATA_SECTION;
+                                break;
+                            }
+                        }
+                    }
 		} else if (cur == '&') {
 		    if ((!terminate) && (!xmlParseLookupChar(ctxt, ';')))
 			goto done;
 		    xmlParseReference(ctxt);
+                    break;
 		} else {
 		    /* TODO Avoid the extra copy, handle directly !!! */
 		    /*
@@ -11465,19 +11147,19 @@
 		     *    callbacks between the push and pull versions
 		     *    of the parser.
 		     */
-		    if ((ctxt->inputNr == 1) &&
-		        (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
+		    if (avail < XML_PARSER_BIG_BUFFER_SIZE) {
 			if ((!terminate) && (!xmlParseLookupCharData(ctxt)))
 			    goto done;
                     }
                     ctxt->checkIndex = 0;
 		    xmlParseCharDataInternal(ctxt, !terminate);
+                    break;
 		}
+
+                ctxt->instate = XML_PARSER_START_TAG;
 		break;
 	    }
             case XML_PARSER_END_TAG:
-		if (avail < 2)
-		    goto done;
 		if ((!terminate) && (!xmlParseLookupChar(ctxt, '>')))
 		    goto done;
 		if (ctxt->sax2) {
@@ -11488,9 +11170,9 @@
 		  else
 		    xmlParseEndTag1(ctxt, 0);
 #endif /* LIBXML_SAX1_ENABLED */
-		if (ctxt->instate == XML_PARSER_EOF) {
-		    /* Nothing */
-		} else if (ctxt->nameNr == 0) {
+                if (ctxt->instate == XML_PARSER_EOF)
+                    goto done;
+		if (ctxt->nameNr == 0) {
 		    ctxt->instate = XML_PARSER_EPILOG;
 		} else {
 		    ctxt->instate = XML_PARSER_CONTENT;
@@ -11580,10 +11262,6 @@
 			goto done;
 		    SKIPL(base + 3);
 		    ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering CONTENT\n");
-#endif
 		}
 		break;
 	    }
@@ -11592,97 +11270,87 @@
             case XML_PARSER_EPILOG:
 		SKIP_BLANKS;
                 avail = ctxt->input->end - ctxt->input->cur;
-		if (avail < 2)
+		if (avail < 1)
 		    goto done;
-		cur = ctxt->input->cur[0];
-		next = ctxt->input->cur[1];
-	        if ((cur == '<') && (next == '?')) {
-		    if ((!terminate) &&
-                        (!xmlParseLookupString(ctxt, 2, "?>", 2)))
-			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing PI\n");
-#endif
-		    xmlParsePI(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		} else if ((cur == '<') && (next == '!') &&
-		    (ctxt->input->cur[2] == '-') &&
-		    (ctxt->input->cur[3] == '-')) {
-		    if ((!terminate) &&
-                        (!xmlParseLookupString(ctxt, 4, "-->", 3)))
-			goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing Comment\n");
-#endif
-		    xmlParseComment(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		} else if ((ctxt->instate == XML_PARSER_MISC) &&
-                    (cur == '<') && (next == '!') &&
-		    (ctxt->input->cur[2] == 'D') &&
-		    (ctxt->input->cur[3] == 'O') &&
-		    (ctxt->input->cur[4] == 'C') &&
-		    (ctxt->input->cur[5] == 'T') &&
-		    (ctxt->input->cur[6] == 'Y') &&
-		    (ctxt->input->cur[7] == 'P') &&
-		    (ctxt->input->cur[8] == 'E')) {
-		    if ((!terminate) && (!xmlParseLookupGt(ctxt)))
+		if (ctxt->input->cur[0] == '<') {
+                    if ((!terminate) && (avail < 2))
                         goto done;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: Parsing internal subset\n");
-#endif
-		    ctxt->inSubset = 1;
-		    xmlParseDocTypeDecl(ctxt);
-		    if (ctxt->instate == XML_PARSER_EOF)
-			goto done;
-		    if (RAW == '[') {
-			ctxt->instate = XML_PARSER_DTD;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: entering DTD\n");
-#endif
-		    } else {
-			/*
-			 * Create and update the external subset.
-			 */
-			ctxt->inSubset = 2;
-			if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
-			    (ctxt->sax->externalSubset != NULL))
-			    ctxt->sax->externalSubset(ctxt->userData,
-				    ctxt->intSubName, ctxt->extSubSystem,
-				    ctxt->extSubURI);
-			ctxt->inSubset = 0;
-			xmlCleanSpecialAttr(ctxt);
-			ctxt->instate = XML_PARSER_PROLOG;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"PP: entering PROLOG\n");
-#endif
-		    }
-		} else if ((cur == '<') && (next == '!') &&
-		           (avail <
-                            (ctxt->instate == XML_PARSER_MISC ? 9 : 4))) {
-		    goto done;
-		} else if (ctxt->instate == XML_PARSER_EPILOG) {
-		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-		    xmlHaltParser(ctxt);
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering EOF\n");
-#endif
-		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
-			ctxt->sax->endDocument(ctxt->userData);
-		    goto done;
+                    next = ctxt->input->cur[1];
+                    if (next == '?') {
+                        if ((!terminate) &&
+                            (!xmlParseLookupString(ctxt, 2, "?>", 2)))
+                            goto done;
+                        xmlParsePI(ctxt);
+                        if (ctxt->instate == XML_PARSER_EOF)
+                            goto done;
+                        break;
+                    } else if (next == '!') {
+                        if ((!terminate) && (avail < 3))
+                            goto done;
+
+                        if (ctxt->input->cur[2] == '-') {
+                            if ((!terminate) && (avail < 4))
+                                goto done;
+                            if (ctxt->input->cur[3] == '-') {
+                                if ((!terminate) &&
+                                    (!xmlParseLookupString(ctxt, 4, "-->", 3)))
+                                    goto done;
+                                xmlParseComment(ctxt);
+                                if (ctxt->instate == XML_PARSER_EOF)
+                                    goto done;
+                                break;
+                            }
+                        } else if (ctxt->instate == XML_PARSER_MISC) {
+                            if ((!terminate) && (avail < 9))
+                                goto done;
+                            if ((ctxt->input->cur[2] == 'D') &&
+                                (ctxt->input->cur[3] == 'O') &&
+                                (ctxt->input->cur[4] == 'C') &&
+                                (ctxt->input->cur[5] == 'T') &&
+                                (ctxt->input->cur[6] == 'Y') &&
+                                (ctxt->input->cur[7] == 'P') &&
+                                (ctxt->input->cur[8] == 'E')) {
+                                if ((!terminate) && (!xmlParseLookupGt(ctxt)))
+                                    goto done;
+                                ctxt->inSubset = 1;
+                                xmlParseDocTypeDecl(ctxt);
+                                if (ctxt->instate == XML_PARSER_EOF)
+                                    goto done;
+                                if (RAW == '[') {
+                                    ctxt->instate = XML_PARSER_DTD;
+                                } else {
+                                    /*
+                                     * Create and update the external subset.
+                                     */
+                                    ctxt->inSubset = 2;
+                                    if ((ctxt->sax != NULL) &&
+                                        (!ctxt->disableSAX) &&
+                                        (ctxt->sax->externalSubset != NULL))
+                                        ctxt->sax->externalSubset(
+                                                ctxt->userData,
+                                                ctxt->intSubName,
+                                                ctxt->extSubSystem,
+                                                ctxt->extSubURI);
+                                    ctxt->inSubset = 0;
+                                    xmlCleanSpecialAttr(ctxt);
+                                    if (ctxt->instate == XML_PARSER_EOF)
+                                        goto done;
+                                    ctxt->instate = XML_PARSER_PROLOG;
+                                }
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                if (ctxt->instate == XML_PARSER_EPILOG) {
+                    if (ctxt->errNo == XML_ERR_OK)
+                        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+		    ctxt->instate = XML_PARSER_EOF;
+                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+                        ctxt->sax->endDocument(ctxt->userData);
                 } else {
 		    ctxt->instate = XML_PARSER_START_TAG;
-#ifdef DEBUG_PUSH
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PP: entering START_TAG\n");
-#endif
 		}
 		break;
             case XML_PARSER_DTD: {
@@ -11701,90 +11369,16 @@
 		if (ctxt->instate == XML_PARSER_EOF)
 		    goto done;
 		ctxt->instate = XML_PARSER_PROLOG;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering PROLOG\n");
-#endif
                 break;
 	    }
-            case XML_PARSER_COMMENT:
+            default:
 		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == COMMENT\n");
-		ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_IGNORE:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == IGNORE");
-	        ctxt->instate = XML_PARSER_DTD;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering DTD\n");
-#endif
-	        break;
-            case XML_PARSER_PI:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == PI\n");
-		ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering CONTENT\n");
-#endif
-		break;
-            case XML_PARSER_ENTITY_DECL:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == ENTITY_DECL\n");
-		ctxt->instate = XML_PARSER_DTD;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering DTD\n");
-#endif
-		break;
-            case XML_PARSER_ENTITY_VALUE:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == ENTITY_VALUE\n");
-		ctxt->instate = XML_PARSER_CONTENT;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering DTD\n");
-#endif
-		break;
-            case XML_PARSER_ATTRIBUTE_VALUE:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == ATTRIBUTE_VALUE\n");
-		ctxt->instate = XML_PARSER_START_TAG;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering START_TAG\n");
-#endif
-		break;
-            case XML_PARSER_SYSTEM_LITERAL:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == SYSTEM_LITERAL\n");
-		ctxt->instate = XML_PARSER_START_TAG;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering START_TAG\n");
-#endif
-		break;
-            case XML_PARSER_PUBLIC_LITERAL:
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: internal error, state == PUBLIC_LITERAL\n");
-		ctxt->instate = XML_PARSER_START_TAG;
-#ifdef DEBUG_PUSH
-		xmlGenericError(xmlGenericErrorContext,
-			"PP: entering START_TAG\n");
-#endif
+			"PP: internal error\n");
+		ctxt->instate = XML_PARSER_EOF;
 		break;
 	}
     }
 done:
-#ifdef DEBUG_PUSH
-    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
-#endif
     return(ret);
 encoding_error:
     if (ctxt->input->end - ctxt->input->cur < 4) {
@@ -11840,39 +11434,16 @@
 
     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
         (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-	size_t cur = ctxt->input->cur - ctxt->input->base;
+	size_t pos = ctxt->input->cur - ctxt->input->base;
 	int res;
 
 	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
 	if (res < 0) {
             xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
 	    xmlHaltParser(ctxt);
 	    return(ctxt->errNo);
 	}
-#ifdef DEBUG_PUSH
-	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
-#endif
-
-    } else if (ctxt->instate != XML_PARSER_EOF) {
-	if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
-	    xmlParserInputBufferPtr in = ctxt->input->buf;
-	    if ((in->encoder != NULL) && (in->buffer != NULL) &&
-		    (in->raw != NULL)) {
-		int nbchars;
-		size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
-		size_t current = ctxt->input->cur - ctxt->input->base;
-
-		nbchars = xmlCharEncInput(in, terminate);
-		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
-		if (nbchars < 0) {
-	            xmlFatalErr(ctxt, in->error, NULL);
-                    xmlHaltParser(ctxt);
-		    return(ctxt->errNo);
-		}
-	    }
-	}
     }
 
     xmlParseTryOrFinish(ctxt, terminate);
@@ -11891,14 +11462,11 @@
 
     if ((end_in_lf == 1) && (ctxt->input != NULL) &&
         (ctxt->input->buf != NULL)) {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
-					 ctxt->input);
-	size_t current = ctxt->input->cur - ctxt->input->base;
+	size_t pos = ctxt->input->cur - ctxt->input->base;
         int res;
 
 	res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
-	xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
-			      base, current);
+	xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
         if (res < 0) {
             xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
             xmlHaltParser(ctxt);
@@ -11909,14 +11477,26 @@
 	/*
 	 * Check for termination
 	 */
-	if ((ctxt->instate != XML_PARSER_EOF) &&
-	    (ctxt->instate != XML_PARSER_EPILOG)) {
-	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-	}
-	if ((ctxt->instate == XML_PARSER_EPILOG) &&
-            (ctxt->input->cur < ctxt->input->end)) {
-	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-	}
+        if ((ctxt->instate != XML_PARSER_EOF) &&
+            (ctxt->instate != XML_PARSER_EPILOG)) {
+            if (ctxt->nameNr > 0) {
+                const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
+                int line = ctxt->pushTab[ctxt->nameNr - 1].line;
+                xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
+                        "Premature end of data in tag %s line %d\n",
+                        name, line, NULL);
+            } else if (ctxt->instate == XML_PARSER_START) {
+                xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+            } else {
+                xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
+                               "Start tag expected, '<' not found\n");
+            }
+        } else if ((ctxt->input->buf != NULL) &&
+                   (ctxt->input->buf->encoder != NULL) &&
+                   (!xmlBufIsEmpty(ctxt->input->buf->raw))) {
+            xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
+                           "Truncated multi-byte sequence at EOF\n");
+        }
 	if (ctxt->instate != XML_PARSER_EOF) {
 	    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
 		ctxt->sax->endDocument(ctxt->userData);
@@ -12000,28 +11580,17 @@
     xmlBufResetInput(inputStream->buf->buffer, inputStream);
     inputPush(ctxt, inputStream);
 
-    /*
-     * If the caller didn't provide an initial 'chunk' for determining
-     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
-     * that it can be automatically determined later
-     */
-    ctxt->charset = XML_CHAR_ENCODING_NONE;
-
     if ((size != 0) && (chunk != NULL) &&
         (ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-	size_t cur = ctxt->input->cur - ctxt->input->base;
+	size_t pos = ctxt->input->cur - ctxt->input->base;
         int res;
 
 	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
         if (res < 0) {
             xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
             xmlHaltParser(ctxt);
         }
-#ifdef DEBUG_PUSH
-	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
-#endif
     }
 
     return(ctxt);
@@ -12114,7 +11683,6 @@
     xmlDtdPtr ret = NULL;
     xmlParserCtxtPtr ctxt;
     xmlParserInputPtr pinput = NULL;
-    xmlChar start[4];
 
     if (input == NULL)
 	return(NULL);
@@ -12152,13 +11720,6 @@
         xmlSwitchEncoding(ctxt, enc);
     }
 
-    pinput->filename = NULL;
-    pinput->line = 1;
-    pinput->col = 1;
-    pinput->base = ctxt->input->cur;
-    pinput->cur = ctxt->input->cur;
-    pinput->free = NULL;
-
     /*
      * let's parse that entity knowing it's an external subset.
      */
@@ -12172,22 +11733,7 @@
     ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
 	                               BAD_CAST "none", BAD_CAST "none");
 
-    if ((enc == XML_CHAR_ENCODING_NONE) &&
-        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
-	/*
-	 * Get the 4 first bytes and decode the charset
-	 * if enc != XML_CHAR_ENCODING_NONE
-	 * plug some encoding conversion routines.
-	 */
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(start, 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-    }
+    xmlDetectEncoding(ctxt);
 
     xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
 
@@ -12235,7 +11781,6 @@
     xmlDtdPtr ret = NULL;
     xmlParserCtxtPtr ctxt;
     xmlParserInputPtr input = NULL;
-    xmlCharEncoding enc;
     xmlChar* systemIdCanonic;
 
     if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
@@ -12280,20 +11825,13 @@
 	    xmlFree(systemIdCanonic);
 	return(NULL);
     }
-    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
-	enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
-	xmlSwitchEncoding(ctxt, enc);
-    }
+
+    xmlDetectEncoding(ctxt);
 
     if (input->filename == NULL)
 	input->filename = (char *) systemIdCanonic;
     else
 	xmlFree(systemIdCanonic);
-    input->line = 1;
-    input->col = 1;
-    input->base = ctxt->input->cur;
-    input->cur = ctxt->input->cur;
-    input->free = NULL;
 
     /*
      * let's parse that entity knowing it's an external subset.
@@ -12421,8 +11959,6 @@
     xmlDocPtr newDoc;
     xmlNodePtr newRoot;
     xmlParserErrors ret = XML_ERR_OK;
-    xmlChar start[4];
-    xmlCharEncoding enc;
 
     if (((depth > 40) &&
 	((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
@@ -12483,22 +12019,7 @@
         newRoot->doc = doc;
     }
 
-    /*
-     * Get the 4 first bytes and decode the charset
-     * if enc != XML_CHAR_ENCODING_NONE
-     * plug some encoding conversion routines.
-     */
-    GROW;
-    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
-	start[0] = RAW;
-	start[1] = NXT(1);
-	start[2] = NXT(2);
-	start[3] = NXT(3);
-	enc = xmlDetectCharEncoding(start, 4);
-	if (enc != XML_CHAR_ENCODING_NONE) {
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-    }
+    xmlDetectEncoding(ctxt);
 
     /*
      * Parse a possible text declaration first
@@ -12715,7 +12236,6 @@
     xmlSAXHandlerPtr oldsax = NULL;
     xmlNodePtr content = NULL;
     xmlNodePtr last = NULL;
-    int size;
     xmlParserErrors ret = XML_ERR_OK;
 #ifdef SAX2
     int i;
@@ -12734,9 +12254,7 @@
     if (string == NULL)
         return(XML_ERR_INTERNAL_ERROR);
 
-    size = xmlStrlen(string);
-
-    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
+    ctxt = xmlCreateDocParserCtxt(string);
     if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
     ctxt->nbErrors = oldctxt->nbErrors;
     ctxt->nbWarnings = oldctxt->nbWarnings;
@@ -12985,10 +12503,6 @@
     if (doc->encoding != NULL) {
         xmlCharEncodingHandlerPtr hdlr;
 
-        if (ctxt->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->encoding);
-        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
-
         hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
         if (hdlr != NULL) {
             xmlSwitchToEncoding(ctxt, hdlr);
@@ -13147,7 +12661,6 @@
     xmlDocPtr newDoc;
     xmlSAXHandlerPtr oldsax = NULL;
     xmlNodePtr content, newRoot;
-    int size;
     int ret = 0;
 
     if (depth > 40) {
@@ -13160,9 +12673,7 @@
     if (string == NULL)
         return(-1);
 
-    size = xmlStrlen(string);
-
-    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
+    ctxt = xmlCreateDocParserCtxt(string);
     if (ctxt == NULL) return(-1);
     ctxt->userData = ctxt;
     if (sax != NULL) {
@@ -13965,20 +13476,44 @@
 
 /**
  * xmlCreateDocParserCtxt:
- * @cur:  a pointer to an array of xmlChar
+ * @str:  a pointer to an array of xmlChar
  *
  * Creates a parser context for an XML in-memory document.
  *
  * Returns the new parser context or NULL
  */
 xmlParserCtxtPtr
-xmlCreateDocParserCtxt(const xmlChar *cur) {
-    int len;
+xmlCreateDocParserCtxt(const xmlChar *str) {
+    xmlParserCtxtPtr ctxt;
+    xmlParserInputPtr input;
+    xmlParserInputBufferPtr buf;
 
-    if (cur == NULL)
+    if (str == NULL)
 	return(NULL);
-    len = xmlStrlen(cur);
-    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
+
+    ctxt = xmlNewParserCtxt();
+    if (ctxt == NULL)
+	return(NULL);
+
+    buf = xmlParserInputBufferCreateString(str);
+    if (buf == NULL) {
+	xmlFreeParserCtxt(ctxt);
+	return(NULL);
+    }
+
+    input = xmlNewInputStream(ctxt);
+    if (input == NULL) {
+	xmlFreeParserInputBuffer(buf);
+	xmlFreeParserCtxt(ctxt);
+	return(NULL);
+    }
+
+    input->filename = NULL;
+    input->buf = buf;
+    xmlBufResetInput(input->buf->buffer, input);
+
+    inputPush(ctxt, input);
+    return(ctxt);
 }
 
 #ifdef LIBXML_SAX1_ENABLED
@@ -14090,118 +13625,6 @@
 
 /************************************************************************
  *									*
- *				Miscellaneous				*
- *									*
- ************************************************************************/
-
-static int xmlParserInitialized = 0;
-
-/**
- * xmlInitParser:
- *
- * Initialization function for the XML parser.
- * This is not reentrant. Call once before processing in case of
- * use in multithreaded programs.
- */
-
-void
-xmlInitParser(void) {
-    /*
-     * Note that the initialization code must not make memory allocations.
-     */
-    if (xmlParserInitialized != 0)
-	return;
-
-#ifdef LIBXML_THREAD_ENABLED
-    __xmlGlobalInitMutexLock();
-    if (xmlParserInitialized == 0) {
-#endif
-#if defined(_WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
-        if (xmlFree == free)
-            atexit(xmlCleanupParser);
-#endif
-
-	xmlInitThreadsInternal();
-	xmlInitGlobalsInternal();
-	xmlInitMemoryInternal();
-        __xmlInitializeDict();
-	xmlInitEncodingInternal();
-	xmlRegisterDefaultInputCallbacks();
-#ifdef LIBXML_OUTPUT_ENABLED
-	xmlRegisterDefaultOutputCallbacks();
-#endif /* LIBXML_OUTPUT_ENABLED */
-#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-	xmlInitXPathInternal();
-#endif
-	xmlParserInitialized = 1;
-#ifdef LIBXML_THREAD_ENABLED
-    }
-    __xmlGlobalInitMutexUnlock();
-#endif
-}
-
-/**
- * xmlCleanupParser:
- *
- * This function name is somewhat misleading. It does not clean up
- * parser state, it cleans up memory allocated by the library itself.
- * It is a cleanup function for the XML library. It tries to reclaim all
- * related global memory allocated for the library processing.
- * It doesn't deallocate any document related memory. One should
- * call xmlCleanupParser() only when the process has finished using
- * the library and all XML/HTML documents built with it.
- * See also xmlInitParser() which has the opposite function of preparing
- * the library for operations.
- *
- * WARNING: if your application is multithreaded or has plugin support
- *          calling this may crash the application if another thread or
- *          a plugin is still using libxml2. It's sometimes very hard to
- *          guess if libxml2 is in use in the application, some libraries
- *          or plugins may use it without notice. In case of doubt abstain
- *          from calling this function or do it just before calling exit()
- *          to avoid leak reports from valgrind !
- */
-
-void
-xmlCleanupParser(void) {
-    if (!xmlParserInitialized)
-	return;
-
-    xmlCleanupCharEncodingHandlers();
-#ifdef LIBXML_CATALOG_ENABLED
-    xmlCatalogCleanup();
-#endif
-    xmlCleanupDictInternal();
-    xmlCleanupInputCallbacks();
-#ifdef LIBXML_OUTPUT_ENABLED
-    xmlCleanupOutputCallbacks();
-#endif
-#ifdef LIBXML_SCHEMAS_ENABLED
-    xmlSchemaCleanupTypes();
-    xmlRelaxNGCleanupTypes();
-#endif
-    xmlCleanupGlobalsInternal();
-    xmlCleanupThreadsInternal();
-    xmlCleanupMemoryInternal();
-    xmlParserInitialized = 0;
-}
-
-#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && !defined(LIBXML_STATIC) && \
-    !defined(_WIN32)
-static void
-ATTRIBUTE_DESTRUCTOR
-xmlDestructor(void) {
-    /*
-     * Calling custom deallocation functions in a destructor can cause
-     * problems, for example with Nokogiri.
-     */
-    if (xmlFree == free)
-        xmlCleanupParser();
-}
-#endif
-
-/************************************************************************
- *									*
  *	New set (2.6.0) of simpler and more flexible APIs		*
  *									*
  ************************************************************************/
@@ -14295,7 +13718,6 @@
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
     ctxt->depth = 0;
-    ctxt->charset = XML_CHAR_ENCODING_UTF8;
     ctxt->catalogs = NULL;
     ctxt->sizeentities = 0;
     ctxt->sizeentcopy = 0;
@@ -14338,15 +13760,11 @@
 {
     xmlParserInputPtr inputStream;
     xmlParserInputBufferPtr buf;
-    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
 
     if (ctxt == NULL)
         return(1);
 
-    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
-        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
-
-    buf = xmlAllocParserInputBuffer(enc);
+    buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
     if (buf == NULL)
         return(1);
 
@@ -14381,29 +13799,21 @@
 
     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
         (ctxt->input->buf != NULL)) {
-	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
-        size_t cur = ctxt->input->cur - ctxt->input->base;
+        size_t pos = ctxt->input->cur - ctxt->input->base;
         int res;
 
         res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+        xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos);
         if (res < 0) {
             xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
             xmlHaltParser(ctxt);
             return(1);
         }
-#ifdef DEBUG_PUSH
-        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
-#endif
     }
 
     if (encoding != NULL) {
         xmlCharEncodingHandlerPtr hdlr;
 
-        if (ctxt->encoding != NULL)
-	    xmlFree((xmlChar *) ctxt->encoding);
-        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
-
         hdlr = xmlFindCharEncodingHandler(encoding);
         if (hdlr != NULL) {
             xmlSwitchToEncoding(ctxt, hdlr);
@@ -14411,8 +13821,6 @@
 	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
 			      "Unsupported encoding %s\n", BAD_CAST encoding);
         }
-    } else if (enc != XML_CHAR_ENCODING_NONE) {
-        xmlSwitchEncoding(ctxt, enc);
     }
 
     return(0);
@@ -14576,6 +13984,25 @@
 }
 
 /**
+ * xmlCtxtSetMaxAmplification:
+ * @ctxt: an XML parser context
+ * @maxAmpl:  maximum amplification factor
+ *
+ * To protect against exponential entity expansion ("billion laughs"), the
+ * size of serialized output is (roughly) limited to the input size
+ * multiplied by this factor. The default value is 5.
+ *
+ * When working with documents making heavy use of entity expansion, it can
+ * be necessary to increase the value. For security reasons, this should only
+ * be considered when processing trusted input.
+ */
+void
+xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl)
+{
+    ctxt->maxAmpl = maxAmpl;
+}
+
+/**
  * xmlDoRead:
  * @ctxt:  an XML parser context
  * @URL:  the base URL to use for the document
@@ -14792,7 +14219,7 @@
 /**
  * xmlCtxtReadDoc:
  * @ctxt:  an XML parser context
- * @cur:  a pointer to a zero terminated string
+ * @str:  a pointer to a zero terminated string
  * @URL:  the base URL to use for the document
  * @encoding:  the document encoding, or NULL
  * @options:  a combination of xmlParserOption
@@ -14803,13 +14230,33 @@
  * Returns the resulting document tree
  */
 xmlDocPtr
-xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
+xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar *str,
                const char *URL, const char *encoding, int options)
 {
-    if (cur == NULL)
+    xmlParserInputBufferPtr input;
+    xmlParserInputPtr stream;
+
+    if (ctxt == NULL)
         return (NULL);
-    return (xmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL,
-                              encoding, options));
+    if (str == NULL)
+        return (NULL);
+    xmlInitParser();
+
+    xmlCtxtReset(ctxt);
+
+    input = xmlParserInputBufferCreateString(str);
+    if (input == NULL) {
+	return(NULL);
+    }
+
+    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
+    if (stream == NULL) {
+	xmlFreeParserInputBuffer(input);
+	return(NULL);
+    }
+
+    inputPush(ctxt, stream);
+    return (xmlDoRead(ctxt, URL, encoding, options, 1));
 }
 
 /**
diff --git a/third_party/libxml/src/parserInternals.c b/third_party/libxml/src/parserInternals.c
index 11324b2..51a472ee 100644
--- a/third_party/libxml/src/parserInternals.c
+++ b/third_party/libxml/src/parserInternals.c
@@ -24,19 +24,16 @@
 #include <libxml/tree.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
-#include <libxml/valid.h>
 #include <libxml/entities.h>
 #include <libxml/xmlerror.h>
 #include <libxml/encoding.h>
-#include <libxml/valid.h>
 #include <libxml/xmlIO.h>
 #include <libxml/uri.h>
 #include <libxml/dict.h>
-#include <libxml/SAX.h>
+#include <libxml/xmlsave.h>
 #ifdef LIBXML_CATALOG_ENABLED
 #include <libxml/catalog.h>
 #endif
-#include <libxml/globals.h>
 #include <libxml/chvalid.h>
 
 #define CUR(ctxt) ctxt->input->cur
@@ -50,6 +47,12 @@
 #include "private/parser.h"
 
 /*
+ * XML_MAX_AMPLIFICATION_DEFAULT is the default maximum allowed amplification
+ * factor of serialized output after entity expansion.
+ */
+#define XML_MAX_AMPLIFICATION_DEFAULT 5
+
+/*
  * Various global defaults for parsing
  */
 
@@ -179,7 +182,7 @@
  * xmlFatalErr:
  * @ctxt:  an XML parser context
  * @error:  the error number
- * @extra:  extra information string
+ * @info:  extra information string
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
@@ -445,41 +448,9 @@
  *									*
  ************************************************************************/
 
-/* #define DEBUG_INPUT */
-/* #define DEBUG_STACK */
-/* #define DEBUG_PUSH */
-
-
 /* we need to keep enough input to show errors in context */
 #define LINE_LEN        80
 
-#ifdef DEBUG_INPUT
-#define CHECK_BUFFER(in) check_buffer(in)
-
-static
-void check_buffer(xmlParserInputPtr in) {
-    if (in->base != xmlBufContent(in->buf->buffer)) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlParserInput: base mismatch problem\n");
-    }
-    if (in->cur < in->base) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlParserInput: cur < base problem\n");
-    }
-    if (in->cur > in->base + xmlBufUse(in->buf->buffer)) {
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlParserInput: cur > base + use problem\n");
-    }
-    xmlGenericError(xmlGenericErrorContext,"buffer %p : content %x, cur %d, use %d\n",
-            (void *) in, (int) xmlBufContent(in->buf->buffer),
-            in->cur - in->base, xmlBufUse(in->buf->buffer));
-}
-
-#else
-#define CHECK_BUFFER(in)
-#endif
-
-
 /**
  * xmlHaltParser:
  * @ctxt:  an XML parser context
@@ -532,6 +503,10 @@
 /**
  * xmlParserGrow:
  * @ctxt:  an XML parser context
+ *
+ * Grow the input buffer.
+ *
+ * Returns the number of bytes read or -1 in case of error.
  */
 int
 xmlParserGrow(xmlParserCtxtPtr ctxt) {
@@ -546,9 +521,6 @@
     /* Don't grow push parser buffer. */
     if (ctxt->progressive)
         return(0);
-    /* Don't grow memory buffers. */
-    if ((buf->encoder == NULL) && (buf->readcallback == NULL))
-        return(0);
     if (buf->error != 0)
         return(-1);
 
@@ -564,7 +536,7 @@
         return(0);
 
     ret = xmlParserInputBufferGrow(buf, INPUT_CHUNK);
-    xmlBufSetInputBaseCur(buf->buffer, in, 0, curBase);
+    xmlBufUpdateInput(buf->buffer, in, curBase);
 
     if (ret < 0) {
         xmlFatalErr(ctxt, buf->error, NULL);
@@ -595,25 +567,13 @@
     size_t indx;
 
     if ((in == NULL) || (len < 0)) return(-1);
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext, "Grow\n");
-#endif
     if (in->buf == NULL) return(-1);
     if (in->base == NULL) return(-1);
     if (in->cur == NULL) return(-1);
     if (in->buf->buffer == NULL) return(-1);
 
-    /* Don't grow memory buffers. */
-    if ((in->buf->encoder == NULL) && (in->buf->readcallback == NULL))
-        return(0);
-
-    CHECK_BUFFER(in);
-
     indx = in->cur - in->base;
     if (xmlBufUse(in->buf->buffer) > (unsigned int) indx + INPUT_CHUNK) {
-
-	CHECK_BUFFER(in);
-
         return(0);
     }
     ret = xmlParserInputBufferGrow(in->buf, len);
@@ -628,14 +588,14 @@
     in->cur = in->base + indx;
     in->end = xmlBufEnd(in->buf->buffer);
 
-    CHECK_BUFFER(in);
-
     return(ret);
 }
 
 /**
  * xmlParserShrink:
  * @ctxt:  an XML parser context
+ *
+ * Shrink the input buffer.
  */
 void
 xmlParserShrink(xmlParserCtxtPtr ctxt) {
@@ -667,7 +627,7 @@
 	}
     }
 
-    xmlBufSetInputBaseCur(buf->buffer, in, 0, used);
+    xmlBufUpdateInput(buf->buffer, in, used);
 }
 
 /**
@@ -683,17 +643,12 @@
     size_t used;
     size_t ret;
 
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext, "Shrink\n");
-#endif
     if (in == NULL) return;
     if (in->buf == NULL) return;
     if (in->base == NULL) return;
     if (in->cur == NULL) return;
     if (in->buf->buffer == NULL) return;
 
-    CHECK_BUFFER(in);
-
     used = in->cur - in->base;
     /*
      * Do not shrink on large buffers whose only a tiny fraction
@@ -725,8 +680,6 @@
     }
     in->cur = in->base + used;
     in->end = xmlBufEnd(in->buf->buffer);
-
-    CHECK_BUFFER(in);
 }
 
 /************************************************************************
@@ -765,7 +718,7 @@
             return;
     }
 
-    if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
+    if ((ctxt->input->flags & XML_INPUT_8_BIT) == 0) {
         const unsigned char *cur;
         unsigned char c;
 
@@ -876,7 +829,10 @@
 		     "Input is not proper UTF-8, indicate encoding !\n%s",
 		     BAD_CAST buffer, NULL);
     }
-    ctxt->charset = XML_CHAR_ENCODING_8859_1;
+    if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) {
+        ctxt->input->flags |= XML_INPUT_HAS_ENCODING;
+        ctxt->input->flags |= XML_INPUT_8_BIT;
+    }
     ctxt->input->cur++;
     return;
 }
@@ -917,7 +873,7 @@
 	    *len = 1;
 	    return(*ctxt->input->cur);
     }
-    if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
+    if ((ctxt->input->flags & XML_INPUT_8_BIT) == 0) {
 	/*
 	 * We are supposed to handle UTF8, check it's valid
 	 * From rfc2044: encoding of the Unicode values on UTF-8:
@@ -1040,7 +996,10 @@
 		     "Input is not proper UTF-8, indicate encoding !\n%s",
 		     BAD_CAST buffer, NULL);
     }
-    ctxt->charset = XML_CHAR_ENCODING_8859_1;
+    if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) {
+        ctxt->input->flags |= XML_INPUT_HAS_ENCODING;
+        ctxt->input->flags |= XML_INPUT_8_BIT;
+    }
     *len = 1;
     return(*ctxt->input->cur);
 
@@ -1073,7 +1032,8 @@
 xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar * cur, int *len)
 {
     if ((len == NULL) || (cur == NULL)) return(0);
-    if ((ctxt == NULL) || (ctxt->charset == XML_CHAR_ENCODING_UTF8)) {
+    if ((ctxt == NULL) || (ctxt->input == NULL) ||
+        ((ctxt->input->flags & XML_INPUT_8_BIT) == 0)) {
         /*
          * We are supposed to handle UTF8, check it's valid
          * From rfc2044: encoding of the Unicode values on UTF-8:
@@ -1253,7 +1213,7 @@
         return(NULL);
     outlen = sizeof(out) - 1;
     inlen = input->end - input->cur;
-    res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen, 0);
+    res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen);
     if (res < 0)
         return(handler);
     out[outlen] = 0;
@@ -1287,12 +1247,15 @@
                 break;
             out[i] = 0;
             xmlCharEncCloseFunc(handler);
-            handler = xmlFindCharEncodingHandler((char *) out + start);
-            break;
+            return(xmlFindCharEncodingHandler((char *) out + start));
         }
     }
 
-    return(handler);
+    /*
+     * ICU handlers are stateful, so we have to recreate them.
+     */
+    xmlCharEncCloseFunc(handler);
+    return(xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC));
 }
 
 /**
@@ -1300,58 +1263,29 @@
  * @ctxt:  the parser context
  * @enc:  the encoding value (number)
  *
- * change the input functions when discovering the character encoding
- * of a given entity.
+ * Use encoding specified by enum to decode input data.
+ *
+ * This function can be used to enforce the encoding of chunks passed
+ * to xmlParseChunk.
  *
  * Returns 0 in case of success, -1 otherwise
  */
 int
 xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
 {
-    xmlCharEncodingHandlerPtr handler;
+    xmlCharEncodingHandlerPtr handler = NULL;
+    int check = 1;
     int ret;
 
-    if (ctxt == NULL) return(-1);
-
-    /*
-     * FIXME: The BOM shouldn't be skipped here, but in the parsing code.
-     *
-     * Note that we look for a decoded UTF-8 BOM when switching to UTF-16.
-     * This is mostly useless but Webkit/Chromium relies on this behavior.
-     * See https://bugs.chromium.org/p/chromium/issues/detail?id=1451026
-     */
-    if ((ctxt->input != NULL) &&
-        (ctxt->input->consumed == 0) &&
-        (ctxt->input->cur != NULL) &&
-        (ctxt->input->cur == ctxt->input->base) &&
-        ((enc == XML_CHAR_ENCODING_UTF8) ||
-         (enc == XML_CHAR_ENCODING_UTF16LE) ||
-         (enc == XML_CHAR_ENCODING_UTF16BE))) {
-        /*
-         * Errata on XML-1.0 June 20 2001
-         * Specific handling of the Byte Order Mark for
-         * UTF-8
-         */
-        if ((ctxt->input->cur[0] == 0xEF) &&
-            (ctxt->input->cur[1] == 0xBB) &&
-            (ctxt->input->cur[2] == 0xBF)) {
-            ctxt->input->cur += 3;
-        }
-    }
+    if ((ctxt == NULL) || (ctxt->input == NULL))
+        return(-1);
 
     switch (enc) {
-	case XML_CHAR_ENCODING_ERROR:
-	    __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
-	                   "encoding unknown\n", NULL, NULL);
-	    return(-1);
 	case XML_CHAR_ENCODING_NONE:
-	    /* let's assume it's UTF-8 without the XML decl */
-	    ctxt->charset = XML_CHAR_ENCODING_UTF8;
-	    return(0);
 	case XML_CHAR_ENCODING_UTF8:
-	    /* default encoding, no conversion should be needed */
-	    ctxt->charset = XML_CHAR_ENCODING_UTF8;
-	    return(0);
+        case XML_CHAR_ENCODING_ASCII:
+            check = 0;
+            break;
         case XML_CHAR_ENCODING_EBCDIC:
             handler = xmlDetectEBCDIC(ctxt->input);
             break;
@@ -1359,45 +1293,28 @@
             handler = xmlGetCharEncodingHandler(enc);
             break;
     }
-    if (handler == NULL) {
-	/*
-	 * Default handlers.
-	 */
-	switch (enc) {
-	    case XML_CHAR_ENCODING_ASCII:
-		/* default encoding, no conversion should be needed */
-		ctxt->charset = XML_CHAR_ENCODING_UTF8;
-		return(0);
-	    case XML_CHAR_ENCODING_8859_1:
-		if ((ctxt->inputNr == 1) &&
-		    (ctxt->encoding == NULL) &&
-		    (ctxt->input != NULL) &&
-		    (ctxt->input->encoding != NULL)) {
-		    ctxt->encoding = xmlStrdup(ctxt->input->encoding);
-		}
-		ctxt->charset = enc;
-		return(0);
-	    default:
-		__xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
-                        "encoding not supported: %s\n",
-			BAD_CAST xmlGetCharEncodingName(enc), NULL);
-                /*
-                 * TODO: We could recover from errors in external entities
-                 * if we didn't stop the parser. But most callers of this
-                 * function don't check the return value.
-                 */
-                xmlStopParser(ctxt);
-                return(-1);
-        }
-    }
-    ret = xmlSwitchInputEncoding(ctxt, ctxt->input, handler);
-    if ((ret < 0) || (ctxt->errNo == XML_I18N_CONV_FAILED)) {
+
+    if ((check) && (handler == NULL)) {
+        const char *name = xmlGetCharEncodingName(enc);
+
+        __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+                "encoding not supported: %s\n",
+                BAD_CAST (name ? name : "<null>"), NULL);
         /*
-	 * on encoding conversion errors, stop the parser
-	 */
+         * TODO: We could recover from errors in external entities
+         * if we didn't stop the parser. But most callers of this
+         * function don't check the return value.
+         */
         xmlStopParser(ctxt);
-	ctxt->errNo = XML_I18N_CONV_FAILED;
+        return(-1);
     }
+
+    ret = xmlSwitchInputEncoding(ctxt, ctxt->input, handler);
+
+    if ((ret >= 0) && (enc == XML_CHAR_ENCODING_NONE)) {
+        ctxt->input->flags &= ~XML_INPUT_HAS_ENCODING;
+    }
+
     return(ret);
 }
 
@@ -1407,8 +1324,9 @@
  * @input:  the input stream
  * @handler:  the encoding handler
  *
- * change the input functions when discovering the character encoding
- * of a given entity.
+ * DEPRECATED: Internal function, don't use.
+ *
+ * Use encoding handler to decode input data.
  *
  * Returns 0 in case of success, -1 otherwise
  */
@@ -1419,27 +1337,28 @@
     int nbchars;
     xmlParserInputBufferPtr in;
 
-    if (handler == NULL)
-        return (-1);
-    if (input == NULL)
-        return (-1);
-    in = input->buf;
-    if (in == NULL) {
-	xmlErrInternal(ctxt,
-                "static memory buffer doesn't support encoding\n", NULL);
-        /*
-         * Callers assume that the input buffer takes ownership of the
-         * encoding handler. xmlCharEncCloseFunc frees unregistered
-         * handlers and avoids a memory leak.
-         */
+    if ((input == NULL) || (input->buf == NULL)) {
         xmlCharEncCloseFunc(handler);
 	return (-1);
     }
+    in = input->buf;
+
+    input->flags |= XML_INPUT_HAS_ENCODING;
+    input->flags &= ~XML_INPUT_8_BIT;
+
+    /*
+     * UTF-8 requires no encoding handler.
+     */
+    if ((handler != NULL) &&
+        (xmlStrcasecmp(BAD_CAST handler->name, BAD_CAST "UTF-8") == 0)) {
+        xmlCharEncCloseFunc(handler);
+        handler = NULL;
+    }
+
+    if (in->encoder == handler)
+        return (0);
 
     if (in->encoder != NULL) {
-        if (in->encoder == handler)
-            return (0);
-
         /*
          * Switching encodings during parsing is a really bad idea,
          * but Chromium can switch between ISO-8859-1 and UTF-16 before
@@ -1454,45 +1373,13 @@
         return (0);
     }
 
-    ctxt->charset = XML_CHAR_ENCODING_UTF8;
     in->encoder = handler;
 
     /*
      * Is there already some content down the pipe to convert ?
      */
     if (xmlBufIsEmpty(in->buffer) == 0) {
-        size_t processed, use, consumed;
-
-        /*
-         * FIXME: The BOM shouldn't be skipped here, but in the parsing code.
-         */
-
-        /*
-         * Specific handling of the Byte Order Mark for
-         * UTF-16
-         */
-        if ((handler->name != NULL) &&
-            (!strcmp(handler->name, "UTF-16LE") ||
-             !strcmp(handler->name, "UTF-16")) &&
-            (input->cur[0] == 0xFF) && (input->cur[1] == 0xFE)) {
-            input->cur += 2;
-        }
-        if ((handler->name != NULL) &&
-            (!strcmp(handler->name, "UTF-16BE")) &&
-            (input->cur[0] == 0xFE) && (input->cur[1] == 0xFF)) {
-            input->cur += 2;
-        }
-        /*
-         * Errata on XML-1.0 June 20 2001
-         * Specific handling of the Byte Order Mark for
-         * UTF-8
-         */
-        if ((handler->name != NULL) &&
-            (!strcmp(handler->name, "UTF-8")) &&
-            (input->cur[0] == 0xEF) &&
-            (input->cur[1] == 0xBB) && (input->cur[2] == 0xBF)) {
-            input->cur += 3;
-        }
+        size_t processed;
 
         /*
          * Shrink the current input buffer.
@@ -1504,19 +1391,8 @@
         in->raw = in->buffer;
         in->buffer = xmlBufCreate();
         in->rawconsumed = processed;
-        use = xmlBufUse(in->raw);
 
-        /*
-         * TODO: We must flush and decode the whole buffer to make functions
-         * like xmlReadMemory work with a user-provided encoding. If the
-         * encoding is specified directly, we should probably set
-         * XML_PARSE_IGNORE_ENC in xmlDoRead to avoid switching encodings
-         * twice. Then we could set "flush" to false which should save
-         * a considerable amount of memory when parsing from memory.
-         * It's probably even possible to remove this whole if-block
-         * completely.
-         */
-        nbchars = xmlCharEncInput(in, 1);
+        nbchars = xmlCharEncInput(in);
         xmlBufResetInput(in->buffer, input);
         if (nbchars < 0) {
             /* TODO: This could be an out of memory or an encoding error. */
@@ -1526,12 +1402,6 @@
             xmlHaltParser(ctxt);
             return (-1);
         }
-        consumed = use - xmlBufUse(in->raw);
-        if ((consumed > ULONG_MAX) ||
-            (in->rawconsumed > ULONG_MAX - (unsigned long)consumed))
-            in->rawconsumed = ULONG_MAX;
-        else
-	    in->rawconsumed += consumed;
     }
     return (0);
 }
@@ -1541,8 +1411,10 @@
  * @ctxt:  the parser context
  * @handler:  the encoding handler
  *
- * change the input functions when discovering the character encoding
- * of a given entity.
+ * Use encoding handler to decode input data.
+ *
+ * This function can be used to enforce the encoding of chunks passed
+ * to xmlParseChunk.
  *
  * Returns 0 in case of success, -1 otherwise
  */
@@ -1554,6 +1426,188 @@
     return(xmlSwitchInputEncoding(ctxt, ctxt->input, handler));
 }
 
+/**
+ * xmlDetectEncoding:
+ * @ctxt:  the parser context
+ *
+ * Handle optional BOM, detect and switch to encoding.
+ *
+ * Assumes that there are at least four bytes in the input buffer.
+ */
+void
+xmlDetectEncoding(xmlParserCtxtPtr ctxt) {
+    const xmlChar *in;
+    xmlCharEncoding enc;
+    int bomSize;
+    int autoFlag = 0;
+
+    if (xmlParserGrow(ctxt) < 0)
+        return;
+    in = ctxt->input->cur;
+    if (ctxt->input->end - in < 4)
+        return;
+
+    if (ctxt->input->flags & XML_INPUT_HAS_ENCODING) {
+        /*
+         * If the encoding was already set, only skip the BOM which was
+         * possibly decoded to UTF-8.
+         */
+        if ((in[0] == 0xEF) && (in[1] == 0xBB) && (in[2] == 0xBF)) {
+            ctxt->input->cur += 3;
+        }
+
+        return;
+    }
+
+    enc = XML_CHAR_ENCODING_NONE;
+    bomSize = 0;
+
+    switch (in[0]) {
+        case 0x00:
+            if ((in[1] == 0x00) && (in[2] == 0x00) && (in[3] == 0x3C)) {
+                enc = XML_CHAR_ENCODING_UCS4BE;
+                autoFlag = XML_INPUT_AUTO_OTHER;
+            } else if ((in[1] == 0x3C) && (in[2] == 0x00) && (in[3] == 0x3F)) {
+                enc = XML_CHAR_ENCODING_UTF16BE;
+                autoFlag = XML_INPUT_AUTO_UTF16BE;
+            }
+            break;
+
+        case 0x3C:
+            if (in[1] == 0x00) {
+                if ((in[2] == 0x00) && (in[3] == 0x00)) {
+                    enc = XML_CHAR_ENCODING_UCS4LE;
+                    autoFlag = XML_INPUT_AUTO_OTHER;
+                } else if ((in[2] == 0x3F) && (in[3] == 0x00)) {
+                    enc = XML_CHAR_ENCODING_UTF16LE;
+                    autoFlag = XML_INPUT_AUTO_UTF16LE;
+                }
+            }
+            break;
+
+        case 0x4C:
+	    if ((in[1] == 0x6F) && (in[2] == 0xA7) && (in[3] == 0x94)) {
+	        enc = XML_CHAR_ENCODING_EBCDIC;
+                autoFlag = XML_INPUT_AUTO_OTHER;
+            }
+            break;
+
+        case 0xEF:
+            if ((in[1] == 0xBB) && (in[2] == 0xBF)) {
+                enc = XML_CHAR_ENCODING_UTF8;
+                autoFlag = XML_INPUT_AUTO_UTF8;
+                bomSize = 3;
+            }
+            break;
+
+        case 0xFE:
+            if (in[1] == 0xFF) {
+                enc = XML_CHAR_ENCODING_UTF16BE;
+                autoFlag = XML_INPUT_AUTO_UTF16BE;
+                bomSize = 2;
+            }
+            break;
+
+        case 0xFF:
+            if (in[1] == 0xFE) {
+                enc = XML_CHAR_ENCODING_UTF16LE;
+                autoFlag = XML_INPUT_AUTO_UTF16LE;
+                bomSize = 2;
+            }
+            break;
+    }
+
+    if (bomSize > 0) {
+        ctxt->input->cur += bomSize;
+    }
+
+    if (enc != XML_CHAR_ENCODING_NONE) {
+        ctxt->input->flags |= autoFlag;
+        xmlSwitchEncoding(ctxt, enc);
+    }
+}
+
+/**
+ * xmlSetDeclaredEncoding:
+ * @ctxt:  the parser context
+ * @encoding:  declared encoding
+ *
+ * Set the encoding from a declaration in the document.
+ *
+ * If no encoding was set yet, switch the encoding. Otherwise, only warn
+ * about encoding mismatches.
+ *
+ * Takes ownership of 'encoding'.
+ */
+void
+xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) {
+    if (ctxt->encoding != NULL)
+        xmlFree((xmlChar *) ctxt->encoding);
+    ctxt->encoding = encoding;
+
+    if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) &&
+        ((ctxt->options & XML_PARSE_IGNORE_ENC) == 0)) {
+        xmlCharEncodingHandlerPtr handler;
+
+        handler = xmlFindCharEncodingHandler((const char *) encoding);
+        if (handler == NULL) {
+            __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+                             "Unsupported encoding: %s\n",
+                             encoding, NULL);
+            return;
+        }
+
+        xmlSwitchToEncoding(ctxt, handler);
+        ctxt->input->flags |= XML_INPUT_USES_ENC_DECL;
+    } else if (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) {
+        static const char *allowedUTF8[] = {
+            "UTF-8", "UTF8", NULL
+        };
+        static const char *allowedUTF16LE[] = {
+            "UTF-16", "UTF-16LE", "UTF16", NULL
+        };
+        static const char *allowedUTF16BE[] = {
+            "UTF-16", "UTF-16BE", "UTF16", NULL
+        };
+        const char **allowed = NULL;
+        const char *autoEnc = NULL;
+
+        switch (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) {
+            case XML_INPUT_AUTO_UTF8:
+                allowed = allowedUTF8;
+                autoEnc = "UTF-8";
+                break;
+            case XML_INPUT_AUTO_UTF16LE:
+                allowed = allowedUTF16LE;
+                autoEnc = "UTF-16LE";
+                break;
+            case XML_INPUT_AUTO_UTF16BE:
+                allowed = allowedUTF16BE;
+                autoEnc = "UTF-16BE";
+                break;
+        }
+
+        if (allowed != NULL) {
+            const char **p;
+            int match = 0;
+
+            for (p = allowed; *p != NULL; p++) {
+                if (xmlStrcasecmp(encoding, BAD_CAST *p) == 0) {
+                    match = 1;
+                    break;
+                }
+            }
+
+            if (match == 0) {
+                xmlWarningMsg(ctxt, XML_WAR_ENCODING_MISMATCH,
+                              "Encoding '%s' doesn't match "
+                              "auto-detected '%s'\n",
+                              encoding, BAD_CAST autoEnc);
+            }
+        }
+    }
+}
+
 /************************************************************************
  *									*
  *	Commodity functions to handle entities processing		*
@@ -1572,7 +1626,6 @@
 
     if (input->filename != NULL) xmlFree((char *) input->filename);
     if (input->directory != NULL) xmlFree((char *) input->directory);
-    if (input->encoding != NULL) xmlFree((char *) input->encoding);
     if (input->version != NULL) xmlFree((char *) input->version);
     if ((input->free != NULL) && (input->base != NULL))
         input->free((xmlChar *) input->base);
@@ -1601,7 +1654,6 @@
     memset(input, 0, sizeof(xmlParserInput));
     input->line = 1;
     input->col = 1;
-    input->standalone = -1;
 
     /*
      * If the context is NULL the id cannot be initialized, but that
@@ -1744,9 +1796,7 @@
     if (xmlParserDebugEntities)
 	xmlGenericError(xmlGenericErrorContext,
 		"new fixed input: %.30s\n", buffer);
-    buf = xmlParserInputBufferCreateMem((const char *) buffer,
-                                        xmlStrlen(buffer),
-                                        XML_CHAR_ENCODING_NONE);
+    buf = xmlParserInputBufferCreateString(buffer);
     if (buf == NULL) {
 	xmlErrMemory(ctxt, NULL);
         return(NULL);
@@ -2016,11 +2066,11 @@
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
     ctxt->depth = 0;
-    ctxt->charset = XML_CHAR_ENCODING_UTF8;
     ctxt->catalogs = NULL;
     ctxt->sizeentities = 0;
     ctxt->sizeentcopy = 0;
     ctxt->input_id = 1;
+    ctxt->maxAmpl = XML_MAX_AMPLIFICATION_DEFAULT;
     xmlInitNodeInfoSeq(&ctxt->node_seq);
     return(0);
 }
@@ -2471,7 +2521,10 @@
     int old = xmlKeepBlanksDefaultValue;
 
     xmlKeepBlanksDefaultValue = val;
-    if (!val) xmlIndentTreeOutput = 1;
+#ifdef LIBXML_OUTPUT_ENABLED
+    if (!val)
+        xmlIndentTreeOutput = 1;
+#endif
     return(old);
 }
 
diff --git a/third_party/libxml/src/pattern.c b/third_party/libxml/src/pattern.c
index 04a4eb7..55ae2d3e 100644
--- a/third_party/libxml/src/pattern.c
+++ b/third_party/libxml/src/pattern.c
@@ -27,18 +27,15 @@
 #include "libxml.h"
 
 #include <string.h>
+#include <libxml/pattern.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
-#include <libxml/hash.h>
 #include <libxml/dict.h>
 #include <libxml/xmlerror.h>
 #include <libxml/parserInternals.h>
-#include <libxml/pattern.h>
 
 #ifdef LIBXML_PATTERN_ENABLED
 
-/* #define DEBUG_STREAMING */
-
 #ifdef ERROR
 #undef ERROR
 #endif
@@ -935,7 +932,6 @@
 
 	if (IS_BLANK_CH(CUR)) {
 	    ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
-	    XML_PAT_FREE_STRING(ctxt, prefix);
 	    ctxt->error = 1;
 	    goto error;
 	}
@@ -960,12 +956,12 @@
 		ERROR5(NULL, NULL, NULL,
 		    "xmlCompileAttributeTest : no namespace bound to prefix %s\n",
 		    prefix);
-	        XML_PAT_FREE_STRING(ctxt, prefix);
 		ctxt->error = 1;
 		goto error;
 	    }
 	}
-	XML_PAT_FREE_STRING(ctxt, prefix);
+        XML_PAT_FREE_STRING(ctxt, name);
+        name = NULL;
 	if (token == NULL) {
 	    if (CUR == '*') {
 		NEXT;
@@ -984,6 +980,8 @@
     }
     return;
 error:
+    if (name != NULL)
+	XML_PAT_FREE_STRING(ctxt, name);
     if (URL != NULL)
 	XML_PAT_FREE_STRING(ctxt, URL)
     if (token != NULL)
@@ -1415,62 +1413,6 @@
  *									*
  ************************************************************************/
 
-#ifdef DEBUG_STREAMING
-static void
-xmlDebugStreamComp(xmlStreamCompPtr stream) {
-    int i;
-
-    if (stream == NULL) {
-        printf("Stream: NULL\n");
-	return;
-    }
-    printf("Stream: %d steps\n", stream->nbStep);
-    for (i = 0;i < stream->nbStep;i++) {
-	if (stream->steps[i].ns != NULL) {
-	    printf("{%s}", stream->steps[i].ns);
-	}
-        if (stream->steps[i].name == NULL) {
-	    printf("* ");
-	} else {
-	    printf("%s ", stream->steps[i].name);
-	}
-	if (stream->steps[i].flags & XML_STREAM_STEP_ROOT)
-	    printf("root ");
-	if (stream->steps[i].flags & XML_STREAM_STEP_DESC)
-	    printf("// ");
-	if (stream->steps[i].flags & XML_STREAM_STEP_FINAL)
-	    printf("final ");
-	printf("\n");
-    }
-}
-static void
-xmlDebugStreamCtxt(xmlStreamCtxtPtr ctxt, int match) {
-    int i;
-
-    if (ctxt == NULL) {
-        printf("Stream: NULL\n");
-	return;
-    }
-    printf("Stream: level %d, %d states: ", ctxt->level, ctxt->nbState);
-    if (match)
-        printf("matches\n");
-    else
-        printf("\n");
-    for (i = 0;i < ctxt->nbState;i++) {
-        if (ctxt->states[2 * i] < 0)
-	    printf(" %d: free\n", i);
-	else {
-	    printf(" %d: step %d, level %d", i, ctxt->states[2 * i],
-	           ctxt->states[(2 * i) + 1]);
-            if (ctxt->comp->steps[ctxt->states[2 * i]].flags &
-	        XML_STREAM_STEP_DESC)
-	        printf(" //\n");
-	    else
-	        printf("\n");
-	}
-    }
-}
-#endif
 /**
  * xmlNewStreamComp:
  * @size: the number of expected steps
@@ -1729,9 +1671,6 @@
     stream->steps[s].flags |= XML_STREAM_STEP_FINAL;
     if (root)
 	stream->steps[0].flags |= XML_STREAM_STEP_ROOT;
-#ifdef DEBUG_STREAMING
-    xmlDebugStreamComp(stream);
-#endif
     comp->stream = stream;
     return(0);
 error:
@@ -1852,9 +1791,6 @@
     int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc;
     xmlStreamCompPtr comp;
     xmlStreamStep step;
-#ifdef DEBUG_STREAMING
-    xmlStreamCtxtPtr orig = stream;
-#endif
 
     if ((stream == NULL) || (stream->nbState < 0))
         return(-1);
@@ -2172,9 +2108,6 @@
 
     if (err > 0)
         ret = -1;
-#ifdef DEBUG_STREAMING
-    xmlDebugStreamCtxt(orig, ret);
-#endif
     return(ret);
 }
 
diff --git a/third_party/libxml/src/runsuite.c b/third_party/libxml/src/runsuite.c
index 750df2a2..c1d35ad 100644
--- a/third_party/libxml/src/runsuite.c
+++ b/third_party/libxml/src/runsuite.c
@@ -6,9 +6,8 @@
  * daniel@veillard.com
  */
 
-#include "libxml.h"
 #include <stdio.h>
-
+#include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 
@@ -201,9 +200,6 @@
 
 static void
 initializeLibxml2(void) {
-    xmlGetWarningsDefaultValue = 0;
-    xmlPedanticParserDefault(0);
-
     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
     xmlInitParser();
     xmlSetExternalEntityLoader(testExternalEntityLoader);
diff --git a/third_party/libxml/src/runtest.c b/third_party/libxml/src/runtest.c
index 20c991ea..ed1dfab 100644
--- a/third_party/libxml/src/runtest.c
+++ b/third_party/libxml/src/runtest.c
@@ -11,14 +11,14 @@
  * daniel@veillard.com
  */
 
-#include "libxml.h"
+#include "config.h"
 #include <stdio.h>
-
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #elif defined (_WIN32)
 #include <io.h>
 #endif
+#include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -66,11 +66,9 @@
 #endif
 
 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
-#include <libxml/globals.h>
 #include <libxml/threads.h>
 #include <libxml/parser.h>
 #include <libxml/catalog.h>
-#include <string.h>
 #endif
 
 /*
@@ -558,7 +556,6 @@
     xmlMemStrdup = NULL;
     xmlInitParser();
     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
-    xmlPedanticParserDefault(0);
     xmlSetExternalEntityLoader(testExternalEntityLoader);
     xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
 #ifdef LIBXML_SCHEMAS_ENABLED
@@ -2473,6 +2470,7 @@
     return(0);
 }
 
+#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_HTML_ENABLED)
 /**
  * fdParseTest:
  * @filename: the file to parse
@@ -2537,7 +2535,7 @@
 
     return(0);
 }
-
+#endif
 
 
 #ifdef LIBXML_READER_ENABLED
@@ -4065,9 +4063,6 @@
     /*
      * load XPath expr as a file
      */
-    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
-    xmlSubstituteEntitiesDefault(1);
-
     doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
     if (doc == NULL) {
 	fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
@@ -4216,9 +4211,6 @@
      * build an XML tree from a the file; we need to add default
      * attributes and resolve all character and entities references
      */
-    xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
-    xmlSubstituteEntitiesDefault(1);
-
     doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
     if (doc == NULL) {
 	fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
@@ -4391,13 +4383,6 @@
 static const unsigned int num_threads = sizeof(threadParams) /
                                         sizeof(threadParams[0]);
 
-#ifndef xmlDoValidityCheckingDefaultValue
-#error xmlDoValidityCheckingDefaultValue is not a macro
-#endif
-#ifndef xmlGenericErrorContext
-#error xmlGenericErrorContext is not a macro
-#endif
-
 static void *
 thread_specific_data(void *private_data)
 {
@@ -4406,43 +4391,13 @@
     const char *filename = params->filename;
     int okay = 1;
 
-    if (!strcmp(filename, "test/threads/invalid.xml")) {
-        xmlDoValidityCheckingDefaultValue = 0;
-        xmlGenericErrorContext = stdout;
-    } else {
-        xmlDoValidityCheckingDefaultValue = 1;
-        xmlGenericErrorContext = stderr;
-    }
-#ifdef LIBXML_SAX1_ENABLED
-    myDoc = xmlParseFile(filename);
-#else
-    myDoc = xmlReadFile(filename, NULL, XML_WITH_CATALOG);
-#endif
+    myDoc = xmlReadFile(filename, NULL, XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
     if (myDoc) {
         xmlFreeDoc(myDoc);
     } else {
         printf("parse failed\n");
         okay = 0;
     }
-    if (!strcmp(filename, "test/threads/invalid.xml")) {
-        if (xmlDoValidityCheckingDefaultValue != 0) {
-            printf("ValidityCheckingDefaultValue override failed\n");
-            okay = 0;
-        }
-        if (xmlGenericErrorContext != stdout) {
-            printf("xmlGenericErrorContext override failed\n");
-            okay = 0;
-        }
-    } else {
-        if (xmlDoValidityCheckingDefaultValue != 1) {
-            printf("ValidityCheckingDefaultValue override failed\n");
-            okay = 0;
-        }
-        if (xmlGenericErrorContext != stderr) {
-            printf("xmlGenericErrorContext override failed\n");
-            okay = 0;
-        }
-    }
     params->okay = okay;
     return(NULL);
 }
diff --git a/third_party/libxml/src/runxmlconf.c b/third_party/libxml/src/runxmlconf.c
index f440bdc19..cb1ef5e 100644
--- a/third_party/libxml/src/runxmlconf.c
+++ b/third_party/libxml/src/runxmlconf.c
@@ -6,10 +6,10 @@
  * daniel@veillard.com
  */
 
-#include "libxml.h"
 #include <stdio.h>
+#include <libxml/xmlversion.h>
 
-#ifdef LIBXML_XPATH_ENABLED
+#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_VALID_ENABLED)
 
 #include <string.h>
 #include <sys/stat.h>
@@ -148,9 +148,6 @@
 
 static void
 initializeLibxml2(void) {
-    xmlGetWarningsDefaultValue = 0;
-    xmlPedanticParserDefault(0);
-
     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
     xmlInitParser();
     xmlSetExternalEntityLoader(testExternalEntityLoader);
@@ -252,8 +249,10 @@
         nb_errors++;
 	ret = 0;
     } else {
-	if ((xmlLastError.code == XML_ERR_OK) ||
-	    (xmlLastError.domain != XML_FROM_NAMESPACE)) {
+        xmlError *error = xmlGetLastError();
+
+	if ((error->code == XML_ERR_OK) ||
+	    (error->domain != XML_FROM_NAMESPACE)) {
 	    test_log("test %s : %s failed to detect namespace error\n",
 		     id, filename);
 	    nb_errors++;
@@ -593,9 +592,9 @@
 }
 
 #else /* ! LIBXML_XPATH_ENABLED */
-#include <stdio.h>
 int
 main(int argc ATTRIBUTE_UNUSED, char **argv) {
-    fprintf(stderr, "%s need XPath support\n", argv[0]);
+    fprintf(stderr, "%s need XPath and validation support\n", argv[0]);
+    return(0);
 }
 #endif
diff --git a/third_party/libxml/src/testModule.c b/third_party/libxml/src/testModule.c
index 45edd9f..6aea44d 100644
--- a/third_party/libxml/src/testModule.c
+++ b/third_party/libxml/src/testModule.c
@@ -6,12 +6,12 @@
  * joelwreed@comcast.net
  */
 
-#include "libxml.h"
-#ifdef LIBXML_MODULES_ENABLED
+#include <stdio.h>
 #include <libxml/xmlversion.h>
 
+#ifdef LIBXML_MODULES_ENABLED
+
 #include <limits.h>
-#include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
 
@@ -74,7 +74,6 @@
 }
 
 #else
-#include <stdio.h>
 int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
     printf("%s : Module support not compiled in\n", argv[0]);
     return(0);
diff --git a/third_party/libxml/src/testThreads.c b/third_party/libxml/src/testThreads.c
index d153594..fd1f885 100644
--- a/third_party/libxml/src/testThreads.c
+++ b/third_party/libxml/src/testThreads.c
@@ -1,12 +1,11 @@
-#include "libxml.h"
-
+#include "config.h"
 #include <stdlib.h>
 #include <stdio.h>
 
-#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
-#include <libxml/globals.h>
-#include <libxml/threads.h>
 #include <libxml/parser.h>
+#include <libxml/threads.h>
+
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
 #include <libxml/catalog.h>
 #ifdef HAVE_PTHREAD_H
 #include <pthread.h>
@@ -42,13 +41,6 @@
 static const unsigned int num_threads = sizeof(threadParams) /
                                         sizeof(threadParams[0]);
 
-#ifndef xmlDoValidityCheckingDefaultValue
-#error xmlDoValidityCheckingDefaultValue is not a macro
-#endif
-#ifndef xmlGenericErrorContext
-#error xmlGenericErrorContext is not a macro
-#endif
-
 static void *
 thread_specific_data(void *private_data)
 {
@@ -56,59 +48,61 @@
     xmlThreadParams *params = (xmlThreadParams *) private_data;
     const char *filename = params->filename;
     int okay = 1;
+    int options = 0;
 
-    if (!strcmp(filename, "test/threads/invalid.xml")) {
-        xmlDoValidityCheckingDefaultValue = 0;
-        xmlGenericErrorContext = stdout;
-    } else {
-        xmlDoValidityCheckingDefaultValue = 1;
-        xmlGenericErrorContext = stderr;
+    if (xmlCheckThreadLocalStorage() != 0) {
+        printf("xmlCheckThreadLocalStorage failed\n");
+        params->okay = 0;
+        return(NULL);
     }
-#ifdef LIBXML_SAX1_ENABLED
-    myDoc = xmlParseFile(filename);
-#else
-    myDoc = xmlReadFile(filename, NULL, XML_WITH_CATALOG);
-#endif
+
+    if (strcmp(filename, "test/threads/invalid.xml") != 0) {
+        options |= XML_PARSE_DTDVALID;
+    }
+    myDoc = xmlReadFile(filename, NULL, options);
     if (myDoc) {
         xmlFreeDoc(myDoc);
     } else {
         printf("parse failed\n");
 	okay = 0;
     }
-    if (!strcmp(filename, "test/threads/invalid.xml")) {
-        if (xmlDoValidityCheckingDefaultValue != 0) {
-	    printf("ValidityCheckingDefaultValue override failed\n");
-	    okay = 0;
-	}
-        if (xmlGenericErrorContext != stdout) {
-	    printf("xmlGenericErrorContext override failed\n");
-	    okay = 0;
-	}
-    } else {
-        if (xmlDoValidityCheckingDefaultValue != 1) {
-	    printf("ValidityCheckingDefaultValue override failed\n");
-	    okay = 0;
-	}
-        if (xmlGenericErrorContext != stderr) {
-	    printf("xmlGenericErrorContext override failed\n");
-	    okay = 0;
-	}
-    }
     params->okay = okay;
     return(NULL);
 }
 
-#ifdef HAVE_PTHREAD_H
+#ifdef _WIN32
+static DWORD WINAPI
+win32_thread_specific_data(void *private_data)
+{
+    thread_specific_data(private_data);
+    return(0);
+}
+#endif
+#endif /* LIBXML_THREADS_ENABLED */
+
 int
 main(void)
 {
-    unsigned int i, repeat;
-    int ret;
+    unsigned int repeat;
+    int status = 0;
+
+    (void) repeat;
 
     xmlInitParser();
+
+    if (xmlCheckThreadLocalStorage() != 0) {
+        printf("xmlCheckThreadLocalStorage failed for main thread\n");
+        return(1);
+    }
+
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
     for (repeat = 0;repeat < TEST_REPEAT_COUNT;repeat++) {
+        unsigned int i;
+        int ret;
+
 	xmlLoadCatalog(catalog);
 
+#ifdef HAVE_PTHREAD_H
         memset(tid, 0xff, sizeof(*tid)*num_threads);
 
 	for (i = 0; i < num_threads; i++) {
@@ -127,35 +121,7 @@
 		exit(1);
 	    }
 	}
-
-	xmlCatalogCleanup();
-	for (i = 0; i < num_threads; i++)
-	    if (threadParams[i].okay == 0)
-		printf("Thread %d handling %s failed\n", i,
-                       threadParams[i].filename);
-    }
-    xmlCleanupParser();
-    return (0);
-}
 #elif defined(_WIN32)
-static DWORD WINAPI
-win32_thread_specific_data(void *private_data)
-{
-    thread_specific_data(private_data);
-    return(0);
-}
-
-int
-main(void)
-{
-    unsigned int i, repeat;
-    BOOL ret;
-
-    xmlInitParser();
-    for (repeat = 0;repeat < TEST_REPEAT_COUNT;repeat++)
-    {
-        xmlLoadCatalog(catalog);
-
         for (i = 0; i < num_threads; i++)
         {
             tid[i] = (HANDLE) -1;
@@ -187,26 +153,22 @@
             }
             CloseHandle (tid[i]);
         }
+#endif /* pthreads */
 
-        xmlCatalogCleanup();
-        for (i = 0; i < num_threads; i++) {
-            if (threadParams[i].okay == 0)
-            printf("Thread %d handling %s failed\n", i,
-                   threadParams[i].filename);
+	xmlCatalogCleanup();
+
+	for (i = 0; i < num_threads; i++) {
+	    if (threadParams[i].okay == 0) {
+		printf("Thread %d handling %s failed\n", i,
+                       threadParams[i].filename);
+                status = 1;
+            }
         }
     }
+#endif /* LIBXML_THREADS_ENABLED */
 
     xmlCleanupParser();
 
-    return (0);
+    return (status);
 }
-#endif /* pthreads */
 
-#else /* !LIBXML_THREADS_ENABLED */
-int
-main(void)
-{
-    fprintf(stderr, "libxml was not compiled with thread or catalog support\n");
-    return (0);
-}
-#endif
diff --git a/third_party/libxml/src/testapi.c b/third_party/libxml/src/testapi.c
index fd3fc94..7337b34 100644
--- a/third_party/libxml/src/testapi.c
+++ b/third_party/libxml/src/testapi.c
@@ -11,14 +11,13 @@
 /* Disable deprecation warnings */
 #define XML_DEPRECATED
 
-#include "libxml.h"
 #include <stdio.h>
-
 #include <stdlib.h>
 #include <string.h>
 #include <libxml/xmlerror.h>
 #include <libxml/catalog.h>
 #include <libxml/relaxng.h>
+#include <libxml/parser.h>
 
 
 static int testlibxml2(void);
@@ -1640,8 +1639,8 @@
     htmlDocPtr ret_val;
     htmlParserCtxtPtr ctxt; /* an HTML parser context */
     int n_ctxt;
-    xmlChar * cur; /* a pointer to a zero terminated string */
-    int n_cur;
+    xmlChar * str; /* a pointer to a zero terminated string */
+    int n_str;
     const char * URL; /* the base URL to use for the document */
     int n_URL;
     char * encoding; /* the document encoding, or NULL */
@@ -1650,22 +1649,22 @@
     int n_options;
 
     for (n_ctxt = 0;n_ctxt < gen_nb_htmlParserCtxtPtr;n_ctxt++) {
-    for (n_cur = 0;n_cur < gen_nb_const_xmlChar_ptr;n_cur++) {
+    for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) {
     for (n_URL = 0;n_URL < gen_nb_filepath;n_URL++) {
     for (n_encoding = 0;n_encoding < gen_nb_const_char_ptr;n_encoding++) {
     for (n_options = 0;n_options < gen_nb_int;n_options++) {
         mem_base = xmlMemBlocks();
         ctxt = gen_htmlParserCtxtPtr(n_ctxt, 0);
-        cur = gen_const_xmlChar_ptr(n_cur, 1);
+        str = gen_const_xmlChar_ptr(n_str, 1);
         URL = gen_filepath(n_URL, 2);
         encoding = gen_const_char_ptr(n_encoding, 3);
         options = gen_int(n_options, 4);
 
-        ret_val = htmlCtxtReadDoc(ctxt, (const xmlChar *)cur, URL, (const char *)encoding, options);
+        ret_val = htmlCtxtReadDoc(ctxt, (const xmlChar *)str, URL, (const char *)encoding, options);
         desret_htmlDocPtr(ret_val);
         call_tests++;
         des_htmlParserCtxtPtr(n_ctxt, ctxt, 0);
-        des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 1);
+        des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1);
         des_filepath(n_URL, URL, 2);
         des_const_char_ptr(n_encoding, (const char *)encoding, 3);
         des_int(n_options, options, 4);
@@ -1675,7 +1674,7 @@
 	           xmlMemBlocks() - mem_base);
 	    test_ret++;
             printf(" %d", n_ctxt);
-            printf(" %d", n_cur);
+            printf(" %d", n_str);
             printf(" %d", n_URL);
             printf(" %d", n_encoding);
             printf(" %d", n_options);
@@ -5299,12 +5298,13 @@
     for (n_version = 0;n_version < gen_nb_int;n_version++) {
         mem_base = xmlMemBlocks();
         version = gen_int(n_version, 0);
-
+        
         {
             int original_version = xmlSAXDefaultVersion(2);
 
 
         ret_val = xmlSAXDefaultVersion(version);
+        
             (void)xmlSAXDefaultVersion(original_version);
         }
 
@@ -5417,7 +5417,7 @@
 test_xmlC14NDocDumpMemory(void) {
     int test_ret = 0;
 
-#if defined(LIBXML_C14N_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
+#if defined(LIBXML_C14N_ENABLED)
     int mem_base;
     int ret_val;
     xmlDocPtr doc; /* the XML document for canonization */
@@ -5486,7 +5486,7 @@
 test_xmlC14NDocSave(void) {
     int test_ret = 0;
 
-#if defined(LIBXML_C14N_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
+#if defined(LIBXML_C14N_ENABLED)
     int mem_base;
     int ret_val;
     xmlDocPtr doc; /* the XML document for canonization */
@@ -5562,7 +5562,7 @@
 test_xmlC14NDocSaveTo(void) {
     int test_ret = 0;
 
-#if defined(LIBXML_C14N_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
+#if defined(LIBXML_C14N_ENABLED)
     int mem_base;
     int ret_val;
     xmlDocPtr doc; /* the XML document for canonization */
@@ -12140,23 +12140,23 @@
 
     int mem_base;
     xmlParserCtxtPtr ret_val;
-    xmlChar * cur; /* a pointer to an array of xmlChar */
-    int n_cur;
+    xmlChar * str; /* a pointer to an array of xmlChar */
+    int n_str;
 
-    for (n_cur = 0;n_cur < gen_nb_const_xmlChar_ptr;n_cur++) {
+    for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) {
         mem_base = xmlMemBlocks();
-        cur = gen_const_xmlChar_ptr(n_cur, 0);
+        str = gen_const_xmlChar_ptr(n_str, 0);
 
-        ret_val = xmlCreateDocParserCtxt((const xmlChar *)cur);
+        ret_val = xmlCreateDocParserCtxt((const xmlChar *)str);
         desret_xmlParserCtxtPtr(ret_val);
         call_tests++;
-        des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 0);
+        des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 0);
         xmlResetLastError();
         if (mem_base != xmlMemBlocks()) {
             printf("Leak of %d blocks found in xmlCreateDocParserCtxt",
 	           xmlMemBlocks() - mem_base);
 	    test_ret++;
-            printf(" %d", n_cur);
+            printf(" %d", n_str);
             printf("\n");
         }
     }
@@ -12239,8 +12239,8 @@
     xmlDocPtr ret_val;
     xmlParserCtxtPtr ctxt; /* an XML parser context */
     int n_ctxt;
-    xmlChar * cur; /* a pointer to a zero terminated string */
-    int n_cur;
+    xmlChar * str; /* a pointer to a zero terminated string */
+    int n_str;
     const char * URL; /* the base URL to use for the document */
     int n_URL;
     char * encoding; /* the document encoding, or NULL */
@@ -12249,22 +12249,22 @@
     int n_options;
 
     for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) {
-    for (n_cur = 0;n_cur < gen_nb_const_xmlChar_ptr;n_cur++) {
+    for (n_str = 0;n_str < gen_nb_const_xmlChar_ptr;n_str++) {
     for (n_URL = 0;n_URL < gen_nb_filepath;n_URL++) {
     for (n_encoding = 0;n_encoding < gen_nb_const_char_ptr;n_encoding++) {
     for (n_options = 0;n_options < gen_nb_parseroptions;n_options++) {
         mem_base = xmlMemBlocks();
         ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0);
-        cur = gen_const_xmlChar_ptr(n_cur, 1);
+        str = gen_const_xmlChar_ptr(n_str, 1);
         URL = gen_filepath(n_URL, 2);
         encoding = gen_const_char_ptr(n_encoding, 3);
         options = gen_parseroptions(n_options, 4);
 
-        ret_val = xmlCtxtReadDoc(ctxt, (const xmlChar *)cur, URL, (const char *)encoding, options);
+        ret_val = xmlCtxtReadDoc(ctxt, (const xmlChar *)str, URL, (const char *)encoding, options);
         desret_xmlDocPtr(ret_val);
         call_tests++;
         des_xmlParserCtxtPtr(n_ctxt, ctxt, 0);
-        des_const_xmlChar_ptr(n_cur, (const xmlChar *)cur, 1);
+        des_const_xmlChar_ptr(n_str, (const xmlChar *)str, 1);
         des_filepath(n_URL, URL, 2);
         des_const_char_ptr(n_encoding, (const char *)encoding, 3);
         des_parseroptions(n_options, options, 4);
@@ -12274,7 +12274,7 @@
 	           xmlMemBlocks() - mem_base);
 	    test_ret++;
             printf(" %d", n_ctxt);
-            printf(" %d", n_cur);
+            printf(" %d", n_str);
             printf(" %d", n_URL);
             printf(" %d", n_encoding);
             printf(" %d", n_options);
@@ -12508,6 +12508,16 @@
 
 
 static int
+test_xmlCtxtSetMaxAmplification(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
 test_xmlCtxtUseOptions(void) {
     int test_ret = 0;
 
@@ -14757,11 +14767,267 @@
     return(test_ret);
 }
 
+
+static int
+test_xmlThrDefDoValidityCheckingDefaultValue(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefDoValidityCheckingDefaultValue(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefDoValidityCheckingDefaultValue",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefGetWarningsDefaultValue(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefGetWarningsDefaultValue(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefGetWarningsDefaultValue",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefKeepBlanksDefaultValue(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefKeepBlanksDefaultValue(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefKeepBlanksDefaultValue",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefLineNumbersDefaultValue(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefLineNumbersDefaultValue(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefLineNumbersDefaultValue",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefLoadExtDtdDefaultValue(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefLoadExtDtdDefaultValue(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefLoadExtDtdDefaultValue",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefParserDebugEntities(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefParserDebugEntities(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefParserDebugEntities",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefPedanticParserDefaultValue(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefPedanticParserDefaultValue(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefPedanticParserDefaultValue",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefSubstituteEntitiesDefaultValue(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefSubstituteEntitiesDefaultValue(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefSubstituteEntitiesDefaultValue",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
 static int
 test_parser(void) {
     int test_ret = 0;
 
-    if (quiet == 0) printf("Testing parser : 59 of 71 functions ...\n");
+    if (quiet == 0) printf("Testing parser : 67 of 80 functions ...\n");
     test_ret += test_xmlByteConsumed();
     test_ret += test_xmlClearNodeInfoSeq();
     test_ret += test_xmlClearParserCtxt();
@@ -14772,6 +15038,7 @@
     test_ret += test_xmlCtxtReadMemory();
     test_ret += test_xmlCtxtReset();
     test_ret += test_xmlCtxtResetPush();
+    test_ret += test_xmlCtxtSetMaxAmplification();
     test_ret += test_xmlCtxtUseOptions();
     test_ret += test_xmlGetExternalEntityLoader();
     test_ret += test_xmlHasFeature();
@@ -14823,6 +15090,14 @@
     test_ret += test_xmlSetupParserForBuffer();
     test_ret += test_xmlStopParser();
     test_ret += test_xmlSubstituteEntitiesDefault();
+    test_ret += test_xmlThrDefDoValidityCheckingDefaultValue();
+    test_ret += test_xmlThrDefGetWarningsDefaultValue();
+    test_ret += test_xmlThrDefKeepBlanksDefaultValue();
+    test_ret += test_xmlThrDefLineNumbersDefaultValue();
+    test_ret += test_xmlThrDefLoadExtDtdDefaultValue();
+    test_ret += test_xmlThrDefParserDebugEntities();
+    test_ret += test_xmlThrDefPedanticParserDefaultValue();
+    test_ret += test_xmlThrDefSubstituteEntitiesDefaultValue();
 
     if (test_ret != 0)
 	printf("Module parser: %d errors\n", test_ret);
@@ -19107,6 +19382,16 @@
 
 
 static int
+test_xmlDeregisterNodeDefault(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
 test_xmlDocCopyNode(void) {
     int test_ret = 0;
 
@@ -22217,6 +22502,16 @@
 
 
 static int
+test_xmlRegisterNodeDefault(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
 test_xmlRemoveProp(void) {
     int test_ret = 0;
 
@@ -23181,6 +23476,90 @@
 
 
 static int
+test_xmlThrDefBufferAllocScheme(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    xmlBufferAllocationScheme ret_val;
+    xmlBufferAllocationScheme v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_xmlBufferAllocationScheme;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_xmlBufferAllocationScheme(n_v, 0);
+
+        ret_val = xmlThrDefBufferAllocScheme(v);
+        desret_xmlBufferAllocationScheme(ret_val);
+        call_tests++;
+        des_xmlBufferAllocationScheme(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefBufferAllocScheme",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefDefaultBufferSize(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefDefaultBufferSize(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefDefaultBufferSize",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefDeregisterNodeDefault(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefRegisterNodeDefault(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
 test_xmlUnsetNsProp(void) {
     int test_ret = 0;
 
@@ -23273,7 +23652,6 @@
 test_xmlValidateNCName(void) {
     int test_ret = 0;
 
-#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
 #ifdef LIBXML_TREE_ENABLED
     int mem_base;
     int ret_val;
@@ -23306,7 +23684,6 @@
     }
     function_tests++;
 #endif
-#endif
 
     return(test_ret);
 }
@@ -23444,7 +23821,7 @@
 test_tree(void) {
     int test_ret = 0;
 
-    if (quiet == 0) printf("Testing tree : 142 of 164 functions ...\n");
+    if (quiet == 0) printf("Testing tree : 144 of 170 functions ...\n");
     test_ret += test_xmlAddChild();
     test_ret += test_xmlAddChildList();
     test_ret += test_xmlAddNextSibling();
@@ -23491,6 +23868,7 @@
     test_ret += test_xmlDOMWrapNewCtxt();
     test_ret += test_xmlDOMWrapReconcileNamespaces();
     test_ret += test_xmlDOMWrapRemoveNode();
+    test_ret += test_xmlDeregisterNodeDefault();
     test_ret += test_xmlDocCopyNode();
     test_ret += test_xmlDocCopyNodeList();
     test_ret += test_xmlDocDump();
@@ -23566,6 +23944,7 @@
     test_ret += test_xmlNodeSetSpacePreserve();
     test_ret += test_xmlPreviousElementSibling();
     test_ret += test_xmlReconciliateNs();
+    test_ret += test_xmlRegisterNodeDefault();
     test_ret += test_xmlRemoveProp();
     test_ret += test_xmlReplaceNode();
     test_ret += test_xmlSaveFile();
@@ -23588,6 +23967,10 @@
     test_ret += test_xmlStringLenGetNodeList();
     test_ret += test_xmlTextConcat();
     test_ret += test_xmlTextMerge();
+    test_ret += test_xmlThrDefBufferAllocScheme();
+    test_ret += test_xmlThrDefDefaultBufferSize();
+    test_ret += test_xmlThrDefDeregisterNodeDefault();
+    test_ret += test_xmlThrDefRegisterNodeDefault();
     test_ret += test_xmlUnsetNsProp();
     test_ret += test_xmlUnsetProp();
     test_ret += test_xmlValidateNCName();
@@ -25772,7 +26155,7 @@
     int n_ctxt;
     xmlDocPtr doc; /* a document instance */
     int n_doc;
-    xmlNodePtr root; /*  */
+    xmlNodePtr root; /* an element instance */
     int n_root;
 
     for (n_ctxt = 0;n_ctxt < gen_nb_xmlValidCtxtPtr;n_ctxt++) {
@@ -27782,6 +28165,16 @@
 
 
 static int
+test_xmlOutputBufferCreateFilenameDefault(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
 test_xmlOutputBufferFlush(void) {
     int test_ret = 0;
 
@@ -28090,6 +28483,16 @@
 
 
 static int
+test_xmlParserInputBufferCreateFilenameDefault(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
 test_xmlParserInputBufferCreateMem(void) {
     int test_ret = 0;
 
@@ -28438,11 +28841,31 @@
     return(test_ret);
 }
 
+
+static int
+test_xmlThrDefOutputBufferCreateFilenameDefault(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefParserInputBufferCreateFilenameDefault(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
 static int
 test_xmlIO(void) {
     int test_ret = 0;
 
-    if (quiet == 0) printf("Testing xmlIO : 41 of 51 functions ...\n");
+    if (quiet == 0) printf("Testing xmlIO : 41 of 55 functions ...\n");
     test_ret += test_xmlAllocOutputBuffer();
     test_ret += test_xmlAllocParserInputBuffer();
     test_ret += test_xmlCheckFilename();
@@ -28467,6 +28890,7 @@
     test_ret += test_xmlOutputBufferCreateFd();
     test_ret += test_xmlOutputBufferCreateFile();
     test_ret += test_xmlOutputBufferCreateFilename();
+    test_ret += test_xmlOutputBufferCreateFilenameDefault();
     test_ret += test_xmlOutputBufferFlush();
     test_ret += test_xmlOutputBufferGetContent();
     test_ret += test_xmlOutputBufferGetSize();
@@ -28477,6 +28901,7 @@
     test_ret += test_xmlParserInputBufferCreateFd();
     test_ret += test_xmlParserInputBufferCreateFile();
     test_ret += test_xmlParserInputBufferCreateFilename();
+    test_ret += test_xmlParserInputBufferCreateFilenameDefault();
     test_ret += test_xmlParserInputBufferCreateMem();
     test_ret += test_xmlParserInputBufferCreateStatic();
     test_ret += test_xmlParserInputBufferGrow();
@@ -28487,6 +28912,8 @@
     test_ret += test_xmlRegisterDefaultInputCallbacks();
     test_ret += test_xmlRegisterDefaultOutputCallbacks();
     test_ret += test_xmlRegisterHTTPPostCallbacks();
+    test_ret += test_xmlThrDefOutputBufferCreateFilenameDefault();
+    test_ret += test_xmlThrDefParserInputBufferCreateFilenameDefault();
 
     if (test_ret != 0)
 	printf("Module xmlIO: %d errors\n", test_ret);
@@ -29099,11 +29526,31 @@
     return(test_ret);
 }
 
+
+static int
+test_xmlThrDefSetGenericErrorFunc(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefSetStructuredErrorFunc(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
 static int
 test_xmlerror(void) {
     int test_ret = 0;
 
-    if (quiet == 0) printf("Testing xmlerror : 7 of 15 functions ...\n");
+    if (quiet == 0) printf("Testing xmlerror : 7 of 17 functions ...\n");
     test_ret += test_initGenericErrorDefaultFunc();
     test_ret += test_xmlCopyError();
     test_ret += test_xmlCtxtGetLastError();
@@ -29119,6 +29566,8 @@
     test_ret += test_xmlResetLastError();
     test_ret += test_xmlSetGenericErrorFunc();
     test_ret += test_xmlSetStructuredErrorFunc();
+    test_ret += test_xmlThrDefSetGenericErrorFunc();
+    test_ret += test_xmlThrDefSetStructuredErrorFunc();
 
     if (test_ret != 0)
 	printf("Module xmlerror: %d errors\n", test_ret);
@@ -31953,6 +32402,16 @@
 
 
 static int
+test_xmlTextReaderSetMaxAmplification(void) {
+    int test_ret = 0;
+
+
+    /* missing type support */
+    return(test_ret);
+}
+
+
+static int
 test_xmlTextReaderSetParserProp(void) {
     int test_ret = 0;
 
@@ -32217,7 +32676,7 @@
 test_xmlreader(void) {
     int test_ret = 0;
 
-    if (quiet == 0) printf("Testing xmlreader : 76 of 86 functions ...\n");
+    if (quiet == 0) printf("Testing xmlreader : 76 of 87 functions ...\n");
     test_ret += test_xmlNewTextReader();
     test_ret += test_xmlNewTextReaderFilename();
     test_ret += test_xmlReaderForDoc();
@@ -32289,6 +32748,7 @@
     test_ret += test_xmlTextReaderSchemaValidate();
     test_ret += test_xmlTextReaderSchemaValidateCtxt();
     test_ret += test_xmlTextReaderSetErrorHandler();
+    test_ret += test_xmlTextReaderSetMaxAmplification();
     test_ret += test_xmlTextReaderSetParserProp();
     test_ret += test_xmlTextReaderSetSchema();
     test_ret += test_xmlTextReaderSetStructuredErrorHandler();
@@ -33340,7 +33800,7 @@
     long ret_val;
     xmlSaveCtxtPtr ctxt; /* a document saving context */
     int n_ctxt;
-    xmlNodePtr cur; /*  */
+    xmlNodePtr cur; /* the top node of the subtree to save */
     int n_cur;
 
     for (n_ctxt = 0;n_ctxt < gen_nb_xmlSaveCtxtPtr;n_ctxt++) {
@@ -33371,11 +33831,113 @@
     return(test_ret);
 }
 
+
+static int
+test_xmlThrDefIndentTreeOutput(void) {
+    int test_ret = 0;
+
+#if defined(LIBXML_OUTPUT_ENABLED)
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefIndentTreeOutput(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefIndentTreeOutput",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+#endif
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefSaveNoEmptyTags(void) {
+    int test_ret = 0;
+
+#if defined(LIBXML_OUTPUT_ENABLED)
+    int mem_base;
+    int ret_val;
+    int v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_int;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_int(n_v, 0);
+
+        ret_val = xmlThrDefSaveNoEmptyTags(v);
+        desret_int(ret_val);
+        call_tests++;
+        des_int(n_v, v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefSaveNoEmptyTags",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+#endif
+
+    return(test_ret);
+}
+
+
+static int
+test_xmlThrDefTreeIndentString(void) {
+    int test_ret = 0;
+
+#if defined(LIBXML_OUTPUT_ENABLED)
+    int mem_base;
+    const char * ret_val;
+    char * v; /*  */
+    int n_v;
+
+    for (n_v = 0;n_v < gen_nb_const_char_ptr;n_v++) {
+        mem_base = xmlMemBlocks();
+        v = gen_const_char_ptr(n_v, 0);
+
+        ret_val = xmlThrDefTreeIndentString((const char *)v);
+        desret_const_char_ptr(ret_val);
+        call_tests++;
+        des_const_char_ptr(n_v, (const char *)v, 0);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlThrDefTreeIndentString",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_v);
+            printf("\n");
+        }
+    }
+    function_tests++;
+#endif
+
+    return(test_ret);
+}
+
 static int
 test_xmlsave(void) {
     int test_ret = 0;
 
-    if (quiet == 0) printf("Testing xmlsave : 4 of 10 functions ...\n");
+    if (quiet == 0) printf("Testing xmlsave : 7 of 13 functions ...\n");
     test_ret += test_xmlSaveClose();
     test_ret += test_xmlSaveDoc();
     test_ret += test_xmlSaveFlush();
@@ -33385,6 +33947,9 @@
     test_ret += test_xmlSaveToFd();
     test_ret += test_xmlSaveToFilename();
     test_ret += test_xmlSaveTree();
+    test_ret += test_xmlThrDefIndentTreeOutput();
+    test_ret += test_xmlThrDefSaveNoEmptyTags();
+    test_ret += test_xmlThrDefTreeIndentString();
 
     if (test_ret != 0)
 	printf("Module xmlsave: %d errors\n", test_ret);
diff --git a/third_party/libxml/src/testchar.c b/third_party/libxml/src/testchar.c
index a819e19..0dc7ccd 100644
--- a/third_party/libxml/src/testchar.c
+++ b/third_party/libxml/src/testchar.c
@@ -271,11 +271,11 @@
     data[3] = 0;
     for (i = 0;i <= 0xFF;i++) {
         data[0] = (char) i;
-	ctxt->charset = XML_CHAR_ENCODING_UTF8;
         ctxt->nbErrors = 0;
 
 	lastError = 0;
         c = xmlCurrentChar(ctxt, &len);
+        ctxt->input->flags = 0;
 	if ((i == 0) || (i >= 0x80)) {
 	    /* we must see an error there */
 	    if (lastError != XML_ERR_INVALID_CHAR) {
@@ -307,11 +307,11 @@
 	for (j = 0;j <= 0xFF;j++) {
 	    data[0] = (char) i;
 	    data[1] = (char) j;
-	    ctxt->charset = XML_CHAR_ENCODING_UTF8;
             ctxt->nbErrors = 0;
 
 	    lastError = 0;
 	    c = xmlCurrentChar(ctxt, &len);
+            ctxt->input->flags = 0;
 
 	    /* if first bit of first char is set, then second bit must too */
 	    if ((i & 0x80) && ((i & 0x40) == 0)) {
@@ -401,11 +401,11 @@
 	K = lows[k];
 	data[2] = (char) K;
 	value = (K & 0x3F) + ((j & 0x3F) << 6) + ((i & 0xF) << 12);
-	ctxt->charset = XML_CHAR_ENCODING_UTF8;
         ctxt->nbErrors = 0;
 
 	lastError = 0;
 	c = xmlCurrentChar(ctxt, &len);
+        ctxt->input->flags = 0;
 
 	/*
 	 * if fourth bit of first char is set, then the sequence would need
@@ -504,11 +504,11 @@
 	data[3] = (char) L;
 	value = (L & 0x3F) + ((K & 0x3F) << 6) + ((j & 0x3F) << 12) +
 	        ((i & 0x7) << 18);
-	ctxt->charset = XML_CHAR_ENCODING_UTF8;
         ctxt->nbErrors = 0;
 
 	lastError = 0;
 	c = xmlCurrentChar(ctxt, &len);
+        ctxt->input->flags = 0;
 
 	/*
 	 * if fifth bit of first char is set, then the sequence would need
@@ -713,9 +713,65 @@
     return ret;
 }
 
+#if defined(LIBXML_PUSH_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
+
+static char *
+convert(xmlCharEncodingHandlerPtr handler, const char *utf8, int size,
+        int *outSize) {
+    char *ret;
+    int inlen;
+    int res;
+
+    inlen = size;
+    *outSize = size * 2;
+    ret = xmlMalloc(*outSize);
+    if (ret == NULL)
+        return(NULL);
+    res = handler->output(BAD_CAST ret, outSize, BAD_CAST utf8, &inlen);
+    if ((res < 0) || (inlen != size)) {
+        xmlFree(ret);
+        return(NULL);
+    }
+
+    return(ret);
+}
+
+static int
+testUserEncodingPush(void) {
+    xmlCharEncodingHandlerPtr handler;
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    char buf[] =
+        "\xEF\xBB\xBF"
+        "<?xml version='1.0' encoding='ISO-8859-1'?>\n"
+        "<d>text</d>\n";
+    char *utf16;
+    int utf16Size;
+    int ret = 1;
+
+    handler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF16LE);
+    utf16 = convert(handler, buf, sizeof(buf) - 1, &utf16Size);
+    ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
+    xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_UTF16LE);
+    xmlParseChunk(ctxt, utf16, utf16Size, 0);
+    xmlParseChunk(ctxt, NULL, 0, 1);
+    doc = ctxt->myDoc;
+
+    if ((doc != NULL) &&
+        (doc->children != NULL) &&
+        (doc->children->children != NULL) &&
+        (xmlStrcmp(doc->children->children->content, BAD_CAST "text") == 0))
+        ret = 0;
+
+    xmlFreeDoc(doc);
+    xmlFreeParserCtxt(ctxt);
+    xmlFree(utf16);
+
+    return(ret);
+}
+
 static int
 testUTF8Chunks(void) {
-#if defined(LIBXML_PUSH_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
     xmlParserCtxtPtr ctxt;
     xmlChar *out;
     int outSize;
@@ -786,11 +842,11 @@
     xmlFreeParserCtxt(ctxt);
 
     return(ret);
-#else
     return(0);
-#endif
 }
 
+#endif
+
 int main(void) {
 
     int ret = 0;
@@ -814,7 +870,10 @@
     ret += testCharRanges();
     ret += testDocumentRanges();
     ret += testUserEncoding();
+#if defined(LIBXML_PUSH_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
+    ret += testUserEncodingPush();
     ret += testUTF8Chunks();
+#endif
 
     /*
      * Cleanup function for the XML library.
diff --git a/third_party/libxml/src/testdict.c b/third_party/libxml/src/testdict.c
index f731a98..97157b1 100644
--- a/third_party/libxml/src/testdict.c
+++ b/third_party/libxml/src/testdict.c
@@ -1,3 +1,4 @@
+#include <stdlib.h>
 #include <string.h>
 #include <libxml/parser.h>
 #include <libxml/dict.h>
@@ -22,9 +23,9 @@
    NULL
 };
 
-#define NB_STRINGS_MAX 10000
-#define NB_STRINGS_NS 1000
-#define NB_STRINGS_PREFIX 50
+#define NB_STRINGS_MAX 100000
+#define NB_STRINGS_NS  10000
+#define NB_STRINGS_PREFIX (NB_STRINGS_NS / 20)
 #define NB_STRINGS_MIN 10
 
 static xmlChar **strings1;
diff --git a/third_party/libxml/src/testlimits.c b/third_party/libxml/src/testlimits.c
index 5400bd8..de0da9d 100644
--- a/third_party/libxml/src/testlimits.c
+++ b/third_party/libxml/src/testlimits.c
@@ -10,9 +10,8 @@
  * daniel@veillard.com
  */
 
-#include "libxml.h"
 #include <stdio.h>
-
+#include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <time.h>
@@ -659,9 +658,6 @@
 
 static void
 initializeLibxml2(void) {
-    xmlGetWarningsDefaultValue = 0;
-    xmlPedanticParserDefault(0);
-
     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
     xmlInitParser();
     xmlSetExternalEntityLoader(testExternalEntityLoader);
diff --git a/third_party/libxml/src/testrecurse.c b/third_party/libxml/src/testrecurse.c
index d0a4ed24..01e15b2 100644
--- a/third_party/libxml/src/testrecurse.c
+++ b/third_party/libxml/src/testrecurse.c
@@ -10,9 +10,9 @@
  * daniel@veillard.com
  */
 
-#include "libxml.h"
 #include <stdio.h>
 
+#include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 
@@ -627,9 +627,6 @@
 
 static void
 initializeLibxml2(void) {
-    xmlGetWarningsDefaultValue = 0;
-    xmlPedanticParserDefault(0);
-
     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
     xmlInitParser();
     xmlSetExternalEntityLoader(testExternalEntityLoader);
@@ -995,7 +992,12 @@
         total_size = strlen(hugeDocParts->start) +
                      strlen(hugeDocParts->segment) * (MAX_NODES - 1) +
                      strlen(hugeDocParts->finish) +
-                     28;
+                     /*
+                      * Other external entities pa.ent, pb.ent, pc.ent.
+                      * These are currently counted twice because they're
+                      * used both in DTD and EntityValue.
+                      */
+                     (16 + 6 + 6) * 2;
         if (ctxt->sizeentities != total_size) {
             fprintf(stderr, "Wrong parsed entity size: %lu (expected %lu)\n",
                     ctxt->sizeentities, total_size);
diff --git a/third_party/libxml/src/threads.c b/third_party/libxml/src/threads.c
index 60dbce4..33a6777 100644
--- a/third_party/libxml/src/threads.c
+++ b/third_party/libxml/src/threads.c
@@ -14,16 +14,25 @@
 #include <stdlib.h>
 
 #include <libxml/threads.h>
-#include <libxml/globals.h>
+#include <libxml/parser.h>
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/xmlschemastypes.h>
+#include <libxml/relaxng.h>
+#endif
 
 #if defined(SOLARIS)
 #include <note.h>
 #endif
 
 #include "private/dict.h"
+#include "private/enc.h"
+#include "private/globals.h"
+#include "private/memory.h"
 #include "private/threads.h"
-
-/* #define DEBUG_THREADS */
+#include "private/xpath.h"
 
 #if defined(HAVE_POSIX_THREADS) && \
     defined(__GLIBC__) && \
@@ -60,10 +69,6 @@
  * configure.ac can probably be removed.
  */
 
-#pragma weak pthread_getspecific
-#pragma weak pthread_setspecific
-#pragma weak pthread_key_create
-#pragma weak pthread_key_delete
 #pragma weak pthread_mutex_init
 #pragma weak pthread_mutex_destroy
 #pragma weak pthread_mutex_lock
@@ -113,27 +118,6 @@
 #endif
 };
 
-/*
- * This module still has some internal static data.
- *   - xmlLibraryLock a global lock
- *   - globalkey used for per-thread data
- */
-
-#ifdef HAVE_POSIX_THREADS
-static pthread_key_t globalkey;
-static pthread_t mainthread;
-static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
-#elif defined HAVE_WIN32_THREADS
-#if defined(HAVE_COMPILER_TLS)
-static __declspec(thread) xmlGlobalState tlstate;
-static __declspec(thread) int tlstate_inited = 0;
-#else /* HAVE_COMPILER_TLS */
-static DWORD globalkey = TLS_OUT_OF_INDEXES;
-#endif /* HAVE_COMPILER_TLS */
-static DWORD mainthread;
-static volatile LPCRITICAL_SECTION global_init_lock = NULL;
-#endif
-
 static xmlRMutexPtr xmlLibraryLock = NULL;
 
 /**
@@ -369,275 +353,6 @@
 #endif
 }
 
-/**
- * xmlGlobalInitMutexLock
- *
- * Makes sure that the global initialization mutex is initialized and
- * locks it.
- */
-void
-__xmlGlobalInitMutexLock(void)
-{
-    /* Make sure the global init lock is initialized and then lock it. */
-#ifdef HAVE_POSIX_THREADS
-#ifdef XML_PTHREAD_WEAK
-    if (pthread_mutex_lock == NULL)
-        return;
-#else
-    if (XML_IS_THREADED() == 0)
-        return;
-#endif
-    /* The mutex is statically initialized, so we just lock it. */
-    pthread_mutex_lock(&global_init_lock);
-#elif defined HAVE_WIN32_THREADS
-    LPCRITICAL_SECTION cs;
-
-    /* Create a new critical section */
-    if (global_init_lock == NULL) {
-        cs = malloc(sizeof(CRITICAL_SECTION));
-        if (cs == NULL) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlGlobalInitMutexLock: out of memory\n");
-            return;
-        }
-        InitializeCriticalSection(cs);
-
-        /* Swap it into the global_init_lock */
-#ifdef InterlockedCompareExchangePointer
-        InterlockedCompareExchangePointer((void **) &global_init_lock,
-                                          cs, NULL);
-#else /* Use older void* version */
-        InterlockedCompareExchange((void **) &global_init_lock,
-                                   (void *) cs, NULL);
-#endif /* InterlockedCompareExchangePointer */
-
-        /* If another thread successfully recorded its critical
-         * section in the global_init_lock then discard the one
-         * allocated by this thread. */
-        if (global_init_lock != cs) {
-            DeleteCriticalSection(cs);
-            free(cs);
-        }
-    }
-
-    /* Lock the chosen critical section */
-    EnterCriticalSection(global_init_lock);
-#endif
-}
-
-void
-__xmlGlobalInitMutexUnlock(void)
-{
-#ifdef HAVE_POSIX_THREADS
-#ifdef XML_PTHREAD_WEAK
-    if (pthread_mutex_lock == NULL)
-        return;
-#else
-    if (XML_IS_THREADED() == 0)
-        return;
-#endif
-    pthread_mutex_unlock(&global_init_lock);
-#elif defined HAVE_WIN32_THREADS
-    if (global_init_lock != NULL) {
-	LeaveCriticalSection(global_init_lock);
-    }
-#endif
-}
-
-/**
- * xmlGlobalInitMutexDestroy
- *
- * Makes sure that the global initialization mutex is destroyed before
- * application termination.
- */
-void
-__xmlGlobalInitMutexDestroy(void)
-{
-#ifdef HAVE_POSIX_THREADS
-#elif defined HAVE_WIN32_THREADS
-    if (global_init_lock != NULL) {
-        DeleteCriticalSection(global_init_lock);
-        free(global_init_lock);
-        global_init_lock = NULL;
-    }
-#endif
-}
-
-/************************************************************************
- *									*
- *			Per thread global state handling		*
- *									*
- ************************************************************************/
-
-#ifdef LIBXML_THREAD_ENABLED
-#ifdef xmlLastError
-#undef xmlLastError
-#endif
-
-/**
- * xmlFreeGlobalState:
- * @state:  a thread global state
- *
- * xmlFreeGlobalState() is called when a thread terminates with a non-NULL
- * global state. It is is used here to reclaim memory resources.
- */
-static void
-xmlFreeGlobalState(void *state)
-{
-    xmlGlobalState *gs = (xmlGlobalState *) state;
-
-    /* free any memory allocated in the thread's xmlLastError */
-    xmlResetError(&(gs->xmlLastError));
-    free(state);
-}
-
-/**
- * xmlNewGlobalState:
- *
- * xmlNewGlobalState() allocates a global state. This structure is used to
- * hold all data for use by a thread when supporting backwards compatibility
- * of libxml2 to pre-thread-safe behaviour.
- *
- * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
- */
-static xmlGlobalStatePtr
-xmlNewGlobalState(void)
-{
-    xmlGlobalState *gs;
-
-    gs = malloc(sizeof(xmlGlobalState));
-    if (gs == NULL) {
-	xmlGenericError(xmlGenericErrorContext,
-			"xmlGetGlobalState: out of memory\n");
-        return (NULL);
-    }
-
-    memset(gs, 0, sizeof(xmlGlobalState));
-    xmlInitializeGlobalState(gs);
-    return (gs);
-}
-#endif /* LIBXML_THREAD_ENABLED */
-
-#ifdef HAVE_POSIX_THREADS
-#elif defined HAVE_WIN32_THREADS
-#if !defined(HAVE_COMPILER_TLS)
-#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
-typedef struct _xmlGlobalStateCleanupHelperParams {
-    HANDLE thread;
-    void *memory;
-} xmlGlobalStateCleanupHelperParams;
-
-static void
-xmlGlobalStateCleanupHelper(void *p)
-{
-    xmlGlobalStateCleanupHelperParams *params =
-        (xmlGlobalStateCleanupHelperParams *) p;
-    WaitForSingleObject(params->thread, INFINITE);
-    CloseHandle(params->thread);
-    xmlFreeGlobalState(params->memory);
-    free(params);
-    _endthread();
-}
-#else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
-
-typedef struct _xmlGlobalStateCleanupHelperParams {
-    void *memory;
-    struct _xmlGlobalStateCleanupHelperParams *prev;
-    struct _xmlGlobalStateCleanupHelperParams *next;
-} xmlGlobalStateCleanupHelperParams;
-
-static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL;
-static CRITICAL_SECTION cleanup_helpers_cs;
-
-#endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
-#endif /* HAVE_COMPILER_TLS */
-#endif /* HAVE_WIN32_THREADS */
-
-/**
- * xmlGetGlobalState:
- *
- * DEPRECATED: Internal function, do not use.
- *
- * xmlGetGlobalState() is called to retrieve the global state for a thread.
- *
- * Returns the thread global state or NULL in case of error
- */
-xmlGlobalStatePtr
-xmlGetGlobalState(void)
-{
-#ifdef HAVE_POSIX_THREADS
-    xmlGlobalState *globalval;
-
-    if (XML_IS_THREADED() == 0)
-        return (NULL);
-
-    if ((globalval = (xmlGlobalState *)
-         pthread_getspecific(globalkey)) == NULL) {
-        xmlGlobalState *tsd = xmlNewGlobalState();
-	if (tsd == NULL)
-	    return(NULL);
-
-        pthread_setspecific(globalkey, tsd);
-        return (tsd);
-    }
-    return (globalval);
-#elif defined HAVE_WIN32_THREADS
-#if defined(HAVE_COMPILER_TLS)
-    if (!tlstate_inited) {
-        tlstate_inited = 1;
-        xmlInitializeGlobalState(&tlstate);
-    }
-    return &tlstate;
-#else /* HAVE_COMPILER_TLS */
-    xmlGlobalState *globalval;
-    xmlGlobalStateCleanupHelperParams *p;
-#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
-    globalval = (xmlGlobalState *) TlsGetValue(globalkey);
-#else
-    p = (xmlGlobalStateCleanupHelperParams *) TlsGetValue(globalkey);
-    globalval = (xmlGlobalState *) (p ? p->memory : NULL);
-#endif
-    if (globalval == NULL) {
-        xmlGlobalState *tsd = xmlNewGlobalState();
-
-        if (tsd == NULL)
-	    return(NULL);
-        p = (xmlGlobalStateCleanupHelperParams *)
-            malloc(sizeof(xmlGlobalStateCleanupHelperParams));
-	if (p == NULL) {
-            xmlGenericError(xmlGenericErrorContext,
-                            "xmlGetGlobalState: out of memory\n");
-            xmlFreeGlobalState(tsd);
-	    return(NULL);
-	}
-        p->memory = tsd;
-#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
-        DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
-                        GetCurrentProcess(), &p->thread, 0, TRUE,
-                        DUPLICATE_SAME_ACCESS);
-        TlsSetValue(globalkey, tsd);
-        _beginthread(xmlGlobalStateCleanupHelper, 0, p);
-#else
-        EnterCriticalSection(&cleanup_helpers_cs);
-        if (cleanup_helpers_head != NULL) {
-            cleanup_helpers_head->prev = p;
-        }
-        p->next = cleanup_helpers_head;
-        p->prev = NULL;
-        cleanup_helpers_head = p;
-        TlsSetValue(globalkey, p);
-        LeaveCriticalSection(&cleanup_helpers_cs);
-#endif
-
-        return (tsd);
-    }
-    return (globalval);
-#endif /* HAVE_COMPILER_TLS */
-#else
-    return (NULL);
-#endif
-}
-
 /************************************************************************
  *									*
  *			Library wide thread interfaces			*
@@ -676,34 +391,6 @@
 }
 
 /**
- * xmlIsMainThread:
- *
- * DEPRECATED: Internal function, do not use.
- *
- * xmlIsMainThread() check whether the current thread is the main thread.
- *
- * Returns 1 if the current thread is the main thread, 0 otherwise
- */
-int
-xmlIsMainThread(void)
-{
-    xmlInitParser();
-
-#ifdef DEBUG_THREADS
-    xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");
-#endif
-#ifdef HAVE_POSIX_THREADS
-    if (XML_IS_THREADED() == 0)
-        return (1);
-    return (pthread_equal(mainthread,pthread_self()));
-#elif defined HAVE_WIN32_THREADS
-    return (mainthread == GetCurrentThreadId());
-#else
-    return (1);
-#endif
-}
-
-/**
  * xmlLockLibrary:
  *
  * xmlLockLibrary() is used to take out a re-entrant lock on the libxml2
@@ -712,9 +399,6 @@
 void
 xmlLockLibrary(void)
 {
-#ifdef DEBUG_THREADS
-    xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n");
-#endif
     xmlRMutexLock(xmlLibraryLock);
 }
 
@@ -727,9 +411,6 @@
 void
 xmlUnlockLibrary(void)
 {
-#ifdef DEBUG_THREADS
-    xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n");
-#endif
     xmlRMutexUnlock(xmlLibraryLock);
 }
 
@@ -745,14 +426,42 @@
 }
 
 /**
- * xmlInitThreadsInternal:
+ * xmlCleanupThreads:
  *
- * Used to to initialize all the thread related data.
+ * DEPRECATED: This function is a no-op. Call xmlCleanupParser
+ * to free global state but see the warnings there. xmlCleanupParser
+ * should be only called once at program exit. In most cases, you don't
+ * have call cleanup functions at all.
  */
 void
-xmlInitThreadsInternal(void)
+xmlCleanupThreads(void)
 {
+}
+
+/************************************************************************
+ *									*
+ *			Library wide initialization			*
+ *									*
+ ************************************************************************/
+
+static int xmlParserInitialized = 0;
+
 #ifdef HAVE_POSIX_THREADS
+static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
+#elif defined HAVE_WIN32_THREADS
+static volatile LPCRITICAL_SECTION global_init_lock = NULL;
+#endif
+
+/**
+ * xmlGlobalInitMutexLock
+ *
+ * Makes sure that the global initialization mutex is initialized and
+ * locks it.
+ */
+static void
+xmlGlobalInitMutexLock(void) {
+#ifdef HAVE_POSIX_THREADS
+
 #ifdef XML_PTHREAD_WEAK
     /*
      * This is somewhat unreliable since libpthread could be loaded
@@ -761,10 +470,6 @@
      */
     if (libxml_is_threaded == -1)
         libxml_is_threaded =
-            (pthread_getspecific != NULL) &&
-            (pthread_setspecific != NULL) &&
-            (pthread_key_create != NULL) &&
-            (pthread_key_delete != NULL) &&
             (pthread_mutex_init != NULL) &&
             (pthread_mutex_destroy != NULL) &&
             (pthread_mutex_lock != NULL) &&
@@ -779,136 +484,195 @@
             /* (pthread_equal != NULL) && */
             (pthread_self != NULL) &&
             (pthread_cond_signal != NULL);
-    if (libxml_is_threaded == 0)
-        return;
-#endif /* XML_PTHREAD_WEAK */
-    pthread_key_create(&globalkey, xmlFreeGlobalState);
-    mainthread = pthread_self();
-#elif defined(HAVE_WIN32_THREADS)
-#if !defined(HAVE_COMPILER_TLS)
-#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
-    InitializeCriticalSection(&cleanup_helpers_cs);
 #endif
-    globalkey = TlsAlloc();
-#endif
-    mainthread = GetCurrentThreadId();
-#endif
-}
 
-/**
- * xmlCleanupThreads:
- *
- * DEPRECATED: This function is a no-op. Call xmlCleanupParser
- * to free global state but see the warnings there. xmlCleanupParser
- * should be only called once at program exit. In most cases, you don't
- * have call cleanup functions at all.
- */
-void
-xmlCleanupThreads(void)
-{
-}
+    /* The mutex is statically initialized, so we just lock it. */
+    if (XML_IS_THREADED() != 0)
+        pthread_mutex_lock(&global_init_lock);
 
-/**
- * xmlCleanupThreadsInternal:
- *
- * Used to to cleanup all the thread related data.
- */
-void
-xmlCleanupThreadsInternal(void)
-{
-#ifdef HAVE_POSIX_THREADS
-#ifdef XML_PTHREAD_WEAK
-    if (libxml_is_threaded == 0)
-        return;
-#endif /* XML_PTHREAD_WEAK */
-    pthread_key_delete(globalkey);
-#elif defined(HAVE_WIN32_THREADS)
-#if !defined(HAVE_COMPILER_TLS)
-    if (globalkey != TLS_OUT_OF_INDEXES) {
-#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
-        xmlGlobalStateCleanupHelperParams *p;
+#elif defined HAVE_WIN32_THREADS
 
-        EnterCriticalSection(&cleanup_helpers_cs);
-        p = cleanup_helpers_head;
-        while (p != NULL) {
-            xmlGlobalStateCleanupHelperParams *temp = p;
+    LPCRITICAL_SECTION cs;
 
-            p = p->next;
-            xmlFreeGlobalState(temp->memory);
-            free(temp);
+    /* Create a new critical section */
+    if (global_init_lock == NULL) {
+        cs = malloc(sizeof(CRITICAL_SECTION));
+        if (cs == NULL) {
+            xmlGenericError(xmlGenericErrorContext,
+                            "xmlGlobalInitMutexLock: out of memory\n");
+            return;
         }
-        cleanup_helpers_head = 0;
-        LeaveCriticalSection(&cleanup_helpers_cs);
-#endif
-        TlsFree(globalkey);
-        globalkey = TLS_OUT_OF_INDEXES;
+        InitializeCriticalSection(cs);
+
+        /* Swap it into the global_init_lock */
+#ifdef InterlockedCompareExchangePointer
+        InterlockedCompareExchangePointer((void **) &global_init_lock,
+                                          cs, NULL);
+#else /* Use older void* version */
+        InterlockedCompareExchange((void **) &global_init_lock,
+                                   (void *) cs, NULL);
+#endif /* InterlockedCompareExchangePointer */
+
+        /* If another thread successfully recorded its critical
+         * section in the global_init_lock then discard the one
+         * allocated by this thread. */
+        if (global_init_lock != cs) {
+            DeleteCriticalSection(cs);
+            free(cs);
+        }
     }
-#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
-    DeleteCriticalSection(&cleanup_helpers_cs);
+
+    /* Lock the chosen critical section */
+    EnterCriticalSection(global_init_lock);
+
 #endif
-#endif
+}
+
+static void
+xmlGlobalInitMutexUnlock(void) {
+#ifdef HAVE_POSIX_THREADS
+    if (XML_IS_THREADED() != 0)
+        pthread_mutex_unlock(&global_init_lock);
+#elif defined HAVE_WIN32_THREADS
+    if (global_init_lock != NULL)
+	LeaveCriticalSection(global_init_lock);
 #endif
 }
 
 /**
- * DllMain:
- * @hinstDLL: handle to DLL instance
- * @fdwReason: Reason code for entry
- * @lpvReserved: generic pointer (depends upon reason code)
+ * xmlGlobalInitMutexDestroy
  *
- * Entry point for Windows library. It is being used to free thread-specific
- * storage.
- *
- * Returns TRUE always
+ * Makes sure that the global initialization mutex is destroyed before
+ * application termination.
  */
+static void
+xmlGlobalInitMutexDestroy(void) {
 #ifdef HAVE_POSIX_THREADS
-#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
-#if defined(LIBXML_STATIC_FOR_DLL)
-int
-xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
-           ATTRIBUTE_UNUSED void *lpvReserved)
-#else
-/* declare to avoid "no previous prototype for 'DllMain'" warning */
-/* Note that we do NOT want to include this function declaration in
-   a public header because it's meant to be called by Windows itself,
-   not a program that uses this library.  This also has to be exported. */
-
-XMLPUBFUN BOOL WINAPI
-DllMain (HINSTANCE hinstDLL,
-         DWORD     fdwReason,
-         LPVOID    lpvReserved);
-
-BOOL WINAPI
-DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
-        ATTRIBUTE_UNUSED LPVOID lpvReserved)
-#endif
-{
-    switch (fdwReason) {
-        case DLL_THREAD_DETACH:
-            if (globalkey != TLS_OUT_OF_INDEXES) {
-                xmlGlobalState *globalval = NULL;
-                xmlGlobalStateCleanupHelperParams *p =
-                    (xmlGlobalStateCleanupHelperParams *)
-                    TlsGetValue(globalkey);
-                globalval = (xmlGlobalState *) (p ? p->memory : NULL);
-                if (globalval) {
-                    xmlFreeGlobalState(globalval);
-                    TlsSetValue(globalkey, NULL);
-                }
-                if (p) {
-                    EnterCriticalSection(&cleanup_helpers_cs);
-                    if (p == cleanup_helpers_head)
-                        cleanup_helpers_head = p->next;
-                    else
-                        p->prev->next = p->next;
-                    if (p->next != NULL)
-                        p->next->prev = p->prev;
-                    LeaveCriticalSection(&cleanup_helpers_cs);
-                    free(p);
-                }
-            }
-            break;
+#elif defined HAVE_WIN32_THREADS
+    if (global_init_lock != NULL) {
+        DeleteCriticalSection(global_init_lock);
+        free(global_init_lock);
+        global_init_lock = NULL;
     }
-    return TRUE;
+#endif
+}
+
+/**
+ * xmlInitParser:
+ *
+ * Initialization function for the XML parser.
+ *
+ * Call once from the main thread before using the library in
+ * multithreaded programs.
+ */
+void
+xmlInitParser(void) {
+    static int innerInitialized = 0;
+
+    /*
+     * Note that the initialization code must not make memory allocations.
+     */
+    if (xmlParserInitialized != 0)
+        return;
+
+    xmlGlobalInitMutexLock();
+
+    if (innerInitialized == 0) {
+#if defined(_WIN32) && \
+    (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+        if (xmlFree == free)
+            atexit(xmlCleanupParser);
+#endif
+
+        xmlInitMemoryInternal(); /* Should come second */
+        xmlInitGlobalsInternal();
+        xmlInitDictInternal();
+        xmlInitEncodingInternal();
+#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
+        xmlInitXPathInternal();
+#endif
+
+        xmlRegisterDefaultInputCallbacks();
+#ifdef LIBXML_OUTPUT_ENABLED
+        xmlRegisterDefaultOutputCallbacks();
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+        innerInitialized = 1;
+    }
+
+    xmlGlobalInitMutexUnlock();
+
+    xmlParserInitialized = 1;
+}
+
+/**
+ * xmlCleanupParser:
+ *
+ * This function name is somewhat misleading. It does not clean up
+ * parser state, it cleans up memory allocated by the library itself.
+ * It is a cleanup function for the XML library. It tries to reclaim all
+ * related global memory allocated for the library processing.
+ * It doesn't deallocate any document related memory. One should
+ * call xmlCleanupParser() only when the process has finished using
+ * the library and all XML/HTML documents built with it.
+ * See also xmlInitParser() which has the opposite function of preparing
+ * the library for operations.
+ *
+ * WARNING: if your application is multithreaded or has plugin support
+ *          calling this may crash the application if another thread or
+ *          a plugin is still using libxml2. It's sometimes very hard to
+ *          guess if libxml2 is in use in the application, some libraries
+ *          or plugins may use it without notice. In case of doubt abstain
+ *          from calling this function or do it just before calling exit()
+ *          to avoid leak reports from valgrind !
+ */
+void
+xmlCleanupParser(void) {
+    if (!xmlParserInitialized)
+        return;
+
+    /* These functions can call xmlFree. */
+
+    xmlCleanupCharEncodingHandlers();
+#ifdef LIBXML_CATALOG_ENABLED
+    xmlCatalogCleanup();
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+    xmlSchemaCleanupTypes();
+    xmlRelaxNGCleanupTypes();
+#endif
+
+    /* These functions should never call xmlFree. */
+
+    xmlCleanupInputCallbacks();
+#ifdef LIBXML_OUTPUT_ENABLED
+    xmlCleanupOutputCallbacks();
+#endif
+
+    xmlCleanupDictInternal();
+    xmlCleanupGlobalsInternal();
+    /*
+     * Must come last. On Windows, xmlCleanupGlobalsInternal can call
+     * xmlFree which uses xmlMemMutex in debug mode.
+     */
+    xmlCleanupMemoryInternal();
+
+    xmlGlobalInitMutexDestroy();
+
+    xmlParserInitialized = 0;
+}
+
+#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && !defined(LIBXML_STATIC) && \
+    !defined(_WIN32)
+static void
+ATTRIBUTE_DESTRUCTOR
+xmlDestructor(void) {
+    /*
+     * Calling custom deallocation functions in a destructor can cause
+     * problems, for example with Nokogiri.
+     */
+    if (xmlFree == free)
+        xmlCleanupParser();
 }
 #endif
+
diff --git a/third_party/libxml/src/tree.c b/third_party/libxml/src/tree.c
index 6c8a875..fe02b414 100644
--- a/third_party/libxml/src/tree.c
+++ b/third_party/libxml/src/tree.c
@@ -28,15 +28,13 @@
 #include <zlib.h>
 #endif
 
-#include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/uri.h>
 #include <libxml/entities.h>
-#include <libxml/valid.h>
 #include <libxml/xmlerror.h>
 #include <libxml/parserInternals.h>
-#include <libxml/globals.h>
 #ifdef LIBXML_HTML_ENABLED
 #include <libxml/HTMLtree.h>
 #endif
@@ -142,9 +140,6 @@
 #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
   (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
 
-/* #define DEBUG_BUFFER */
-/* #define DEBUG_TREE */
-
 /************************************************************************
  *									*
  *		Functions to move to entities.c once the		*
@@ -803,10 +798,6 @@
 void
 xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
     if (node == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlSetNs: node == NULL\n");
-#endif
 	return;
     }
     if ((node->type == XML_ELEMENT_NODE) ||
@@ -823,10 +814,6 @@
 void
 xmlFreeNs(xmlNsPtr cur) {
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlFreeNs : ns == NULL\n");
-#endif
 	return;
     }
     if (cur->href != NULL) xmlFree((char *) cur->href);
@@ -844,10 +831,6 @@
 xmlFreeNsList(xmlNsPtr cur) {
     xmlNsPtr next;
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlFreeNsList : ns == NULL\n");
-#endif
 	return;
     }
     while (cur != NULL) {
@@ -875,12 +858,6 @@
     xmlDtdPtr cur;
 
     if ((doc != NULL) && (doc->extSubset != NULL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewDtd(%s): document %s already have a DTD %s\n",
-	    /* !!! */ (char *) name, doc->name,
-	    /* !!! */ (char *)doc->extSubset->name);
-#endif
 	return(NULL);
     }
 
@@ -949,12 +926,6 @@
     xmlDtdPtr cur;
 
     if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-
-     "xmlCreateIntSubset(): document %s already have an internal subset\n",
-	    doc->name);
-#endif
 	return(NULL);
     }
 
@@ -1208,10 +1179,6 @@
     xmlDictPtr dict = NULL;
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlFreeDoc : document == NULL\n");
-#endif
 	return;
     }
 
@@ -1963,10 +1930,6 @@
 xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewProp : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -1989,10 +1952,6 @@
            const xmlChar *value) {
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewNsProp : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2014,10 +1973,6 @@
            const xmlChar *value) {
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewNsPropEatName : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2043,10 +1998,6 @@
     xmlAttrPtr cur;
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewDocProp : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2141,17 +2092,9 @@
 xmlRemoveProp(xmlAttrPtr cur) {
     xmlAttrPtr tmp;
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlRemoveProp : cur == NULL\n");
-#endif
 	return(-1);
     }
     if (cur->parent == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlRemoveProp : cur->parent == NULL\n");
-#endif
 	return(-1);
     }
     tmp = cur->parent->properties;
@@ -2172,10 +2115,6 @@
 	}
         tmp = tmp->next;
     }
-#ifdef DEBUG_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "xmlRemoveProp : attribute not owned by its node\n");
-#endif
     return(-1);
 }
 
@@ -2193,10 +2132,6 @@
     xmlNodePtr cur;
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewPI : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2258,10 +2193,6 @@
     xmlNodePtr cur;
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewNode : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2302,10 +2233,6 @@
     xmlNodePtr cur;
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewNode : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2524,18 +2451,10 @@
     xmlNodePtr cur, prev;
 
     if (parent == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextChild : parent == NULL\n");
-#endif
 	return(NULL);
     }
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewTextChild : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -2959,18 +2878,10 @@
     xmlNodePtr cur, prev;
 
     if (parent == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewChild : parent == NULL\n");
-#endif
 	return(NULL);
     }
 
     if (name == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewChild : name == NULL\n");
-#endif
 	return(NULL);
     }
 
@@ -3087,25 +2998,13 @@
 xmlNodePtr
 xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddNextSibling : cur == NULL\n");
-#endif
 	return(NULL);
     }
     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddNextSibling : elem == NULL\n");
-#endif
 	return(NULL);
     }
 
     if (cur == elem) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddNextSibling : cur == elem\n");
-#endif
 	return(NULL);
     }
 
@@ -3167,25 +3066,13 @@
 xmlNodePtr
 xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddPrevSibling : cur == NULL\n");
-#endif
 	return(NULL);
     }
     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddPrevSibling : elem == NULL\n");
-#endif
 	return(NULL);
     }
 
     if (cur == elem) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddPrevSibling : cur == elem\n");
-#endif
 	return(NULL);
     }
 
@@ -3247,26 +3134,14 @@
     xmlNodePtr parent;
 
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddSibling : cur == NULL\n");
-#endif
 	return(NULL);
     }
 
     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddSibling : elem == NULL\n");
-#endif
 	return(NULL);
     }
 
     if (cur == elem) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddSibling : cur == elem\n");
-#endif
 	return(NULL);
     }
 
@@ -3325,27 +3200,15 @@
     xmlNodePtr prev;
 
     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChildList : parent == NULL\n");
-#endif
 	return(NULL);
     }
 
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChildList : child == NULL\n");
-#endif
 	return(NULL);
     }
 
     if ((cur->doc != NULL) && (parent->doc != NULL) &&
         (cur->doc != parent->doc)) {
-#ifdef DEBUG_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"Elements moved to a different document\n");
-#endif
     }
 
     /*
@@ -3417,26 +3280,14 @@
     xmlNodePtr prev;
 
     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChild : parent == NULL\n");
-#endif
 	return(NULL);
     }
 
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChild : child == NULL\n");
-#endif
 	return(NULL);
     }
 
     if (parent == cur) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlAddChild : parent == cur\n");
-#endif
 	return(NULL);
     }
     /*
@@ -3539,10 +3390,6 @@
 xmlNodePtr
 xmlGetLastChild(const xmlNode *parent) {
     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlGetLastChild : parent == NULL\n");
-#endif
 	return(NULL);
     }
     return(parent->last);
@@ -3907,10 +3754,6 @@
 void
 xmlUnlinkNode(xmlNodePtr cur) {
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlUnlinkNode : node == NULL\n");
-#endif
 	return;
     }
     if (cur->type == XML_NAMESPACE_DECL)
@@ -3987,10 +3830,6 @@
     if (old == cur) return(NULL);
     if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) ||
         (old->parent == NULL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlReplaceNode : old == NULL or without parent\n");
-#endif
 	return(NULL);
     }
     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
@@ -4001,17 +3840,9 @@
 	return(old);
     }
     if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlReplaceNode : Trying to replace attribute node with other node type\n");
-#endif
 	return(old);
     }
     if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
-#endif
 	return(old);
     }
     xmlUnlinkNode(cur);
@@ -4064,10 +3895,6 @@
 	    ret = xmlNewNs(NULL, cur->href, cur->prefix);
 	    break;
 	default:
-#ifdef DEBUG_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "xmlCopyNamespace: invalid type %d\n", cur->type);
-#endif
 	    return(NULL);
     }
     return(ret);
@@ -4471,29 +4298,28 @@
 xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
     xmlNodePtr ret = NULL;
     xmlNodePtr p = NULL,q;
+    xmlDtdPtr newSubset = NULL;
 
     while (node != NULL) {
-#ifdef LIBXML_TREE_ENABLED
 	if (node->type == XML_DTD_NODE ) {
-	    if (doc == NULL) {
+#ifdef LIBXML_TREE_ENABLED
+	    if ((doc == NULL) || (doc->intSubset != NULL)) {
 		node = node->next;
 		continue;
 	    }
-	    if (doc->intSubset == NULL) {
-		q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
-		if (q == NULL) goto error;
-		q->doc = doc;
-		q->parent = parent;
-		doc->intSubset = (xmlDtdPtr) q;
-		xmlAddChild(parent, q);
-	    } else {
-		q = (xmlNodePtr) doc->intSubset;
-		xmlAddChild(parent, q);
-	    }
-	} else
+            q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
+            if (q == NULL) goto error;
+            q->doc = doc;
+            q->parent = parent;
+            newSubset = (xmlDtdPtr) q;
+#else
+            node = node->next;
+            continue;
 #endif /* LIBXML_TREE_ENABLED */
+	} else {
 	    q = xmlStaticCopyNode(node, doc, parent, 1);
-	if (q == NULL) goto error;
+	    if (q == NULL) goto error;
+        }
 	if (ret == NULL) {
 	    q->prev = NULL;
 	    ret = p = q;
@@ -4505,6 +4331,8 @@
 	}
 	node = node->next;
     }
+    if (newSubset != NULL)
+        doc->intSubset = newSubset;
     return(ret);
 error:
     xmlFreeNodeList(ret);
@@ -5769,10 +5597,6 @@
 void
 xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNodeSetContent : node == NULL\n");
-#endif
 	return;
     }
     switch (cur->type) {
@@ -5842,10 +5666,6 @@
 void
 xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNodeSetContentLen : node == NULL\n");
-#endif
 	return;
     }
     switch (cur->type) {
@@ -5912,10 +5732,6 @@
 void
 xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNodeAddContentLen : node == NULL\n");
-#endif
 	return;
     }
     if (len <= 0) return;
@@ -5986,10 +5802,6 @@
     int len;
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNodeAddContent : node == NULL\n");
-#endif
 	return;
     }
     if (content == NULL) return;
@@ -6355,17 +6167,9 @@
     int counter = 1;
 
     if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewReconciledNs : tree == NULL\n");
-#endif
 	return(NULL);
     }
     if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlNewReconciledNs : ns == NULL\n");
-#endif
 	return(NULL);
     }
     /*
@@ -7112,10 +6916,6 @@
         (node->type != XML_CDATA_SECTION_NODE) &&
 	(node->type != XML_COMMENT_NODE) &&
 	(node->type != XML_PI_NODE)) {
-#ifdef DEBUG_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"xmlTextConcat: node is not text nor CDATA\n");
-#endif
         return(-1);
     }
     /* need to check if content is currently in the dictionary */
@@ -7233,7 +7033,7 @@
  * @mem: the memory area
  * @size:  the size in byte
  *
- * Create an XML buffer initialized with bytes.
+ * Returns an XML buffer initialized with bytes.
  */
 xmlBufferPtr
 xmlBufferCreateStatic(void *mem, size_t size) {
@@ -7254,10 +7054,6 @@
 xmlBufferSetAllocationScheme(xmlBufferPtr buf,
                              xmlBufferAllocationScheme scheme) {
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferSetAllocationScheme: buf == NULL\n");
-#endif
         return;
     }
     if (buf->alloc == XML_BUFFER_ALLOC_IO) return;
@@ -7277,10 +7073,6 @@
 void
 xmlBufferFree(xmlBufferPtr buf) {
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferFree: buf == NULL\n");
-#endif
 	return;
     }
 
@@ -7424,17 +7216,9 @@
     size_t ret;
 
     if (buf == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferDump: buf == NULL\n");
-#endif
 	return(0);
     }
     if (buf->content == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferDump: buf->content == NULL\n");
-#endif
 	return(0);
     }
     if (file == NULL)
@@ -7616,10 +7400,6 @@
 	return -1;
     }
     if (len < -1) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferAdd: len < 0\n");
-#endif
 	return -1;
     }
     if (len == 0) return 0;
@@ -7668,17 +7448,9 @@
     if (buf == NULL)
         return(-1);
     if (str == NULL) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferAddHead: str == NULL\n");
-#endif
 	return -1;
     }
     if (len < -1) {
-#ifdef DEBUG_BUFFER
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlBufferAddHead: len < 0\n");
-#endif
 	return -1;
     }
     if (len == 0) return 0;
@@ -7803,10 +7575,6 @@
         return;
     if (xmlStrchr(string, '\"')) {
         if (xmlStrchr(string, '\'')) {
-#ifdef DEBUG_BUFFER
-	    xmlGenericError(xmlGenericErrorContext,
- "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
-#endif
 	    xmlBufferCCat(buf, "\"");
             base = cur = string;
             while(*cur != 0){
@@ -10268,3 +10036,45 @@
     return(0);
 }
 
+/************************************************************************
+ *									*
+ *			Node callbacks					*
+ *									*
+ ************************************************************************/
+
+/**
+ * xmlRegisterNodeDefault:
+ * @func: function pointer to the new RegisterNodeFunc
+ *
+ * Registers a callback for node creation
+ *
+ * Returns the old value of the registration function
+ */
+xmlRegisterNodeFunc
+xmlRegisterNodeDefault(xmlRegisterNodeFunc func)
+{
+    xmlRegisterNodeFunc old = xmlRegisterNodeDefaultValue;
+
+    __xmlRegisterCallbacks = 1;
+    xmlRegisterNodeDefaultValue = func;
+    return(old);
+}
+
+/**
+ * xmlDeregisterNodeDefault:
+ * @func: function pointer to the new DeregisterNodeFunc
+ *
+ * Registers a callback for node destruction
+ *
+ * Returns the previous value of the deregistration function
+ */
+xmlDeregisterNodeFunc
+xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func)
+{
+    xmlDeregisterNodeFunc old = xmlDeregisterNodeDefaultValue;
+
+    __xmlRegisterCallbacks = 1;
+    xmlDeregisterNodeDefaultValue = func;
+    return(old);
+}
+
diff --git a/third_party/libxml/src/uri.c b/third_party/libxml/src/uri.c
index c3d4871f..03b5a31 100644
--- a/third_party/libxml/src/uri.c
+++ b/third_party/libxml/src/uri.c
@@ -16,7 +16,6 @@
 
 #include <libxml/xmlmemory.h>
 #include <libxml/uri.h>
-#include <libxml/globals.h>
 #include <libxml/xmlerror.h>
 
 #include "private/error.h"
diff --git a/third_party/libxml/src/valid.c b/third_party/libxml/src/valid.c
index 479fa62..76d657d6 100644
--- a/third_party/libxml/src/valid.c
+++ b/third_party/libxml/src/valid.c
@@ -21,7 +21,6 @@
 #include <libxml/parserInternals.h>
 #include <libxml/xmlerror.h>
 #include <libxml/list.h>
-#include <libxml/globals.h>
 
 #include "private/error.h"
 #include "private/parser.h"
@@ -29,8 +28,6 @@
 static xmlElementPtr
 xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
                       int create);
-/* #define DEBUG_VALID_ALGO */
-/* #define DEBUG_REGEXP_ALGO */
 
 #define TODO								\
     xmlGenericError(xmlGenericErrorContext,				\
@@ -465,151 +462,6 @@
     return (ret);
 }
 
-#ifdef DEBUG_VALID_ALGO
-static void
-xmlValidPrintNode(xmlNodePtr cur) {
-    if (cur == NULL) {
-	xmlGenericError(xmlGenericErrorContext, "null");
-	return;
-    }
-    switch (cur->type) {
-	case XML_ELEMENT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "%s ", cur->name);
-	    break;
-	case XML_TEXT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "text ");
-	    break;
-	case XML_CDATA_SECTION_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "cdata ");
-	    break;
-	case XML_ENTITY_REF_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "&%s; ", cur->name);
-	    break;
-	case XML_PI_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "pi(%s) ", cur->name);
-	    break;
-	case XML_COMMENT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "comment ");
-	    break;
-	case XML_ATTRIBUTE_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?attr? ");
-	    break;
-	case XML_ENTITY_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?ent? ");
-	    break;
-	case XML_DOCUMENT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?doc? ");
-	    break;
-	case XML_DOCUMENT_TYPE_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?doctype? ");
-	    break;
-	case XML_DOCUMENT_FRAG_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?frag? ");
-	    break;
-	case XML_NOTATION_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?nota? ");
-	    break;
-	case XML_HTML_DOCUMENT_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?html? ");
-	    break;
-	case XML_DTD_NODE:
-	    xmlGenericError(xmlGenericErrorContext, "?dtd? ");
-	    break;
-	case XML_ELEMENT_DECL:
-	    xmlGenericError(xmlGenericErrorContext, "?edecl? ");
-	    break;
-	case XML_ATTRIBUTE_DECL:
-	    xmlGenericError(xmlGenericErrorContext, "?adecl? ");
-	    break;
-	case XML_ENTITY_DECL:
-	    xmlGenericError(xmlGenericErrorContext, "?entdecl? ");
-	    break;
-	case XML_NAMESPACE_DECL:
-	    xmlGenericError(xmlGenericErrorContext, "?nsdecl? ");
-	    break;
-	case XML_XINCLUDE_START:
-	    xmlGenericError(xmlGenericErrorContext, "incstart ");
-	    break;
-	case XML_XINCLUDE_END:
-	    xmlGenericError(xmlGenericErrorContext, "incend ");
-	    break;
-    }
-}
-
-static void
-xmlValidPrintNodeList(xmlNodePtr cur) {
-    if (cur == NULL)
-	xmlGenericError(xmlGenericErrorContext, "null ");
-    while (cur != NULL) {
-	xmlValidPrintNode(cur);
-	cur = cur->next;
-    }
-}
-
-static void
-xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) {
-    char expr[5000];
-
-    expr[0] = 0;
-    xmlGenericError(xmlGenericErrorContext, "valid: ");
-    xmlValidPrintNodeList(cur);
-    xmlGenericError(xmlGenericErrorContext, "against ");
-    xmlSnprintfElementContent(expr, 5000, cont, 1);
-    xmlGenericError(xmlGenericErrorContext, "%s\n", expr);
-}
-
-static void
-xmlValidDebugState(xmlValidStatePtr state) {
-    xmlGenericError(xmlGenericErrorContext, "(");
-    if (state->cont == NULL)
-	xmlGenericError(xmlGenericErrorContext, "null,");
-    else
-	switch (state->cont->type) {
-            case XML_ELEMENT_CONTENT_PCDATA:
-		xmlGenericError(xmlGenericErrorContext, "pcdata,");
-		break;
-            case XML_ELEMENT_CONTENT_ELEMENT:
-		xmlGenericError(xmlGenericErrorContext, "%s,",
-			        state->cont->name);
-		break;
-            case XML_ELEMENT_CONTENT_SEQ:
-		xmlGenericError(xmlGenericErrorContext, "seq,");
-		break;
-            case XML_ELEMENT_CONTENT_OR:
-		xmlGenericError(xmlGenericErrorContext, "or,");
-		break;
-	}
-    xmlValidPrintNode(state->node);
-    xmlGenericError(xmlGenericErrorContext, ",%d,%X,%d)",
-	    state->depth, state->occurs, state->state);
-}
-
-static void
-xmlValidStateDebug(xmlValidCtxtPtr ctxt) {
-    int i, j;
-
-    xmlGenericError(xmlGenericErrorContext, "state: ");
-    xmlValidDebugState(ctxt->vstate);
-    xmlGenericError(xmlGenericErrorContext, " stack: %d ",
-	    ctxt->vstateNr - 1);
-    for (i = 0, j = ctxt->vstateNr - 1;(i < 3) && (j > 0);i++,j--)
-	xmlValidDebugState(&ctxt->vstateTab[j]);
-    xmlGenericError(xmlGenericErrorContext, "\n");
-}
-
-/*****
-#define DEBUG_VALID_STATE(n,c) xmlValidDebug(n,c);
- *****/
-
-#define DEBUG_VALID_STATE(n,c) xmlValidStateDebug(ctxt);
-#define DEBUG_VALID_MSG(m)					\
-    xmlGenericError(xmlGenericErrorContext, "%s\n", m);
-
-#else
-#define DEBUG_VALID_STATE(n,c)
-#define DEBUG_VALID_MSG(m)
-#endif
-
 /* TODO: use hash table for accesses to elem and attribute definitions */
 
 
@@ -828,9 +680,6 @@
 	                XML_DTD_CONTENT_NOT_DETERMINIST,
 	       "Content model of %s is not deterministic: %s\n",
 	       elem->name, BAD_CAST expr, NULL);
-#ifdef DEBUG_REGEXP_ALGO
-        xmlRegexpPrint(stderr, elem->contModel);
-#endif
         ctxt->valid = 0;
 	ctxt->state = NULL;
 	xmlFreeAutomata(ctxt->am);
@@ -1052,7 +901,7 @@
 	    if (cur->c1 != NULL)
 	        tmp->c1 = xmlCopyDocElementContent(doc,cur->c1);
 	    if (tmp->c1 != NULL)
-		tmp->c1->parent = ret;
+		tmp->c1->parent = tmp;
 	    prev = tmp;
 	    cur = cur->c2;
 	}
@@ -4892,13 +4741,10 @@
      * epsilon transition, go directly to the analysis phase
      */
     if (STATE == ROLLBACK_PARENT) {
-	DEBUG_VALID_MSG("restored parent branch");
-	DEBUG_VALID_STATE(NODE, CONT)
 	ret = 1;
 	goto analyze;
     }
 
-    DEBUG_VALID_STATE(NODE, CONT)
     /*
      * we may have to save a backup state here. This is the equivalent
      * of handling epsilon transition in NFAs.
@@ -4910,7 +4756,6 @@
 	((CONT->ocur == XML_ELEMENT_CONTENT_MULT) ||
 	 (CONT->ocur == XML_ELEMENT_CONTENT_OPT) ||
 	 ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) {
-	DEBUG_VALID_MSG("saving parent branch");
 	if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0)
 	    return(0);
     }
@@ -4922,12 +4767,10 @@
     switch (CONT->type) {
 	case XML_ELEMENT_CONTENT_PCDATA:
 	    if (NODE == NULL) {
-		DEBUG_VALID_MSG("pcdata failed no node");
 		ret = 0;
 		break;
 	    }
 	    if (NODE->type == XML_TEXT_NODE) {
-		DEBUG_VALID_MSG("pcdata found, skip to next");
 		/*
 		 * go to next element in the content model
 		 * skipping ignorable elems
@@ -4945,14 +4788,12 @@
                 ret = 1;
 		break;
 	    } else {
-		DEBUG_VALID_MSG("pcdata failed");
 		ret = 0;
 		break;
 	    }
 	    break;
 	case XML_ELEMENT_CONTENT_ELEMENT:
 	    if (NODE == NULL) {
-		DEBUG_VALID_MSG("element failed no node");
 		ret = 0;
 		break;
 	    }
@@ -4968,7 +4809,6 @@
 		}
 	    }
 	    if (ret == 1) {
-		DEBUG_VALID_MSG("element found, skip to next");
 		/*
 		 * go to next element in the content model
 		 * skipping ignorable elems
@@ -4984,7 +4824,6 @@
 			  (NODE->type != XML_TEXT_NODE) &&
 			  (NODE->type != XML_CDATA_SECTION_NODE)));
 	    } else {
-		DEBUG_VALID_MSG("element failed");
 		ret = 0;
 		break;
 	    }
@@ -5017,7 +4856,6 @@
 	    /*
 	     * save the second branch 'or' branch
 	     */
-	    DEBUG_VALID_MSG("saving 'or' branch");
 	    if (vstateVPush(ctxt, CONT->c2, NODE, DEPTH + 1,
 			    OCCURS, ROLLBACK_OR) < 0)
 		return(-1);
@@ -5059,7 +4897,6 @@
      * At this point handle going up in the tree
      */
     if (ret == -1) {
-	DEBUG_VALID_MSG("error found returning");
 	return(ret);
     }
 analyze:
@@ -5074,9 +4911,7 @@
 
 		case XML_ELEMENT_CONTENT_ONCE:
 		    cur = ctxt->vstate->node;
-		    DEBUG_VALID_MSG("Once branch failed, rollback");
 		    if (vstateVPop(ctxt) < 0 ) {
-			DEBUG_VALID_MSG("exhaustion, failed");
 			return(0);
 		    }
 		    if (cur != ctxt->vstate->node)
@@ -5085,69 +4920,50 @@
 		case XML_ELEMENT_CONTENT_PLUS:
 		    if (OCCURRENCE == 0) {
 			cur = ctxt->vstate->node;
-			DEBUG_VALID_MSG("Plus branch failed, rollback");
 			if (vstateVPop(ctxt) < 0 ) {
-			    DEBUG_VALID_MSG("exhaustion, failed");
 			    return(0);
 			}
 			if (cur != ctxt->vstate->node)
 			    determinist = -3;
 			goto cont;
 		    }
-		    DEBUG_VALID_MSG("Plus branch found");
 		    ret = 1;
 		    break;
 		case XML_ELEMENT_CONTENT_MULT:
-#ifdef DEBUG_VALID_ALGO
-		    if (OCCURRENCE == 0) {
-			DEBUG_VALID_MSG("Mult branch failed");
-		    } else {
-			DEBUG_VALID_MSG("Mult branch found");
-		    }
-#endif
 		    ret = 1;
 		    break;
 		case XML_ELEMENT_CONTENT_OPT:
-		    DEBUG_VALID_MSG("Option branch failed");
 		    ret = 1;
 		    break;
 	    }
 	} else {
 	    switch (CONT->ocur) {
 		case XML_ELEMENT_CONTENT_OPT:
-		    DEBUG_VALID_MSG("Option branch succeeded");
 		    ret = 1;
 		    break;
 		case XML_ELEMENT_CONTENT_ONCE:
-		    DEBUG_VALID_MSG("Once branch succeeded");
 		    ret = 1;
 		    break;
 		case XML_ELEMENT_CONTENT_PLUS:
 		    if (STATE == ROLLBACK_PARENT) {
-			DEBUG_VALID_MSG("Plus branch rollback");
 			ret = 1;
 			break;
 		    }
 		    if (NODE == NULL) {
-			DEBUG_VALID_MSG("Plus branch exhausted");
 			ret = 1;
 			break;
 		    }
-		    DEBUG_VALID_MSG("Plus branch succeeded, continuing");
 		    SET_OCCURRENCE;
 		    goto cont;
 		case XML_ELEMENT_CONTENT_MULT:
 		    if (STATE == ROLLBACK_PARENT) {
-			DEBUG_VALID_MSG("Mult branch rollback");
 			ret = 1;
 			break;
 		    }
 		    if (NODE == NULL) {
-			DEBUG_VALID_MSG("Mult branch exhausted");
 			ret = 1;
 			break;
 		    }
-		    DEBUG_VALID_MSG("Mult branch succeeded, continuing");
 		    /* SET_OCCURRENCE; */
 		    goto cont;
 	    }
@@ -5164,33 +4980,26 @@
 
 	switch (CONT->parent->type) {
 	    case XML_ELEMENT_CONTENT_PCDATA:
-		DEBUG_VALID_MSG("Error: parent pcdata");
 		return(-1);
 	    case XML_ELEMENT_CONTENT_ELEMENT:
-		DEBUG_VALID_MSG("Error: parent element");
 		return(-1);
 	    case XML_ELEMENT_CONTENT_OR:
 		if (ret == 1) {
-		    DEBUG_VALID_MSG("Or succeeded");
 		    CONT = CONT->parent;
 		    DEPTH--;
 		} else {
-		    DEBUG_VALID_MSG("Or failed");
 		    CONT = CONT->parent;
 		    DEPTH--;
 		}
 		break;
 	    case XML_ELEMENT_CONTENT_SEQ:
 		if (ret == 0) {
-		    DEBUG_VALID_MSG("Sequence failed");
 		    CONT = CONT->parent;
 		    DEPTH--;
 		} else if (CONT == CONT->parent->c1) {
-		    DEBUG_VALID_MSG("Sequence testing 2nd branch");
 		    CONT = CONT->parent->c2;
 		    goto cont;
 		} else {
-		    DEBUG_VALID_MSG("Sequence succeeded");
 		    CONT = CONT->parent;
 		    DEPTH--;
 		}
@@ -5200,9 +5009,7 @@
 	xmlNodePtr cur;
 
 	cur = ctxt->vstate->node;
-	DEBUG_VALID_MSG("Failed, remaining input, rollback");
 	if (vstateVPop(ctxt) < 0 ) {
-	    DEBUG_VALID_MSG("exhaustion, failed");
 	    return(0);
 	}
 	if (cur != ctxt->vstate->node)
@@ -5213,9 +5020,7 @@
 	xmlNodePtr cur;
 
 	cur = ctxt->vstate->node;
-	DEBUG_VALID_MSG("Failure, rollback");
 	if (vstateVPop(ctxt) < 0 ) {
-	    DEBUG_VALID_MSG("exhaustion, failed");
 	    return(0);
 	}
 	if (cur != ctxt->vstate->node)
@@ -5454,7 +5259,6 @@
 	 * Build a minimal representation of this node content
 	 * sufficient to run the validation process on it
 	 */
-	DEBUG_VALID_MSG("Found an entity reference, linearizing");
 	cur = child;
 	while (cur != NULL) {
 	    switch (cur->type) {
@@ -6460,7 +6264,7 @@
  * xmlValidateElement:
  * @ctxt:  the validation context
  * @doc:  a document instance
- * @elem:  an element instance
+ * @root:  an element instance
  *
  * Try to validate the subtree under an element
  *
diff --git a/third_party/libxml/src/win32/Makefile.bcb b/third_party/libxml/src/win32/Makefile.bcb
index bf599a5..13e0239 100644
--- a/third_party/libxml/src/win32/Makefile.bcb
+++ b/third_party/libxml/src/win32/Makefile.bcb
@@ -57,8 +57,8 @@
 !if "$(DYNRUNTIME)" == "1"
 CFLAGS = $(CFLAGS) -tWR
 !endif
-!if "$(WITH_THREADS)" == "yes" || "$(WITH_THREADS)" == "ctls"
-CFLAGS = $(CFLAGS) -DHAVE_COMPILER_TLS
+!if "$(WITH_THREADS)" == "ctls"
+CFLAGS = $(CFLAGS) "-DXML_THREAD_LOCAL=__declspec(thread)"
 !else if "$(WITH_THREADS)" == "posix"
 CFLAGS = $(CFLAGS) -DHAVE_PTHREAD_H
 !endif
diff --git a/third_party/libxml/src/win32/Makefile.mingw b/third_party/libxml/src/win32/Makefile.mingw
index bd0c4297..620dc1d3 100644
--- a/third_party/libxml/src/win32/Makefile.mingw
+++ b/third_party/libxml/src/win32/Makefile.mingw
@@ -45,11 +45,8 @@
 ifneq ($(WITH_THREADS),no)
 CFLAGS += -D_REENTRANT
 endif
-ifeq ($(WITH_THREADS),yes) 
-CFLAGS += -DHAVE_COMPILER_TLS
-endif
 ifeq ($(WITH_THREADS),ctls)
-CFLAGS += -DHAVE_COMPILER_TLS
+CFLAGS += "-DXML_THREAD_LOCAL=__declspec(thread)"
 endif
 ifeq ($(WITH_THREADS),posix)
 CFLAGS += -DHAVE_PTHREAD_H
diff --git a/third_party/libxml/src/win32/Makefile.msvc b/third_party/libxml/src/win32/Makefile.msvc
index cf348f5e..bc8ddd0 100644
--- a/third_party/libxml/src/win32/Makefile.msvc
+++ b/third_party/libxml/src/win32/Makefile.msvc
@@ -48,8 +48,8 @@
 !if "$(WITH_THREADS)" != "no"
 CFLAGS = $(CFLAGS) /D "_REENTRANT"
 !endif
-!if "$(WITH_THREADS)" == "yes" || "$(WITH_THREADS)" == "ctls"
-CFLAGS = $(CFLAGS) /D "HAVE_COMPILER_TLS"
+!if "$(WITH_THREADS)" == "ctls"
+CFLAGS = $(CFLAGS) /D "XML_THREAD_LOCAL=__declspec(thread)"
 !else if "$(WITH_THREADS)" == "posix"
 CFLAGS = $(CFLAGS) /D "HAVE_PTHREAD_H"
 !endif
diff --git a/third_party/libxml/src/xmlIO.c b/third_party/libxml/src/xmlIO.c
index 9fd9c780..90379e2 100644
--- a/third_party/libxml/src/xmlIO.c
+++ b/third_party/libxml/src/xmlIO.c
@@ -50,10 +50,10 @@
 #  endif
 #endif
 
+#include <libxml/xmlIO.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
-#include <libxml/xmlIO.h>
 #include <libxml/uri.h>
 #include <libxml/nanohttp.h>
 #include <libxml/nanoftp.h>
@@ -61,7 +61,6 @@
 #ifdef LIBXML_CATALOG_ENABLED
 #include <libxml/catalog.h>
 #endif
-#include <libxml/globals.h>
 
 #include "private/buf.h"
 #include "private/enc.h"
@@ -70,14 +69,8 @@
 #include "private/parser.h"
 
 /* #define VERBOSE_FAILURE */
-/* #define DEBUG_EXTERNAL_ENTITIES */
-/* #define DEBUG_INPUT */
 
-#ifdef DEBUG_INPUT
-#define MINLEN 40
-#else
 #define MINLEN 4000
-#endif
 
 /*
  * Input I/O callback sets
@@ -1449,23 +1442,11 @@
 static void
 xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
 
-#ifdef DEBUG_HTTP
-    int z_err;
-#endif
-
     if ( buff == NULL )
 	return;
 
     xmlFree( buff->zbuff );
-#ifdef DEBUG_HTTP
-    z_err = deflateEnd( &buff->zctrl );
-    if ( z_err != Z_OK )
-	xmlGenericError( xmlGenericErrorContext,
-			"xmlFreeZMemBuff:  Error releasing zlib context:  %d\n",
-			z_err );
-#else
     deflateEnd( &buff->zctrl );
-#endif
 
     xmlFree( buff );
     return;
@@ -1563,15 +1544,6 @@
     cur_used = buff->zctrl.next_out - buff->zbuff;
     new_size = buff->size + ext_amt;
 
-#ifdef DEBUG_HTTP
-    if ( cur_used > new_size )
-	xmlGenericError( xmlGenericErrorContext,
-			"xmlZMemBuffExtend:  %s\n%s %d bytes.\n",
-			"Buffer overwrite detected during compressed memory",
-			"buffer extension.  Overflowed by",
-			(cur_used - new_size ) );
-#endif
-
     tmp_ptr = xmlRealloc( buff->zbuff, new_size );
     if ( tmp_ptr != NULL ) {
 	rc = 0;
@@ -1992,57 +1964,6 @@
 					content_lgth );
 
 	if ( http_ctxt != NULL ) {
-#ifdef DEBUG_HTTP
-	    /*  If testing/debugging - dump reply with request content  */
-
-	    FILE *	tst_file = NULL;
-	    char	buffer[ 4096 ];
-	    char *	dump_name = NULL;
-	    int		avail;
-
-	    xmlGenericError( xmlGenericErrorContext,
-			"xmlNanoHTTPCloseWrite:  HTTP %s to\n%s returned %d.\n",
-			http_mthd, ctxt->uri,
-			xmlNanoHTTPReturnCode( http_ctxt ) );
-
-	    /*
-	    **  Since either content or reply may be gzipped,
-	    **  dump them to separate files instead of the
-	    **  standard error context.
-	    */
-
-	    dump_name = tempnam( NULL, "lxml" );
-	    if ( dump_name != NULL ) {
-		(void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name );
-
-		tst_file = fopen( buffer, "wb" );
-		if ( tst_file != NULL ) {
-		    xmlGenericError( xmlGenericErrorContext,
-			"Transmitted content saved in file:  %s\n", buffer );
-
-		    fwrite( http_content, 1, content_lgth, tst_file );
-		    fclose( tst_file );
-		}
-
-		(void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name );
-		tst_file = fopen( buffer, "wb" );
-		if ( tst_file != NULL ) {
-		    xmlGenericError( xmlGenericErrorContext,
-			"Reply content saved in file:  %s\n", buffer );
-
-
-		    while ( (avail = xmlNanoHTTPRead( http_ctxt,
-					buffer, sizeof( buffer ) )) > 0 ) {
-
-			fwrite( buffer, 1, avail, tst_file );
-		    }
-
-		    fclose( tst_file );
-		}
-
-		free( dump_name );
-	    }
-#endif  /*  DEBUG_HTTP  */
 
 	    http_rtn = xmlNanoHTTPReturnCode( http_ctxt );
 	    if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) )
@@ -2909,6 +2830,31 @@
     return(ret);
 }
 
+typedef struct {
+    const char *mem;
+    size_t size;
+} xmlMemIOCtxt;
+
+static int
+xmlMemRead(void *vctxt, char *buf, int size) {
+    xmlMemIOCtxt *ctxt = vctxt;
+
+    if ((size_t) size > ctxt->size)
+        size = ctxt->size;
+
+    memcpy(buf, ctxt->mem, size);
+    ctxt->mem += size;
+    ctxt->size -= size;
+
+    return size;
+}
+
+static int
+xmlMemClose(void *vctxt) {
+    xmlFree(vctxt);
+    return(0);
+}
+
 /**
  * xmlParserInputBufferCreateMem:
  * @mem:  the memory input
@@ -2923,22 +2869,26 @@
 xmlParserInputBufferPtr
 xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
     xmlParserInputBufferPtr ret;
-    int errcode;
+    xmlMemIOCtxt *ctxt;
 
     if (size < 0) return(NULL);
     if (mem == NULL) return(NULL);
 
     ret = xmlAllocParserInputBuffer(enc);
-    if (ret != NULL) {
-        ret->context = (void *) mem;
-	ret->readcallback = NULL;
-	ret->closecallback = NULL;
-	errcode = xmlBufAdd(ret->buffer, (const xmlChar *) mem, size);
-	if (errcode != 0) {
-	    xmlFreeParserInputBuffer(ret);
-	    return(NULL);
-	}
+    if (ret == NULL)
+        return(NULL);
+
+    ctxt = xmlMalloc(sizeof(*ctxt));
+    if (ctxt == NULL) {
+        xmlFreeParserInputBuffer(ret);
+        return(NULL);
     }
+    ctxt->mem = mem;
+    ctxt->size = size;
+
+    ret->context = ctxt;
+    ret->readcallback = xmlMemRead;
+    ret->closecallback = xmlMemClose;
 
     return(ret);
 }
@@ -2959,6 +2909,65 @@
     return(xmlParserInputBufferCreateMem(mem, size, enc));
 }
 
+typedef struct {
+    const xmlChar *str;
+} xmlStringIOCtxt;
+
+static int
+xmlStringRead(void *vctxt, char *buf, int size) {
+    xmlStringIOCtxt *ctxt = vctxt;
+    const xmlChar *zero;
+    size_t len;
+
+    zero = memchr(ctxt->str, 0, size);
+    len = zero ? zero - ctxt->str : size;
+
+    memcpy(buf, ctxt->str, len);
+    ctxt->str += len;
+
+    return(len);
+}
+
+static int
+xmlStringClose(void *vctxt) {
+    xmlFree(vctxt);
+    return(0);
+}
+
+/**
+ * xmlParserInputBufferCreateString:
+ * @str:  a null-terminated string
+ *
+ * Create a buffered parser input for the progressive parsing for the input
+ * from a null-terminated C string.
+ *
+ * Returns the new parser input or NULL
+ */
+xmlParserInputBufferPtr
+xmlParserInputBufferCreateString(const xmlChar *str) {
+    xmlParserInputBufferPtr ret;
+    xmlStringIOCtxt *ctxt;
+
+    if (str == NULL) return(NULL);
+
+    ret = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
+    if (ret == NULL)
+        return(NULL);
+
+    ctxt = xmlMalloc(sizeof(*ctxt));
+    if (ctxt == NULL) {
+        xmlFreeParserInputBuffer(ret);
+        return(NULL);
+    }
+    ctxt->str = str;
+
+    ret->context = ctxt;
+    ret->readcallback = xmlStringRead;
+    ret->closecallback = xmlStringClose;
+
+    return(ret);
+}
+
 #ifdef LIBXML_OUTPUT_ENABLED
 /**
  * xmlOutputBufferCreateFd:
@@ -3111,8 +3120,6 @@
     if (len < 0) return(0);
     if ((in == NULL) || (in->error)) return(-1);
     if (in->encoder != NULL) {
-        size_t use, consumed;
-
         /*
 	 * Store the data in the incoming raw buffer
 	 */
@@ -3132,16 +3139,9 @@
 	/*
 	 * convert as much as possible to the parser reading buffer.
 	 */
-	use = xmlBufUse(in->raw);
-	nbchars = xmlCharEncInput(in, 1);
+	nbchars = xmlCharEncInput(in);
 	if (nbchars < 0)
 	    return(-1);
-        consumed = use - xmlBufUse(in->raw);
-        if ((consumed > ULONG_MAX) ||
-            (in->rawconsumed > ULONG_MAX - (unsigned long)consumed))
-            in->rawconsumed = ULONG_MAX;
-        else
-	    in->rawconsumed += consumed;
     } else {
 	nbchars = len;
         ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
@@ -3150,11 +3150,6 @@
 	    return(-1);
         }
     }
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: pushed %d chars, buffer %d/%d\n",
-            nbchars, xmlBufUse(in->buffer), xmlBufLength(in->buffer));
-#endif
     return(nbchars);
 }
 
@@ -3240,27 +3235,10 @@
     }
 
     if (in->encoder != NULL) {
-        size_t use, consumed;
-
-	/*
-	 * convert as much as possible to the parser reading buffer.
-	 */
-	use = xmlBufUse(buf);
-	res = xmlCharEncInput(in, 1);
+	res = xmlCharEncInput(in);
 	if (res < 0)
 	    return(-1);
-        consumed = use - xmlBufUse(buf);
-        if ((consumed > ULONG_MAX) ||
-            (in->rawconsumed > ULONG_MAX - (unsigned long)consumed))
-            in->rawconsumed = ULONG_MAX;
-        else
-	    in->rawconsumed += consumed;
     }
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: read %d chars, buffer %d\n",
-            nbchars, xmlBufUse(in->buffer));
-#endif
     return(res);
 }
 
@@ -3386,10 +3364,6 @@
     } while (len > 0);
 
 done:
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: wrote %d chars\n", written);
-#endif
     return(written);
 }
 
@@ -3586,10 +3560,6 @@
     } while ((len > 0) && (oldwritten != written));
 
 done:
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: wrote %d chars\n", written);
-#endif
     return(written);
 }
 
@@ -3677,10 +3647,6 @@
     else
         out->written += ret;
 
-#ifdef DEBUG_INPUT
-    xmlGenericError(xmlGenericErrorContext,
-	    "I/O: flushed %d chars\n", ret);
-#endif
     return(ret);
 }
 #endif /* LIBXML_OUTPUT_ENABLED */
@@ -3790,8 +3756,6 @@
                                          "Unknown encoding %s",
                                          BAD_CAST encoding, NULL);
                     }
-                    if (ret->encoding == NULL)
-                        ret->encoding = xmlStrdup(BAD_CAST encoding);
                 }
 #if 0
             } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) {
@@ -3933,10 +3897,6 @@
     xmlParserInputPtr ret = NULL;
     xmlChar *resource = NULL;
 
-#ifdef DEBUG_EXTERNAL_ENTITIES
-    xmlGenericError(xmlGenericErrorContext,
-                    "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
-#endif
     if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) {
         int options = ctxt->options;
 
diff --git a/third_party/libxml/src/xmlmemory.c b/third_party/libxml/src/xmlmemory.c
index c399cbb..1e999b11 100644
--- a/third_party/libxml/src/xmlmemory.c
+++ b/third_party/libxml/src/xmlmemory.c
@@ -12,8 +12,6 @@
 #include <ctype.h>
 #include <time.h>
 
-/* #define DEBUG_MEMORY */
-
 /**
  * MEM_LIST:
  *
@@ -26,9 +24,9 @@
 #endif
 #endif
 
-#include <libxml/globals.h>	/* must come before xmlmemory.h */
 #include <libxml/xmlmemory.h>
 #include <libxml/xmlerror.h>
+#include <libxml/parser.h>
 #include <libxml/threads.h>
 
 #include "private/memory.h"
@@ -150,10 +148,6 @@
     void *ret;
 
     xmlInitParser();
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Malloc(%d)\n",size);
-#endif
 
     TEST_POINT
 
@@ -185,11 +179,6 @@
 #endif
     xmlMutexUnlock(&xmlMemMutex);
 
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Malloc(%d) Ok\n",size);
-#endif
-
     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
 
     ret = HDR_2_CLIENT(p);
@@ -224,10 +213,6 @@
     void *ret;
 
     xmlInitParser();
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Malloc(%d)\n",size);
-#endif
 
     TEST_POINT
 
@@ -259,11 +244,6 @@
 #endif
     xmlMutexUnlock(&xmlMemMutex);
 
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Malloc(%d) Ok\n",size);
-#endif
-
     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
 
     ret = HDR_2_CLIENT(p);
@@ -311,9 +291,6 @@
 {
     MEMHDR *p, *tmp;
     unsigned long number;
-#ifdef DEBUG_MEMORY
-    size_t oldsize;
-#endif
 
     if (ptr == NULL)
         return(xmlMallocLoc(size, file, line));
@@ -332,9 +309,6 @@
     xmlMutexLock(&xmlMemMutex);
     debugMemSize -= p->mh_size;
     debugMemBlocks--;
-#ifdef DEBUG_MEMORY
-    oldsize = p->mh_size;
-#endif
 #ifdef MEM_LIST
     debugmem_list_delete(p);
 #endif
@@ -376,10 +350,6 @@
 
     TEST_POINT
 
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Realloced(%d to %d) Ok\n", oldsize, size);
-#endif
     return(HDR_2_CLIENT(p));
 
 error:
@@ -412,9 +382,6 @@
 {
     MEMHDR *p;
     char *target;
-#ifdef DEBUG_MEMORY
-    size_t size;
-#endif
 
     if (ptr == NULL)
 	return;
@@ -446,9 +413,6 @@
     xmlMutexLock(&xmlMemMutex);
     debugMemSize -= p->mh_size;
     debugMemBlocks--;
-#ifdef DEBUG_MEMORY
-    size = p->mh_size;
-#endif
 #ifdef MEM_LIST
     debugmem_list_delete(p);
 #endif
@@ -458,11 +422,6 @@
 
     TEST_POINT
 
-#ifdef DEBUG_MEMORY
-    xmlGenericError(xmlGenericErrorContext,
-	    "Freed(%d) Ok\n", size);
-#endif
-
     return;
 
 error:
@@ -753,10 +712,6 @@
      p->mh_prev = NULL;
      if (memlist) memlist->mh_prev = p;
      memlist = p;
-#ifdef MEM_LIST_DEBUG
-     if (stderr)
-     Mem_Display(stderr);
-#endif
 }
 
 static void debugmem_list_delete(MEMHDR *p)
@@ -766,10 +721,6 @@
      if (p->mh_prev)
      p->mh_prev->mh_next = p->mh_next;
      else memlist = p->mh_next;
-#ifdef MEM_LIST_DEBUG
-     if (stderr)
-     Mem_Display(stderr);
-#endif
 }
 
 #endif
@@ -894,10 +845,6 @@
 void
 xmlInitMemoryInternal(void) {
      char *breakpoint;
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlInitMemory()\n");
-#endif
      xmlInitMutex(&xmlMemMutex);
 
      breakpoint = getenv("XML_MEM_BREAKPOINT");
@@ -909,10 +856,6 @@
          sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
      }
 
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlInitMemory() Ok\n");
-#endif
 }
 
 /**
@@ -935,15 +878,15 @@
  */
 void
 xmlCleanupMemoryInternal(void) {
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlCleanupMemory()\n");
-#endif
-
+    /*
+     * Don't clean up mutex on Windows. Global state destructors can call
+     * malloc functions after xmlCleanupParser was called. If memory
+     * debugging is enabled, xmlMemMutex can be used after cleanup.
+     *
+     * See python/tests/thread2.py
+     */
+#if !defined(LIBXML_THREAD_ENABLED) || !defined(_WIN32)
     xmlCleanupMutex(&xmlMemMutex);
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlCleanupMemory() Ok\n");
 #endif
 }
 
@@ -965,10 +908,6 @@
 int
 xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
             xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlMemSetup()\n");
-#endif
     if (freeFunc == NULL)
 	return(-1);
     if (mallocFunc == NULL)
@@ -982,10 +921,6 @@
     xmlMallocAtomic = mallocFunc;
     xmlRealloc = reallocFunc;
     xmlMemStrdup = strdupFunc;
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlMemSetup() Ok\n");
-#endif
     return(0);
 }
 
@@ -1032,10 +967,6 @@
 xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
               xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
 	      xmlStrdupFunc strdupFunc) {
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlGcMemSetup()\n");
-#endif
     if (freeFunc == NULL)
 	return(-1);
     if (mallocFunc == NULL)
@@ -1051,10 +982,6 @@
     xmlMallocAtomic = mallocAtomicFunc;
     xmlRealloc = reallocFunc;
     xmlMemStrdup = strdupFunc;
-#ifdef DEBUG_MEMORY
-     xmlGenericError(xmlGenericErrorContext,
-	     "xmlGcMemSetup() Ok\n");
-#endif
     return(0);
 }
 
diff --git a/third_party/libxml/src/xmlreader.c b/third_party/libxml/src/xmlreader.c
index 71f2f93..c04cb11 100644
--- a/third_party/libxml/src/xmlreader.c
+++ b/third_party/libxml/src/xmlreader.c
@@ -77,9 +77,6 @@
   #endif
 #endif
 
-/* #define DEBUG_CALLBACKS */
-/* #define DEBUG_READER */
-
 /**
  * TODO:
  *
@@ -90,12 +87,6 @@
 	    "Unimplemented block at %s:%d\n",				\
             __FILE__, __LINE__);
 
-#ifdef DEBUG_READER
-#define DUMP_READER xmlTextReaderDebug(reader);
-#else
-#define DUMP_READER
-#endif
-
 #define CHUNK_SIZE 512
 /************************************************************************
  *									*
@@ -505,33 +496,6 @@
  *			The reader core parser				*
  *									*
  ************************************************************************/
-#ifdef DEBUG_READER
-static void
-xmlTextReaderDebug(xmlTextReaderPtr reader) {
-    if ((reader == NULL) || (reader->ctxt == NULL)) {
-	fprintf(stderr, "xmlTextReader NULL\n");
-	return;
-    }
-    fprintf(stderr, "xmlTextReader: state %d depth %d ",
-	    reader->state, reader->depth);
-    if (reader->node == NULL) {
-	fprintf(stderr, "node = NULL\n");
-    } else {
-	fprintf(stderr, "node %s\n", reader->node->name);
-    }
-    fprintf(stderr, "  input: base %d, cur %d, depth %d: ",
-	    reader->base, reader->cur, reader->ctxt->nodeNr);
-    if (reader->input->buffer == NULL) {
-	fprintf(stderr, "buffer is NULL\n");
-    } else {
-#ifdef LIBXML_DEBUG_ENABLED
-	xmlDebugDumpString(stderr,
-		&reader->input->buffer->content[reader->cur]);
-#endif
-	fprintf(stderr, "\n");
-    }
-}
-#endif
 
 /**
  * xmlTextReaderEntPush:
@@ -602,9 +566,6 @@
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderStartElement(%s)\n", fullname);
-#endif
     if ((reader != NULL) && (reader->startElement != NULL)) {
 	reader->startElement(ctx, fullname, atts);
 	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
@@ -628,9 +589,6 @@
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderEndElement(%s)\n", fullname);
-#endif
     if ((reader != NULL) && (reader->endElement != NULL)) {
 	reader->endElement(ctx, fullname);
     }
@@ -665,9 +623,6 @@
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderStartElementNs(%s)\n", localname);
-#endif
     if ((reader != NULL) && (reader->startElementNs != NULL)) {
 	reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
 	                       namespaces, nb_attributes, nb_defaulted,
@@ -699,9 +654,6 @@
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderEndElementNs(%s)\n", localname);
-#endif
     if ((reader != NULL) && (reader->endElementNs != NULL)) {
 	reader->endElementNs(ctx, localname, prefix, URI);
     }
@@ -722,9 +674,6 @@
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderCharacters()\n");
-#endif
     if ((reader != NULL) && (reader->characters != NULL)) {
 	reader->characters(ctx, ch, len);
     }
@@ -744,9 +693,6 @@
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
     xmlTextReaderPtr reader = ctxt->_private;
 
-#ifdef DEBUG_CALLBACKS
-    printf("xmlTextReaderCDataBlock()\n");
-#endif
     if ((reader != NULL) && (reader->cdataBlock != NULL)) {
 	reader->cdataBlock(ctx, ch, len);
     }
@@ -781,24 +727,17 @@
 	     */
 	    if (reader->mode != XML_TEXTREADER_MODE_EOF) {
 		val = xmlParserInputBufferRead(reader->input, 4096);
-		if ((val == 0) &&
-		    (reader->input->readcallback == NULL)) {
+		if (val == 0) {
 		    if (xmlBufUse(inbuf) == reader->cur) {
 			reader->mode = XML_TEXTREADER_MODE_EOF;
-			reader->state = oldstate;
+                        break;
 		    }
 		} else if (val < 0) {
                     xmlGenericError(xmlGenericErrorContext,
                                     "xmlParserInputBufferRead failed\n");
 		    reader->mode = XML_TEXTREADER_MODE_EOF;
 		    reader->state = oldstate;
-		    if ((oldstate != XML_TEXTREADER_START) ||
-			(reader->ctxt->myDoc != NULL))
-			return(val);
-		} else if (val == 0) {
-		    /* mark the end of the stream and process the remains */
-		    reader->mode = XML_TEXTREADER_MODE_EOF;
-		    break;
+		    return(val);
 		}
 
 	    } else
@@ -828,6 +767,7 @@
 	    break;
 	}
     }
+    reader->state = oldstate;
 
     /*
      * Discard the consumed input when needed and possible
@@ -864,7 +804,6 @@
 	    }
 	}
     }
-    reader->state = oldstate;
     if (reader->ctxt->wellFormed == 0) {
 	reader->mode = XML_TEXTREADER_MODE_EOF;
         return(-1);
@@ -1232,10 +1171,6 @@
     if (reader->ctxt == NULL)
 	return(-1);
 
-#ifdef DEBUG_READER
-    fprintf(stderr, "\nREAD ");
-    DUMP_READER
-#endif
     if (reader->mode == XML_TEXTREADER_MODE_INITIAL) {
 	reader->mode = XML_TEXTREADER_MODE_INTERACTIVE;
 	/*
@@ -1427,8 +1362,6 @@
     reader->state = XML_TEXTREADER_BACKTRACK;
 
 node_found:
-    DUMP_READER
-
     /*
      * If we are in the middle of a piece of CDATA make sure it's finished
      */
@@ -5238,6 +5171,19 @@
 }
 
 /**
+ * xmlTextReaderSetMaxAmplification:
+ * @reader: an XML reader
+ * @maxAmpl:  maximum amplification factor
+ *
+ * Set the maximum amplification factor. See xmlCtxtSetMaxAmplification.
+ */
+void
+xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader, unsigned maxAmpl)
+{
+    xmlCtxtSetMaxAmplification(reader->ctxt, maxAmpl);
+}
+
+/**
  * xmlTextReaderByteConsumed:
  * @reader: an XML reader
  *
diff --git a/third_party/libxml/src/xmlsave.c b/third_party/libxml/src/xmlsave.c
index 5b5c8f1..125853ff 100644
--- a/third_party/libxml/src/xmlsave.c
+++ b/third_party/libxml/src/xmlsave.c
@@ -1847,7 +1847,7 @@
 /**
  * xmlSaveTree:
  * @ctxt:  a document saving context
- * @node:  the top node of the subtree to save
+ * @cur:  the top node of the subtree to save
  *
  * Save a subtree starting at the node parameter to a saving context
  * TODO: The function is not fully implemented yet as it does not return the
@@ -2166,17 +2166,9 @@
     xmlInitParser();
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlNodeDump : node == NULL\n");
-#endif
         return (-1);
     }
     if (buf == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlNodeDump : buf == NULL\n");
-#endif
         return (-1);
     }
     outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
@@ -2218,18 +2210,8 @@
     xmlInitParser();
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlElemDump : cur == NULL\n");
-#endif
         return;
     }
-#ifdef DEBUG_TREE
-    if (doc == NULL) {
-        xmlGenericError(xmlGenericErrorContext,
-                        "xmlElemDump : doc == NULL\n");
-    }
-#endif
 
     outbuf = xmlOutputBufferCreateFile(f, NULL);
     if (outbuf == NULL)
@@ -2274,6 +2256,8 @@
     int is_xhtml = 0;
 #endif
 
+    (void) doc;
+
     xmlInitParser();
 
     if ((buf == NULL) || (cur == NULL)) return;
@@ -2467,10 +2451,6 @@
     int ret;
 
     if (cur == NULL) {
-#ifdef DEBUG_TREE
-        xmlGenericError(xmlGenericErrorContext,
-		"xmlDocDump : document == NULL\n");
-#endif
 	return(-1);
     }
     encoding = (const char *) cur->encoding;
diff --git a/third_party/libxml/src/xmlwriter.c b/third_party/libxml/src/xmlwriter.c
index 569830c..ad6e00cc 100644
--- a/third_party/libxml/src/xmlwriter.c
+++ b/third_party/libxml/src/xmlwriter.c
@@ -16,6 +16,7 @@
 #include <libxml/parser.h>
 #include <libxml/uri.h>
 #include <libxml/HTMLtree.h>
+#include <libxml/SAX2.h>
 
 #ifdef LIBXML_WRITER_ENABLED
 
diff --git a/third_party/libxml/src/xpath.c b/third_party/libxml/src/xpath.c
index f3546c8..7ca4094 100644
--- a/third_party/libxml/src/xpath.c
+++ b/third_party/libxml/src/xpath.c
@@ -31,7 +31,6 @@
 
 #include <libxml/xmlmemory.h>
 #include <libxml/tree.h>
-#include <libxml/valid.h>
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
 #include <libxml/parserInternals.h>
@@ -44,7 +43,6 @@
 #endif
 #include <libxml/xmlerror.h>
 #include <libxml/threads.h>
-#include <libxml/globals.h>
 #ifdef LIBXML_PATTERN_ENABLED
 #include <libxml/pattern.h>
 #endif
@@ -90,13 +88,6 @@
 #define XP_OPTIMIZED_FILTER_FIRST
 
 /*
-* XP_DEBUG_OBJ_USAGE:
-* Internal flag to enable tracking of how much XPath objects have been
-* created.
-*/
-/* #define XP_DEBUG_OBJ_USAGE */
-
-/*
  * XPATH_MAX_STEPS:
  * when compiling an XPath expression we arbitrary limit the maximum
  * number of step operation in the compiled expression. 1000000 is
@@ -192,6 +183,8 @@
  * xmlXPathIsNaN:
  * @val:  a double value
  *
+ * Checks whether a double is a NaN.
+ *
  * Returns 1 if the value is a NaN, 0 otherwise
  */
 int
@@ -207,6 +200,8 @@
  * xmlXPathIsInf:
  * @val:  a double value
  *
+ * Checks whether a double is an infinity.
+ *
  * Returns 1 if the value is +Infinite, -1 if -Infinite, 0 otherwise
  */
 int
@@ -230,11 +225,6 @@
  * TODO: when compatibility allows remove all "fake node libxslt" strings
  *       the test should just be name[0] = ' '
  */
-#ifdef DEBUG_XPATH_EXPRESSION
-#define DEBUG_STEP
-#define DEBUG_EXPR
-#define DEBUG_EVAL_COUNTS
-#endif
 
 static xmlNs xmlXPathXMLNamespaceStruct = {
     NULL,
@@ -982,10 +972,6 @@
     int last;			/* index of last step in expression */
     xmlChar *expr;		/* the expression being computed */
     xmlDictPtr dict;		/* the dictionary to use if any */
-#ifdef DEBUG_EVAL_COUNTS
-    int nb;
-    xmlChar *string;
-#endif
 #ifdef XPATH_STREAMING
     xmlPatternPtr stream;
 #endif
@@ -1044,9 +1030,6 @@
     }
     memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
     cur->last = -1;
-#ifdef DEBUG_EVAL_COUNTS
-    cur->nb = 0;
-#endif
     return(cur);
 }
 
@@ -1089,11 +1072,6 @@
     if (comp->steps != NULL) {
         xmlFree(comp->steps);
     }
-#ifdef DEBUG_EVAL_COUNTS
-    if (comp->string != NULL) {
-        xmlFree(comp->string);
-    }
-#endif
 #ifdef XPATH_STREAMING
     if (comp->stream != NULL) {
         xmlFreePatternList(comp->stream);
@@ -1240,33 +1218,6 @@
     int maxBoolean;
     int maxNumber;
     int maxMisc;
-#ifdef XP_DEBUG_OBJ_USAGE
-    int dbgCachedAll;
-    int dbgCachedNodeset;
-    int dbgCachedString;
-    int dbgCachedBool;
-    int dbgCachedNumber;
-    int dbgCachedPoint;
-    int dbgCachedRange;
-    int dbgCachedLocset;
-    int dbgCachedUsers;
-    int dbgCachedXSLTTree;
-    int dbgCachedUndefined;
-
-
-    int dbgReusedAll;
-    int dbgReusedNodeset;
-    int dbgReusedString;
-    int dbgReusedBool;
-    int dbgReusedNumber;
-    int dbgReusedPoint;
-    int dbgReusedRange;
-    int dbgReusedLocset;
-    int dbgReusedUsers;
-    int dbgReusedXSLTTree;
-    int dbgReusedUndefined;
-
-#endif
 };
 
 /************************************************************************
@@ -1723,478 +1674,6 @@
     }
 }
 
-#ifdef XP_DEBUG_OBJ_USAGE
-
-/*
-* XPath object usage related debugging variables.
-*/
-static int xmlXPathDebugObjCounterUndefined = 0;
-static int xmlXPathDebugObjCounterNodeset = 0;
-static int xmlXPathDebugObjCounterBool = 0;
-static int xmlXPathDebugObjCounterNumber = 0;
-static int xmlXPathDebugObjCounterString = 0;
-static int xmlXPathDebugObjCounterPoint = 0;
-static int xmlXPathDebugObjCounterRange = 0;
-static int xmlXPathDebugObjCounterLocset = 0;
-static int xmlXPathDebugObjCounterUsers = 0;
-static int xmlXPathDebugObjCounterXSLTTree = 0;
-static int xmlXPathDebugObjCounterAll = 0;
-
-static int xmlXPathDebugObjTotalUndefined = 0;
-static int xmlXPathDebugObjTotalNodeset = 0;
-static int xmlXPathDebugObjTotalBool = 0;
-static int xmlXPathDebugObjTotalNumber = 0;
-static int xmlXPathDebugObjTotalString = 0;
-static int xmlXPathDebugObjTotalPoint = 0;
-static int xmlXPathDebugObjTotalRange = 0;
-static int xmlXPathDebugObjTotalLocset = 0;
-static int xmlXPathDebugObjTotalUsers = 0;
-static int xmlXPathDebugObjTotalXSLTTree = 0;
-static int xmlXPathDebugObjTotalAll = 0;
-
-static int xmlXPathDebugObjMaxUndefined = 0;
-static int xmlXPathDebugObjMaxNodeset = 0;
-static int xmlXPathDebugObjMaxBool = 0;
-static int xmlXPathDebugObjMaxNumber = 0;
-static int xmlXPathDebugObjMaxString = 0;
-static int xmlXPathDebugObjMaxPoint = 0;
-static int xmlXPathDebugObjMaxRange = 0;
-static int xmlXPathDebugObjMaxLocset = 0;
-static int xmlXPathDebugObjMaxUsers = 0;
-static int xmlXPathDebugObjMaxXSLTTree = 0;
-static int xmlXPathDebugObjMaxAll = 0;
-
-static void
-xmlXPathDebugObjUsageReset(xmlXPathContextPtr ctxt)
-{
-    if (ctxt != NULL) {
-	if (ctxt->cache != NULL) {
-	    xmlXPathContextCachePtr cache =
-		(xmlXPathContextCachePtr) ctxt->cache;
-
-	    cache->dbgCachedAll = 0;
-	    cache->dbgCachedNodeset = 0;
-	    cache->dbgCachedString = 0;
-	    cache->dbgCachedBool = 0;
-	    cache->dbgCachedNumber = 0;
-	    cache->dbgCachedPoint = 0;
-	    cache->dbgCachedRange = 0;
-	    cache->dbgCachedLocset = 0;
-	    cache->dbgCachedUsers = 0;
-	    cache->dbgCachedXSLTTree = 0;
-	    cache->dbgCachedUndefined = 0;
-
-	    cache->dbgReusedAll = 0;
-	    cache->dbgReusedNodeset = 0;
-	    cache->dbgReusedString = 0;
-	    cache->dbgReusedBool = 0;
-	    cache->dbgReusedNumber = 0;
-	    cache->dbgReusedPoint = 0;
-	    cache->dbgReusedRange = 0;
-	    cache->dbgReusedLocset = 0;
-	    cache->dbgReusedUsers = 0;
-	    cache->dbgReusedXSLTTree = 0;
-	    cache->dbgReusedUndefined = 0;
-	}
-    }
-
-    xmlXPathDebugObjCounterUndefined = 0;
-    xmlXPathDebugObjCounterNodeset = 0;
-    xmlXPathDebugObjCounterBool = 0;
-    xmlXPathDebugObjCounterNumber = 0;
-    xmlXPathDebugObjCounterString = 0;
-    xmlXPathDebugObjCounterPoint = 0;
-    xmlXPathDebugObjCounterRange = 0;
-    xmlXPathDebugObjCounterLocset = 0;
-    xmlXPathDebugObjCounterUsers = 0;
-    xmlXPathDebugObjCounterXSLTTree = 0;
-    xmlXPathDebugObjCounterAll = 0;
-
-    xmlXPathDebugObjTotalUndefined = 0;
-    xmlXPathDebugObjTotalNodeset = 0;
-    xmlXPathDebugObjTotalBool = 0;
-    xmlXPathDebugObjTotalNumber = 0;
-    xmlXPathDebugObjTotalString = 0;
-    xmlXPathDebugObjTotalPoint = 0;
-    xmlXPathDebugObjTotalRange = 0;
-    xmlXPathDebugObjTotalLocset = 0;
-    xmlXPathDebugObjTotalUsers = 0;
-    xmlXPathDebugObjTotalXSLTTree = 0;
-    xmlXPathDebugObjTotalAll = 0;
-
-    xmlXPathDebugObjMaxUndefined = 0;
-    xmlXPathDebugObjMaxNodeset = 0;
-    xmlXPathDebugObjMaxBool = 0;
-    xmlXPathDebugObjMaxNumber = 0;
-    xmlXPathDebugObjMaxString = 0;
-    xmlXPathDebugObjMaxPoint = 0;
-    xmlXPathDebugObjMaxRange = 0;
-    xmlXPathDebugObjMaxLocset = 0;
-    xmlXPathDebugObjMaxUsers = 0;
-    xmlXPathDebugObjMaxXSLTTree = 0;
-    xmlXPathDebugObjMaxAll = 0;
-
-}
-
-static void
-xmlXPathDebugObjUsageRequested(xmlXPathContextPtr ctxt,
-			      xmlXPathObjectType objType)
-{
-    int isCached = 0;
-
-    if (ctxt != NULL) {
-	if (ctxt->cache != NULL) {
-	    xmlXPathContextCachePtr cache =
-		(xmlXPathContextCachePtr) ctxt->cache;
-
-	    isCached = 1;
-
-	    cache->dbgReusedAll++;
-	    switch (objType) {
-		case XPATH_UNDEFINED:
-		    cache->dbgReusedUndefined++;
-		    break;
-		case XPATH_NODESET:
-		    cache->dbgReusedNodeset++;
-		    break;
-		case XPATH_BOOLEAN:
-		    cache->dbgReusedBool++;
-		    break;
-		case XPATH_NUMBER:
-		    cache->dbgReusedNumber++;
-		    break;
-		case XPATH_STRING:
-		    cache->dbgReusedString++;
-		    break;
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-		case XPATH_POINT:
-		    cache->dbgReusedPoint++;
-		    break;
-		case XPATH_RANGE:
-		    cache->dbgReusedRange++;
-		    break;
-		case XPATH_LOCATIONSET:
-		    cache->dbgReusedLocset++;
-		    break;
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-		case XPATH_USERS:
-		    cache->dbgReusedUsers++;
-		    break;
-		case XPATH_XSLT_TREE:
-		    cache->dbgReusedXSLTTree++;
-		    break;
-		default:
-		    break;
-	    }
-	}
-    }
-
-    switch (objType) {
-	case XPATH_UNDEFINED:
-	    if (! isCached)
-		xmlXPathDebugObjTotalUndefined++;
-	    xmlXPathDebugObjCounterUndefined++;
-	    if (xmlXPathDebugObjCounterUndefined >
-		xmlXPathDebugObjMaxUndefined)
-		xmlXPathDebugObjMaxUndefined =
-		    xmlXPathDebugObjCounterUndefined;
-	    break;
-	case XPATH_NODESET:
-	    if (! isCached)
-		xmlXPathDebugObjTotalNodeset++;
-	    xmlXPathDebugObjCounterNodeset++;
-	    if (xmlXPathDebugObjCounterNodeset >
-		xmlXPathDebugObjMaxNodeset)
-		xmlXPathDebugObjMaxNodeset =
-		    xmlXPathDebugObjCounterNodeset;
-	    break;
-	case XPATH_BOOLEAN:
-	    if (! isCached)
-		xmlXPathDebugObjTotalBool++;
-	    xmlXPathDebugObjCounterBool++;
-	    if (xmlXPathDebugObjCounterBool >
-		xmlXPathDebugObjMaxBool)
-		xmlXPathDebugObjMaxBool =
-		    xmlXPathDebugObjCounterBool;
-	    break;
-	case XPATH_NUMBER:
-	    if (! isCached)
-		xmlXPathDebugObjTotalNumber++;
-	    xmlXPathDebugObjCounterNumber++;
-	    if (xmlXPathDebugObjCounterNumber >
-		xmlXPathDebugObjMaxNumber)
-		xmlXPathDebugObjMaxNumber =
-		    xmlXPathDebugObjCounterNumber;
-	    break;
-	case XPATH_STRING:
-	    if (! isCached)
-		xmlXPathDebugObjTotalString++;
-	    xmlXPathDebugObjCounterString++;
-	    if (xmlXPathDebugObjCounterString >
-		xmlXPathDebugObjMaxString)
-		xmlXPathDebugObjMaxString =
-		    xmlXPathDebugObjCounterString;
-	    break;
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-	case XPATH_POINT:
-	    if (! isCached)
-		xmlXPathDebugObjTotalPoint++;
-	    xmlXPathDebugObjCounterPoint++;
-	    if (xmlXPathDebugObjCounterPoint >
-		xmlXPathDebugObjMaxPoint)
-		xmlXPathDebugObjMaxPoint =
-		    xmlXPathDebugObjCounterPoint;
-	    break;
-	case XPATH_RANGE:
-	    if (! isCached)
-		xmlXPathDebugObjTotalRange++;
-	    xmlXPathDebugObjCounterRange++;
-	    if (xmlXPathDebugObjCounterRange >
-		xmlXPathDebugObjMaxRange)
-		xmlXPathDebugObjMaxRange =
-		    xmlXPathDebugObjCounterRange;
-	    break;
-	case XPATH_LOCATIONSET:
-	    if (! isCached)
-		xmlXPathDebugObjTotalLocset++;
-	    xmlXPathDebugObjCounterLocset++;
-	    if (xmlXPathDebugObjCounterLocset >
-		xmlXPathDebugObjMaxLocset)
-		xmlXPathDebugObjMaxLocset =
-		    xmlXPathDebugObjCounterLocset;
-	    break;
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-	case XPATH_USERS:
-	    if (! isCached)
-		xmlXPathDebugObjTotalUsers++;
-	    xmlXPathDebugObjCounterUsers++;
-	    if (xmlXPathDebugObjCounterUsers >
-		xmlXPathDebugObjMaxUsers)
-		xmlXPathDebugObjMaxUsers =
-		    xmlXPathDebugObjCounterUsers;
-	    break;
-	case XPATH_XSLT_TREE:
-	    if (! isCached)
-		xmlXPathDebugObjTotalXSLTTree++;
-	    xmlXPathDebugObjCounterXSLTTree++;
-	    if (xmlXPathDebugObjCounterXSLTTree >
-		xmlXPathDebugObjMaxXSLTTree)
-		xmlXPathDebugObjMaxXSLTTree =
-		    xmlXPathDebugObjCounterXSLTTree;
-	    break;
-	default:
-	    break;
-    }
-    if (! isCached)
-	xmlXPathDebugObjTotalAll++;
-    xmlXPathDebugObjCounterAll++;
-    if (xmlXPathDebugObjCounterAll >
-	xmlXPathDebugObjMaxAll)
-	xmlXPathDebugObjMaxAll =
-	    xmlXPathDebugObjCounterAll;
-}
-
-static void
-xmlXPathDebugObjUsageReleased(xmlXPathContextPtr ctxt,
-			      xmlXPathObjectType objType)
-{
-    int isCached = 0;
-
-    if (ctxt != NULL) {
-	if (ctxt->cache != NULL) {
-	    xmlXPathContextCachePtr cache =
-		(xmlXPathContextCachePtr) ctxt->cache;
-
-	    isCached = 1;
-
-	    cache->dbgCachedAll++;
-	    switch (objType) {
-		case XPATH_UNDEFINED:
-		    cache->dbgCachedUndefined++;
-		    break;
-		case XPATH_NODESET:
-		    cache->dbgCachedNodeset++;
-		    break;
-		case XPATH_BOOLEAN:
-		    cache->dbgCachedBool++;
-		    break;
-		case XPATH_NUMBER:
-		    cache->dbgCachedNumber++;
-		    break;
-		case XPATH_STRING:
-		    cache->dbgCachedString++;
-		    break;
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-		case XPATH_POINT:
-		    cache->dbgCachedPoint++;
-		    break;
-		case XPATH_RANGE:
-		    cache->dbgCachedRange++;
-		    break;
-		case XPATH_LOCATIONSET:
-		    cache->dbgCachedLocset++;
-		    break;
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-		case XPATH_USERS:
-		    cache->dbgCachedUsers++;
-		    break;
-		case XPATH_XSLT_TREE:
-		    cache->dbgCachedXSLTTree++;
-		    break;
-		default:
-		    break;
-	    }
-
-	}
-    }
-    switch (objType) {
-	case XPATH_UNDEFINED:
-	    xmlXPathDebugObjCounterUndefined--;
-	    break;
-	case XPATH_NODESET:
-	    xmlXPathDebugObjCounterNodeset--;
-	    break;
-	case XPATH_BOOLEAN:
-	    xmlXPathDebugObjCounterBool--;
-	    break;
-	case XPATH_NUMBER:
-	    xmlXPathDebugObjCounterNumber--;
-	    break;
-	case XPATH_STRING:
-	    xmlXPathDebugObjCounterString--;
-	    break;
-#ifdef LIBXML_XPTR_LOCS_ENABLED
-	case XPATH_POINT:
-	    xmlXPathDebugObjCounterPoint--;
-	    break;
-	case XPATH_RANGE:
-	    xmlXPathDebugObjCounterRange--;
-	    break;
-	case XPATH_LOCATIONSET:
-	    xmlXPathDebugObjCounterLocset--;
-	    break;
-#endif /* LIBXML_XPTR_LOCS_ENABLED */
-	case XPATH_USERS:
-	    xmlXPathDebugObjCounterUsers--;
-	    break;
-	case XPATH_XSLT_TREE:
-	    xmlXPathDebugObjCounterXSLTTree--;
-	    break;
-	default:
-	    break;
-    }
-    xmlXPathDebugObjCounterAll--;
-}
-
-static void
-xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt)
-{
-    int reqAll, reqNodeset, reqString, reqBool, reqNumber,
-	reqXSLTTree, reqUndefined;
-    int caAll = 0, caNodeset = 0, caString = 0, caBool = 0,
-	caNumber = 0, caXSLTTree = 0, caUndefined = 0;
-    int reAll = 0, reNodeset = 0, reString = 0, reBool = 0,
-	reNumber = 0, reXSLTTree = 0, reUndefined = 0;
-    int leftObjs = xmlXPathDebugObjCounterAll;
-
-    reqAll = xmlXPathDebugObjTotalAll;
-    reqNodeset = xmlXPathDebugObjTotalNodeset;
-    reqString = xmlXPathDebugObjTotalString;
-    reqBool = xmlXPathDebugObjTotalBool;
-    reqNumber = xmlXPathDebugObjTotalNumber;
-    reqXSLTTree = xmlXPathDebugObjTotalXSLTTree;
-    reqUndefined = xmlXPathDebugObjTotalUndefined;
-
-    printf("# XPath object usage:\n");
-
-    if (ctxt != NULL) {
-	if (ctxt->cache != NULL) {
-	    xmlXPathContextCachePtr cache =
-		(xmlXPathContextCachePtr) ctxt->cache;
-
-	    reAll = cache->dbgReusedAll;
-	    reqAll += reAll;
-	    reNodeset = cache->dbgReusedNodeset;
-	    reqNodeset += reNodeset;
-	    reString = cache->dbgReusedString;
-	    reqString += reString;
-	    reBool = cache->dbgReusedBool;
-	    reqBool += reBool;
-	    reNumber = cache->dbgReusedNumber;
-	    reqNumber += reNumber;
-	    reXSLTTree = cache->dbgReusedXSLTTree;
-	    reqXSLTTree += reXSLTTree;
-	    reUndefined = cache->dbgReusedUndefined;
-	    reqUndefined += reUndefined;
-
-	    caAll = cache->dbgCachedAll;
-	    caBool = cache->dbgCachedBool;
-	    caNodeset = cache->dbgCachedNodeset;
-	    caString = cache->dbgCachedString;
-	    caNumber = cache->dbgCachedNumber;
-	    caXSLTTree = cache->dbgCachedXSLTTree;
-	    caUndefined = cache->dbgCachedUndefined;
-
-	    if (cache->nodesetObjs)
-		leftObjs -= cache->nodesetObjs->number;
-	    if (cache->stringObjs)
-		leftObjs -= cache->stringObjs->number;
-	    if (cache->booleanObjs)
-		leftObjs -= cache->booleanObjs->number;
-	    if (cache->numberObjs)
-		leftObjs -= cache->numberObjs->number;
-	    if (cache->miscObjs)
-		leftObjs -= cache->miscObjs->number;
-	}
-    }
-
-    printf("# all\n");
-    printf("#   total  : %d\n", reqAll);
-    printf("#   left  : %d\n", leftObjs);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalAll);
-    printf("#   reused : %d\n", reAll);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxAll);
-
-    printf("# node-sets\n");
-    printf("#   total  : %d\n", reqNodeset);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalNodeset);
-    printf("#   reused : %d\n", reNodeset);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxNodeset);
-
-    printf("# strings\n");
-    printf("#   total  : %d\n", reqString);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalString);
-    printf("#   reused : %d\n", reString);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxString);
-
-    printf("# booleans\n");
-    printf("#   total  : %d\n", reqBool);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalBool);
-    printf("#   reused : %d\n", reBool);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxBool);
-
-    printf("# numbers\n");
-    printf("#   total  : %d\n", reqNumber);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalNumber);
-    printf("#   reused : %d\n", reNumber);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxNumber);
-
-    printf("# XSLT result tree fragments\n");
-    printf("#   total  : %d\n", reqXSLTTree);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalXSLTTree);
-    printf("#   reused : %d\n", reXSLTTree);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxXSLTTree);
-
-    printf("# undefined\n");
-    printf("#   total  : %d\n", reqUndefined);
-    printf("#   created: %d\n", xmlXPathDebugObjTotalUndefined);
-    printf("#   reused : %d\n", reUndefined);
-    printf("#   max    : %d\n", xmlXPathDebugObjMaxUndefined);
-
-}
-
-#endif /* XP_DEBUG_OBJ_USAGE */
-
 #endif /* LIBXML_DEBUG_ENABLED */
 
 /************************************************************************
@@ -2250,9 +1729,6 @@
 	    xmlFree(obj->nodesetval);
 	}
 	xmlFree(obj);
-#ifdef XP_DEBUG_OBJ_USAGE
-	xmlXPathDebugObjCounterAll--;
-#endif
     }
     xmlPointerListFree(list);
 }
@@ -2358,9 +1834,6 @@
 		cache->miscObjs->items[--cache->miscObjs->number];
 	    ret->type = XPATH_NODESET;
 	    ret->nodesetval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
-#endif
 	    return(ret);
 	}
     }
@@ -2395,9 +1868,6 @@
 		cache->stringObjs->items[--cache->stringObjs->number];
 	    ret->type = XPATH_STRING;
 	    ret->stringval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
 	    return(ret);
 	} else if ((cache->miscObjs != NULL) &&
 	    (cache->miscObjs->number != 0))
@@ -2411,9 +1881,6 @@
 
 	    ret->type = XPATH_STRING;
 	    ret->stringval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
 	    return(ret);
 	}
     }
@@ -2459,9 +1926,6 @@
 		    ret->nodesetval->nodeNr = 1;
 		}
 	    }
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
-#endif
 	    return(ret);
 	} else if ((cache->miscObjs != NULL) &&
 	    (cache->miscObjs->number != 0))
@@ -2485,9 +1949,6 @@
 	    ret->type = XPATH_NODESET;
 	    ret->boolval = 0;
 	    ret->nodesetval = set;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
-#endif
 	    return(ret);
 	}
     }
@@ -2528,9 +1989,6 @@
 		cache->stringObjs->items[--cache->stringObjs->number];
 	    ret->type = XPATH_STRING;
             ret->stringval = copy;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
 	    return(ret);
 	} else if ((cache->miscObjs != NULL) &&
 	    (cache->miscObjs->number != 0))
@@ -2551,9 +2009,6 @@
 
 	    ret->type = XPATH_STRING;
             ret->stringval = copy;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
-#endif
 	    return(ret);
 	}
     }
@@ -2601,9 +2056,6 @@
 		cache->booleanObjs->items[--cache->booleanObjs->number];
 	    ret->type = XPATH_BOOLEAN;
 	    ret->boolval = (val != 0);
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN);
-#endif
 	    return(ret);
 	} else if ((cache->miscObjs != NULL) &&
 	    (cache->miscObjs->number != 0))
@@ -2615,9 +2067,6 @@
 
 	    ret->type = XPATH_BOOLEAN;
 	    ret->boolval = (val != 0);
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN);
-#endif
 	    return(ret);
 	}
     }
@@ -2649,9 +2098,6 @@
 		cache->numberObjs->items[--cache->numberObjs->number];
 	    ret->type = XPATH_NUMBER;
 	    ret->floatval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER);
-#endif
 	    return(ret);
 	} else if ((cache->miscObjs != NULL) &&
 	    (cache->miscObjs->number != 0))
@@ -2663,9 +2109,6 @@
 
 	    ret->type = XPATH_NUMBER;
 	    ret->floatval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-	    xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER);
-#endif
 	    return(ret);
 	}
     }
@@ -2693,9 +2136,6 @@
 
     switch (val->type) {
     case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
-#endif
 	break;
     case XPATH_NODESET:
     case XPATH_XSLT_TREE:
@@ -4062,11 +3502,6 @@
         if (cur->nodeTab[i] == val) break;
 
     if (i >= cur->nodeNr) {	/* not found */
-#ifdef DEBUG
-        xmlGenericError(xmlGenericErrorContext,
-	        "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
-		val->name);
-#endif
         return;
     }
     if ((cur->nodeTab[i] != NULL) &&
@@ -4216,47 +3651,6 @@
     xmlFree(obj);
 }
 
-#if defined(DEBUG) || defined(DEBUG_STEP)
-/**
- * xmlGenericErrorContextNodeSet:
- * @output:  a FILE * for the output
- * @obj:  the xmlNodeSetPtr to display
- *
- * Quick display of a NodeSet
- */
-void
-xmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) {
-    int i;
-
-    if (output == NULL) output = xmlGenericErrorContext;
-    if (obj == NULL)  {
-        fprintf(output, "NodeSet == NULL !\n");
-	return;
-    }
-    if (obj->nodeNr == 0) {
-        fprintf(output, "NodeSet is empty\n");
-	return;
-    }
-    if (obj->nodeTab == NULL) {
-	fprintf(output, " nodeTab == NULL !\n");
-	return;
-    }
-    for (i = 0; i < obj->nodeNr; i++) {
-        if (obj->nodeTab[i] == NULL) {
-	    fprintf(output, " NULL !\n");
-	    return;
-        }
-	if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) ||
-	    (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE))
-	    fprintf(output, " /");
-	else if (obj->nodeTab[i]->name == NULL)
-	    fprintf(output, " noname!");
-	else fprintf(output, " %s", obj->nodeTab[i]->name);
-    }
-    fprintf(output, "\n");
-}
-#endif
-
 /**
  * xmlXPathNewNodeSet:
  * @val:  the NodePtr value
@@ -4281,9 +3675,6 @@
     /* TODO: Check memory error. */
     ret->nodesetval = xmlXPathNodeSetCreate(val);
     /* @@ with_ns to check whether namespace nodes should be looked at @@ */
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET);
-#endif
     return(ret);
 }
 
@@ -4310,9 +3701,6 @@
     ret->boolval = 0;
     ret->user = (void *) val;
     ret->nodesetval = xmlXPathNodeSetCreate(val);
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_XSLT_TREE);
-#endif
     return(ret);
 }
 
@@ -4372,9 +3760,6 @@
     memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_NODESET;
     ret->nodesetval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET);
-#endif
     return(ret);
 }
 
@@ -4388,9 +3773,6 @@
 void
 xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
     if (obj == NULL) return;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageReleased(NULL, obj->type);
-#endif
     xmlFree(obj);
 }
 
@@ -5199,9 +4581,6 @@
     memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_NUMBER;
     ret->floatval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_NUMBER);
-#endif
     return(ret);
 }
 
@@ -5225,9 +4604,6 @@
     memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_BOOLEAN;
     ret->boolval = (val != 0);
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_BOOLEAN);
-#endif
     return(ret);
 }
 
@@ -5257,9 +4633,6 @@
         xmlFree(ret);
         return(NULL);
     }
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING);
-#endif
     return(ret);
 }
 
@@ -5286,9 +4659,6 @@
     memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_STRING;
     ret->stringval = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING);
-#endif
     return(ret);
 }
 
@@ -5338,9 +4708,6 @@
     memset(ret, 0 , sizeof(xmlXPathObject));
     ret->type = XPATH_USERS;
     ret->user = val;
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, XPATH_USERS);
-#endif
     return(ret);
 }
 
@@ -5365,9 +4732,6 @@
 	return(NULL);
     }
     memcpy(ret, val , sizeof(xmlXPathObject));
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageRequested(NULL, val->type);
-#endif
     switch (val->type) {
 	case XPATH_BOOLEAN:
 	case XPATH_NUMBER:
@@ -5475,9 +4839,6 @@
 	if (obj->stringval != NULL)
 	    xmlFree(obj->stringval);
     }
-#ifdef XP_DEBUG_OBJ_USAGE
-    xmlXPathDebugObjUsageReleased(NULL, obj->type);
-#endif
     xmlFree(obj);
 }
 
@@ -5576,11 +4937,6 @@
 	    goto free_obj;
 
 obj_cached:
-
-#ifdef XP_DEBUG_OBJ_USAGE
-	xmlXPathDebugObjUsageReleased(ctxt, obj->type);
-#endif
-
 	if (obj->nodesetval != NULL) {
 	    xmlNodeSetPtr tmpset = obj->nodesetval;
 
@@ -5621,9 +4977,6 @@
 	*/
 	if (obj->nodesetval != NULL)
 	    xmlXPathFreeNodeSet(obj->nodesetval);
-#ifdef XP_DEBUG_OBJ_USAGE
-	xmlXPathDebugObjUsageReleased(NULL, obj->type);
-#endif
 	xmlFree(obj);
     }
     return;
@@ -5740,9 +5093,6 @@
 	return(xmlStrdup((const xmlChar *) ""));
     switch (val->type) {
 	case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	    xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
-#endif
 	    ret = xmlStrdup((const xmlChar *) "");
 	    break;
         case XPATH_NODESET:
@@ -5789,9 +5139,6 @@
 
     switch (val->type) {
     case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
-#endif
 	break;
     case XPATH_NODESET:
     case XPATH_XSLT_TREE:
@@ -5909,9 +5256,6 @@
 	return(xmlXPathNAN);
     switch (val->type) {
     case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
-#endif
 	ret = xmlXPathNAN;
 	break;
     case XPATH_NODESET:
@@ -6023,9 +5367,6 @@
 	return(0);
     switch (val->type) {
     case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n");
-#endif
 	ret = 0;
 	break;
     case XPATH_NODESET:
@@ -6947,25 +6288,12 @@
      */
     switch (arg1->type) {
         case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Equal: undefined\n");
-#endif
 	    break;
         case XPATH_BOOLEAN:
 	    switch (arg2->type) {
 	        case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		    xmlGenericError(xmlGenericErrorContext,
-			    "Equal: undefined\n");
-#endif
 		    break;
 		case XPATH_BOOLEAN:
-#ifdef DEBUG_EXPR
-		    xmlGenericError(xmlGenericErrorContext,
-			    "Equal: %d boolean %d \n",
-			    arg1->boolval, arg2->boolval);
-#endif
 		    ret = (arg1->boolval == arg2->boolval);
 		    break;
 		case XPATH_NUMBER:
@@ -6995,10 +6323,6 @@
         case XPATH_NUMBER:
 	    switch (arg2->type) {
 	        case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		    xmlGenericError(xmlGenericErrorContext,
-			    "Equal: undefined\n");
-#endif
 		    break;
 		case XPATH_BOOLEAN:
 		    ret = (arg2->boolval==
@@ -7056,10 +6380,6 @@
         case XPATH_STRING:
 	    switch (arg2->type) {
 	        case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		    xmlGenericError(xmlGenericErrorContext,
-			    "Equal: undefined\n");
-#endif
 		    break;
 		case XPATH_BOOLEAN:
 		    if ((arg1->stringval == NULL) ||
@@ -7160,10 +6480,6 @@
     }
 
     if (arg1 == arg2) {
-#ifdef DEBUG_EXPR
-        xmlGenericError(xmlGenericErrorContext,
-		"Equal: by pointer\n");
-#endif
 	xmlXPathFreeObject(arg1);
         return(1);
     }
@@ -7183,10 +6499,6 @@
 	}
 	switch (arg2->type) {
 	    case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		xmlGenericError(xmlGenericErrorContext,
-			"Equal: undefined\n");
-#endif
 		break;
 	    case XPATH_NODESET:
 	    case XPATH_XSLT_TREE:
@@ -7247,10 +6559,6 @@
     }
 
     if (arg1 == arg2) {
-#ifdef DEBUG_EXPR
-        xmlGenericError(xmlGenericErrorContext,
-		"NotEqual: by pointer\n");
-#endif
 	xmlXPathReleaseObject(ctxt->context, arg1);
         return(0);
     }
@@ -7270,10 +6578,6 @@
 	}
 	switch (arg2->type) {
 	    case XPATH_UNDEFINED:
-#ifdef DEBUG_EXPR
-		xmlGenericError(xmlGenericErrorContext,
-			"NotEqual: undefined\n");
-#endif
 		break;
 	    case XPATH_NODESET:
 	    case XPATH_XSLT_TREE:
@@ -8465,10 +7769,6 @@
 	valuePush(ctxt,
 	    xmlXPathCacheNewFloat(ctxt->context,
 		(double) ctxt->context->contextSize));
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext,
-		"last() : %d\n", ctxt->context->contextSize);
-#endif
     } else {
 	XP_ERROR(XPATH_INVALID_CTXT_SIZE);
     }
@@ -8492,10 +7792,6 @@
 	valuePush(ctxt,
 	      xmlXPathCacheNewFloat(ctxt->context,
 		(double) ctxt->context->proximityPosition));
-#ifdef DEBUG_EXPR
-	xmlGenericError(xmlGenericErrorContext, "position() : %d\n",
-		ctxt->context->proximityPosition);
-#endif
     } else {
 	XP_ERROR(XPATH_INVALID_CTXT_POSITION);
     }
@@ -10340,14 +9636,6 @@
 	XP_ERROR(XPATH_EXPR_ERROR);
     }
     SKIP_BLANKS;
-#ifdef DEBUG_EXPR
-    if (prefix == NULL)
-	xmlGenericError(xmlGenericErrorContext, "Calling function %s\n",
-			name);
-    else
-	xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n",
-			prefix, name);
-#endif
 
     if (CUR != '(') {
 	xmlFree(name);
@@ -10564,10 +9852,6 @@
 	SKIP_BLANKS;
 	name = xmlXPathScanName(ctxt);
 	if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
-#ifdef DEBUG_STEP
-	    xmlGenericError(xmlGenericErrorContext,
-		    "PathExpr: Axis\n");
-#endif
 	    lc = 1;
 	    xmlFree(name);
 	} else if (name != NULL) {
@@ -10577,29 +9861,17 @@
 	    while (NXT(len) != 0) {
 		if (NXT(len) == '/') {
 		    /* element name */
-#ifdef DEBUG_STEP
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PathExpr: AbbrRelLocation\n");
-#endif
 		    lc = 1;
 		    break;
 		} else if (IS_BLANK_CH(NXT(len))) {
 		    /* ignore blanks */
 		    ;
 		} else if (NXT(len) == ':') {
-#ifdef DEBUG_STEP
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PathExpr: AbbrRelLocation\n");
-#endif
 		    lc = 1;
 		    break;
 		} else if ((NXT(len) == '(')) {
 		    /* Node Type or Function */
 		    if (xmlXPathIsNodeType(name)) {
-#ifdef DEBUG_STEP
-		        xmlGenericError(xmlGenericErrorContext,
-				"PathExpr: Type search\n");
-#endif
 			lc = 1;
 #ifdef LIBXML_XPTR_LOCS_ENABLED
                     } else if (ctxt->xptr &&
@@ -10607,19 +9879,11 @@
                         lc = 1;
 #endif
 		    } else {
-#ifdef DEBUG_STEP
-		        xmlGenericError(xmlGenericErrorContext,
-				"PathExpr: function call\n");
-#endif
 			lc = 0;
 		    }
                     break;
 		} else if ((NXT(len) == '[')) {
 		    /* element name */
-#ifdef DEBUG_STEP
-		    xmlGenericError(xmlGenericErrorContext,
-			    "PathExpr: AbbrRelLocation\n");
-#endif
 		    lc = 1;
 		    break;
 		} else if ((NXT(len) == '<') || (NXT(len) == '>') ||
@@ -10633,10 +9897,6 @@
 		len++;
 	    }
 	    if (NXT(len) == 0) {
-#ifdef DEBUG_STEP
-		xmlGenericError(xmlGenericErrorContext,
-			"PathExpr: AbbrRelLocation\n");
-#endif
 		/* element name */
 		lc = 1;
 	    }
@@ -11347,20 +10607,6 @@
 		xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR);
 	    }
 	}
-#ifdef DEBUG_STEP
-	xmlGenericError(xmlGenericErrorContext,
-		"Basis : computing new set\n");
-#endif
-
-#ifdef DEBUG_STEP
-	xmlGenericError(xmlGenericErrorContext, "Basis : ");
-	if (ctxt->value == NULL)
-	    xmlGenericError(xmlGenericErrorContext, "no value\n");
-	else if (ctxt->value->nodesetval == NULL)
-	    xmlGenericError(xmlGenericErrorContext, "Empty\n");
-	else
-	    xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval);
-#endif
 
 #ifdef LIBXML_XPTR_LOCS_ENABLED
 eval_predicates:
@@ -11384,16 +10630,6 @@
             xmlFree(name);
         }
     }
-#ifdef DEBUG_STEP
-    xmlGenericError(xmlGenericErrorContext, "Step : ");
-    if (ctxt->value == NULL)
-	xmlGenericError(xmlGenericErrorContext, "no value\n");
-    else if (ctxt->value->nodesetval == NULL)
-	xmlGenericError(xmlGenericErrorContext, "Empty\n");
-    else
-	xmlGenericErrorContextNodeSet(xmlGenericErrorContext,
-		ctxt->value->nodesetval);
-#endif
 }
 
 /**
@@ -11495,93 +10731,6 @@
 static int
 xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
 
-#ifdef DEBUG_STEP
-static void
-xmlXPathDebugDumpStepAxis(xmlXPathStepOpPtr op,
-			  int nbNodes)
-{
-    xmlGenericError(xmlGenericErrorContext, "new step : ");
-    switch (op->value) {
-        case AXIS_ANCESTOR:
-            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
-            break;
-        case AXIS_ANCESTOR_OR_SELF:
-            xmlGenericError(xmlGenericErrorContext,
-                            "axis 'ancestors-or-self' ");
-            break;
-        case AXIS_ATTRIBUTE:
-            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
-            break;
-        case AXIS_CHILD:
-            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
-            break;
-        case AXIS_DESCENDANT:
-            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
-            break;
-        case AXIS_DESCENDANT_OR_SELF:
-            xmlGenericError(xmlGenericErrorContext,
-                            "axis 'descendant-or-self' ");
-            break;
-        case AXIS_FOLLOWING:
-            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
-            break;
-        case AXIS_FOLLOWING_SIBLING:
-            xmlGenericError(xmlGenericErrorContext,
-                            "axis 'following-siblings' ");
-            break;
-        case AXIS_NAMESPACE:
-            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
-            break;
-        case AXIS_PARENT:
-            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
-            break;
-        case AXIS_PRECEDING:
-            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
-            break;
-        case AXIS_PRECEDING_SIBLING:
-            xmlGenericError(xmlGenericErrorContext,
-                            "axis 'preceding-sibling' ");
-            break;
-        case AXIS_SELF:
-            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
-            break;
-    }
-    xmlGenericError(xmlGenericErrorContext,
-	" context contains %d nodes\n", nbNodes);
-    switch (op->value2) {
-        case NODE_TEST_NONE:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for none !!!\n");
-            break;
-        case NODE_TEST_TYPE:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for type %d\n", op->value3);
-            break;
-        case NODE_TEST_PI:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for PI !!!\n");
-            break;
-        case NODE_TEST_ALL:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for *\n");
-            break;
-        case NODE_TEST_NS:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for namespace %s\n",
-                            op->value5);
-            break;
-        case NODE_TEST_NAME:
-            xmlGenericError(xmlGenericErrorContext,
-                            "           searching for name %s\n", op->value5);
-            if (op->value4)
-                xmlGenericError(xmlGenericErrorContext,
-                                "           with namespace %s\n", op->value4);
-            break;
-    }
-    xmlGenericError(xmlGenericErrorContext, "Testing : ");
-}
-#endif /* DEBUG_STEP */
-
 /**
  * xmlXPathNodeSetFilter:
  * @ctxt:  the XPath Parser context
@@ -11972,9 +11121,6 @@
     const xmlChar *name = op->value5;
     const xmlChar *URI = NULL;
 
-#ifdef DEBUG_STEP
-    int nbMatches = 0, prevMatches = 0;
-#endif
     int total = 0, hasNsNodes = 0;
     /* The popped object holding the context nodes */
     xmlXPathObjectPtr obj;
@@ -12099,11 +11245,6 @@
             break;
     }
 
-#ifdef DEBUG_STEP
-    xmlXPathDebugDumpStepAxis(op,
-	(obj->nodesetval != NULL) ? obj->nodesetval->nodeNr : 0);
-#endif
-
     if (next == NULL) {
 	xmlXPathReleaseObject(xpctxt, obj);
         return(0);
@@ -12237,10 +11378,6 @@
 
             total++;
 
-#ifdef DEBUG_STEP
-            xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
-#endif
-
 	    switch (test) {
                 case NODE_TEST_NONE:
 		    total = 0;
@@ -12427,11 +11564,6 @@
 	    outSeq = mergeAndClear(outSeq, seq);
 	break;
 
-#ifdef DEBUG_STEP
-	if (seq != NULL)
-	    nbMatches += seq->nodeNr;
-#endif
-
 apply_predicates: /* --------------------------------------------------- */
         if (ctxt->error != XPATH_EXPRESSION_OK)
 	    goto error;
@@ -12543,12 +11675,6 @@
         xpctxt->tmpNsList = NULL;
     }
 
-#ifdef DEBUG_STEP
-    xmlGenericError(xmlGenericErrorContext,
-	"\nExamined %d nodes, found %d nodes at that step\n",
-	total, nbMatches);
-#endif
-
     return(total);
 }
 
@@ -14246,10 +13372,6 @@
 
     if (comp != NULL) {
 	comp->expr = xmlStrdup(str);
-#ifdef DEBUG_EVAL_COUNTS
-	comp->string = xmlStrdup(str);
-	comp->nb = 0;
-#endif
     }
     return(comp);
 }
@@ -14306,13 +13428,6 @@
 	xmlXPathDisableOptimizer = 1;
 #endif
 
-#ifdef DEBUG_EVAL_COUNTS
-    comp->nb++;
-    if ((comp->string != NULL) && (comp->nb > 100)) {
-	fprintf(stderr, "100 x %s\n", comp->string);
-	comp->nb = 0;
-    }
-#endif
     pctxt = xmlXPathCompParserContext(comp, ctxt);
     if (pctxt == NULL)
         return(-1);
diff --git a/third_party/libxml/win32/include/libxml/xmlversion.h b/third_party/libxml/win32/include/libxml/xmlversion.h
index bf5a95bd..637909a 100644
--- a/third_party/libxml/win32/include/libxml/xmlversion.h
+++ b/third_party/libxml/win32/include/libxml/xmlversion.h
@@ -524,6 +524,18 @@
 #endif
 #endif /* __GNUC__ */
 
+/** DOC_DISABLE */
+#define XML_EMPTY
+
+#ifdef LIBXML_THREAD_ENABLED
+#define XML_DECLARE_GLOBAL(name, type, attrs) \
+  attrs XMLPUBFUN type* __##name(void);
+#define XML_GLOBAL_MACRO(name) (*__##name())
+#else
+#define XML_DECLARE_GLOBAL(name, type, attrs) attrs XMLPUBVAR type name;
+#endif
+/** DOC_ENABLE */
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/third_party/webrtc b/third_party/webrtc
index 29d4a01..7892f05 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 29d4a013bc90abdd78cffbe0a671d81a08010539
+Subproject commit 7892f05411d93fe9a2b876daccd817286ca43182
diff --git a/third_party/zstd/README.chromium b/third_party/zstd/README.chromium
index 7214bff7..52374aa 100644
--- a/third_party/zstd/README.chromium
+++ b/third_party/zstd/README.chromium
@@ -1,8 +1,8 @@
 Name: Zstandard
 Short Name: zstd
 URL: https://github.com/facebook/zstd
-Version: 25822342be59d831bad65426ae51f5cc22157b09
-License: BSD and GPLv2
+Version: cdceb0fce59785c841bf697e00067163106064e1
+License: BSD, GPLv2
 License File: src/LICENSE
 CPEPrefix: cpe:/a:facebook:zstandard:1.5.5
 Security Critical: yes
diff --git a/third_party/zstd/src b/third_party/zstd/src
index 2582234..cdceb0f 160000
--- a/third_party/zstd/src
+++ b/third_party/zstd/src
@@ -1 +1 @@
-Subproject commit 25822342be59d831bad65426ae51f5cc22157b09
+Subproject commit cdceb0fce59785c841bf697e00067163106064e1
diff --git a/tools/mac/power/export_dtrace.py b/tools/mac/power/export_dtrace.py
index 7e867c6a..7b2e688 100755
--- a/tools/mac/power/export_dtrace.py
+++ b/tools/mac/power/export_dtrace.py
@@ -139,8 +139,8 @@
 
       # If the next line is non-empty it's not the last in the stack.
       if next_line.strip():
-        # Matches lines like: "0x17e018987e"
-        if line_content.startswith("0x"):
+        # Matches lines like: "0x17e018987e" or "+0x17e018987e"
+        if line_content.startswith("0x") or line_content.startswith("+0x"):
           function = line_content
           module = "unsymbolized module"
         else:
diff --git a/tools/mac/power/export_dtrace_test.py b/tools/mac/power/export_dtrace_test.py
index a645da00..1b5f198 100644
--- a/tools/mac/power/export_dtrace_test.py
+++ b/tools/mac/power/export_dtrace_test.py
@@ -47,7 +47,7 @@
     self.assertEquals(collapser.GetSamplesListForTesting(), [{
         'frames': [
             ('unsymbolized module', '0x21'),
-            ('unsymbolized module', '0x85'),
+            ('unsymbolized module', '+0x85'),
             ('unsymbolized module', '0x37'),
         ],
         'weight':
diff --git a/tools/mac/power/test_data/absolute_offset/11_22.txt b/tools/mac/power/test_data/absolute_offset/11_22.txt
index 8867d74a0..d69cf2a 100644
--- a/tools/mac/power/test_data/absolute_offset/11_22.txt
+++ b/tools/mac/power/test_data/absolute_offset/11_22.txt
@@ -4,7 +4,7 @@
 
 
 0x21
-0x85
++0x85
 0x37
  12
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index cecaf66d..48079cc 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -44064,6 +44064,7 @@
   <int value="4668" label="OutOfFlowAlignSelfNoInsets"/>
   <int value="4669" label="OutOfFlowAlignSelfSingleInset"/>
   <int value="4670" label="OutOfFlowAlignSelfBothInsets"/>
+  <int value="4671" label="V8WebAssemblyJSStringBuiltins"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
diff --git a/tools/metrics/histograms/metadata/android/OWNERS b/tools/metrics/histograms/metadata/android/OWNERS
index b63d284..be1b875e 100644
--- a/tools/metrics/histograms/metadata/android/OWNERS
+++ b/tools/metrics/histograms/metadata/android/OWNERS
@@ -8,4 +8,5 @@
 ckitagawa@chromium.org
 mvanouwerkerk@chromium.org
 sinansahin@google.com
-jinsukkim@chromium.org
\ No newline at end of file
+jinsukkim@chromium.org
+altimin@chromium.org
\ No newline at end of file
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 840adaf..0f17b78 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -40,6 +40,19 @@
   <variant name=".Video" summary=""/>
 </variants>
 
+<variants name="AndroidFrameTimelineJankScenario">
+  <variant name=".FeedScrolling" summary=""/>
+  <variant name=".NewTabePage" summary=""/>
+  <variant name=".OmniboxFocus" summary=""/>
+  <variant name=".OpenLinkInNewTab" summary=""/>
+  <variant name=".StartSurfaceHomepage" summary=""/>
+  <variant name=".StartSurfaceTabSwitcher" summary=""/>
+  <variant name=".Startup" summary=""/>
+  <variant name=".TabSwitcher" summary=""/>
+  <variant name=".Total" summary=""/>
+  <variant name=".WebviewScrolling" summary=""/>
+</variants>
+
 <variants name="AndroidNavigationOrSuggestionPrefetch">
   <variant name="NavigationPrefetch"
       summary="Recorded for prefetches where Chrome is relatively confident
@@ -1584,7 +1597,30 @@
   <token key="ActivityType" variants="ActivityType"/>
 </histogram>
 
-<histogram name="Android.FrameTimelineJank.WebScroll.FrameJankStatus"
+<histogram name="Android.FrameTimelineJank.Duration{JankScenario}" units="ms"
+    expires_after="2024-04-30">
+  <owner>oksamyt@chromium.org</owner>
+  <owner>woa-performance@google.com</owner>
+  <summary>
+    Amount of time it takes to draw Android UI frames as measured by Android's
+    FrameMetrics API. Each frame's draw duration is stored individually.
+
+    The samples for this metric (along with
+    Android.FrameTimelineJank.JankyFrames) are manually passed from Java to C++
+    to be recorded. This is done instead of recording in real time from Java due
+    to the large number of generated samples (potentially ~60 per second).
+    Recording them directly from Java would result in a JNI call for each sample
+    which could cause performance issues.
+
+    FrameMetrics only reports frames with Android UI updates. An idle input
+    field would report only 2 frames per second due to the cursor blink
+    animation. Scrolling through a web page may record no frames if no Android
+    UI (like the address bar) updates.
+  </summary>
+  <token key="JankScenario" variants="AndroidFrameTimelineJankScenario"/>
+</histogram>
+
+<histogram name="Android.FrameTimelineJank.FrameJankStatus{JankScenario}"
     enum="FrameJankStatus" expires_after="2024-04-30">
   <owner>kartarsingh@chromium.org</owner>
   <owner>woa-performance@google.com</owner>
@@ -1605,6 +1641,7 @@
     was stationary would still be marked as scroll janks even when we wouldn't
     have been producing frames during that time.
   </summary>
+  <token key="JankScenario" variants="AndroidFrameTimelineJankScenario"/>
 </histogram>
 
 <histogram base="true"
@@ -1851,41 +1888,6 @@
   </summary>
 </histogram>
 
-<histogram name="Android.Jank.FrameDuration" units="ms"
-    expires_after="2024-04-30">
-  <owner>oksamyt@chromium.org</owner>
-  <owner>woa-performance@google.com</owner>
-  <summary>
-    Amount of time it takes to draw Android UI frames as measured by Android's
-    FrameMetrics API. Each frame's draw duration is stored individually.
-
-    The samples for this metric (along with Android.Jank.JankyFrames) are
-    manually passed from Java to C++ to be recorded. This is done instead of
-    recording in real time from Java due to the large number of generated
-    samples (potentially ~60 per second). Recording them directly from Java
-    would result in a JNI call for each sample which could cause performance
-    issues.
-
-    FrameMetrics only reports frames with Android UI updates. An idle input
-    field would report only 2 frames per second due to the cursor blink
-    animation. Scrolling through a web page may record no frames if no Android
-    UI (like the address bar) updates.
-  </summary>
-</histogram>
-
-<histogram name="Android.Jank.FrameJankStatus" enum="FrameJankStatus"
-    expires_after="2024-04-30">
-  <owner>oksamyt@chromium.org</owner>
-  <owner>woa-performance@google.com</owner>
-  <summary>
-    Jankiness of frames according to the Android's FrameMetrics API. Samples are
-    recorded into the Janky bucket for frames for which their total duration
-    exceeded the given deadline and into the NonJanky bucket for all other
-    frames. This metric is recorded at the same time as
-    Android.Jank.FrameDuration histogram.
-  </summary>
-</histogram>
-
 <histogram name="Android.KernelVersion" enum="AndroidKernelVersion"
     expires_after="2024-03-17">
   <owner>rsesek@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index a3c4f8cd..75a5d6a 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -404,6 +404,20 @@
   <token key="TabletOrClamshell" variants="DisplayModes"/>
 </histogram>
 
+<histogram name="Ash.AmbientMode.Init.{Settings}" enum="Boolean"
+    expires_after="2024-02-20">
+  <owner>esum@google.com</owner>
+  <owner>wutao@google.com</owner>
+  <summary>
+    Background initialization tasks must be completed successfully before the
+    ambient UI can be launched. For example, slide show mode must download an
+    initial set of photos from the server before the UI can be rendered. This
+    records the initialization success/failure count per ambient setting; each
+    ambient setting (slide show, video, etc) has a different initialization
+    process. This is emitted each time ash tries to launch the ambient UI.
+  </summary>
+</histogram>
+
 <histogram name="Ash.AmbientMode.LottieAnimationSmoothness.{Settings}"
     units="%" expires_after="2023-12-01">
   <owner>esum@google.com</owner>
@@ -7564,6 +7578,20 @@
   </summary>
 </histogram>
 
+<histogram name="Ash.Window.SnapTwoWindowsDuration" units="seconds"
+    expires_after="2024-01-14">
+  <owner>sophiewen@chromium.org</owner>
+  <owner>michelefan@chromium.org</owner>
+  <summary>
+    The time it takes to snap two windows, i.e. between a first window getting
+    snapped and a second window getting snapped on the other side. Starts
+    recording when one window gets snapped. Ends recording when another window
+    is snapped on the other side of the screen, or if the first window is no
+    longer snapped on the same side, records the maximum value of 50 hours
+    (18000 seconds).
+  </summary>
+</histogram>
+
 <histogram name="Ash.WindowCycleController.DesksSwitchDistance" units="units"
     expires_after="2024-07-27">
   <owner>afakhry@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml
index fbb3aff..976092e 100644
--- a/tools/metrics/histograms/metadata/content/histograms.xml
+++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -1879,6 +1879,7 @@
     <variant name="Feed" summary="the For-You Feed"/>
     <variant name="Feed.AllFeeds" summary="all Feeds combined"/>
     <variant name="Feed.SingleWebFeed" summary="the single web feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="the Web Feed"/>
   </token>
 </histogram>
@@ -1897,6 +1898,7 @@
     <variant name="Feed.AllFeeds"
         summary="either the For-You or Following/Web feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="the Following/Web Feed"/>
   </token>
 </histogram>
@@ -1913,6 +1915,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
   <token key="Action">
@@ -1953,6 +1956,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
@@ -2003,6 +2007,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
@@ -2019,6 +2024,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
@@ -2038,6 +2044,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
@@ -2053,6 +2060,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
@@ -2134,6 +2142,7 @@
   </summary>
   <token key="FeedType">
     <variant name="Feed.SingleWebFeed" summary="the single Single Web feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="the Web Feed"/>
   </token>
 </histogram>
@@ -2153,6 +2162,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
@@ -2169,6 +2179,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
@@ -2192,6 +2203,7 @@
   </summary>
   <token key="FeedType">
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="Supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
@@ -2209,6 +2221,7 @@
   <token key="FeedType">
     <variant name="Feed" summary="For-You Feed"/>
     <variant name="Feed.SingleWebFeed" summary="Single Web Feed"/>
+    <variant name="Feed.SupervisedFeed" summary="the supervised Feed"/>
     <variant name="Feed.WebFeed" summary="Web Feed"/>
   </token>
 </histogram>
diff --git a/tools/metrics/histograms/metadata/notifications/histograms.xml b/tools/metrics/histograms/metadata/notifications/histograms.xml
index 5aabe8c..42670ef5 100644
--- a/tools/metrics/histograms/metadata/notifications/histograms.xml
+++ b/tools/metrics/histograms/metadata/notifications/histograms.xml
@@ -779,16 +779,6 @@
   </summary>
 </histogram>
 
-<histogram name="Notifications.PersistentWebNotificationClickEventResult"
-    enum="ServiceWorkerStatusCode" expires_after="2022-05-01">
-  <owner>peter@chromium.org</owner>
-  <owner>knollr@chromium.org</owner>
-  <summary>
-    Recorded delivery status for persistent notification clicks to a Service
-    Worker when handling a click on a persistent WebNotification has finished.
-  </summary>
-</histogram>
-
 <histogram name="Notifications.PersistentWebNotificationClickResult"
     enum="PlatformNotificationStatus" expires_after="2023-04-23">
   <owner>peter@chromium.org</owner>
@@ -799,16 +789,6 @@
   </summary>
 </histogram>
 
-<histogram name="Notifications.PersistentWebNotificationCloseEventResult"
-    enum="ServiceWorkerStatusCode" expires_after="M98">
-  <owner>peter@chromium.org</owner>
-  <owner>knollr@chromium.org</owner>
-  <summary>
-    Records delivery status for persistent notification close events sent to a
-    Service Worker when the event has been handled.
-  </summary>
-</histogram>
-
 <histogram name="Notifications.PersistentWebNotificationCloseResult"
     enum="PlatformNotificationStatus" expires_after="2022-09-11">
   <owner>peter@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 183ebb7..6329173f 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -877,6 +877,21 @@
   <token key="Type" variants="InterestGroupRequestType"/>
 </histogram>
 
+<histogram
+    name="Ads.InterestGroup.NetHeaderResponse.HeaderDirectFromSellerSignals.ParseAndFindMatchTime"
+    units="ms" expires_after="2024-06-20">
+  <owner>caraitto@chromium.org</owner>
+  <owner>pauljensen@chromium.org</owner>
+  <owner>privacy-sandbox-dev@chromium.org</owner>
+  <summary>
+    Time required to find a matching directFromSignalsSignalsHeaderAdSlot,
+    reported upon completion of the search.
+
+    See https://github.com/WICG/turtledove/blob/main/FLEDGE.md for the latest
+    version of the FLEDGE explainer.
+  </summary>
+</histogram>
+
 <histogram name="Ads.InterestGroup.ReceivedDeprecatedBiddingSignalsFormat"
     enum="Boolean" expires_after="2024-06-20">
   <owner>mmenke@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index 081deb7b..3b2f1df 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -249,6 +249,16 @@
   </summary>
 </histogram>
 
+<histogram name="Settings.OverscrollHistoryNavigation.Enabled"
+    enum="BooleanEnabled" expires_after="2024-01-21">
+  <owner>charlesmeng@chromium.org</owner>
+  <owner>estalin@chromium.org</owner>
+  <summary>
+    Logs whether the overscroll history navigation setting is enabled or
+    disabled when it is toggled in chrome://settings/accessibility.
+  </summary>
+</histogram>
+
 <histogram name="Settings.PinUnlockSetup" enum="LockScreenProgress"
     expires_after="2024-02-25">
   <owner>anastasiian@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index f91a29c..2148aa8 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "full_remote_path": "perfetto-luci-artifacts/v37.0/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "51b8315725a4dd49e1ab7ded191fe4ca3bd326f1",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/d0a7b97ca3f762396fcbcb419a0dcd20aaf687f7/trace_processor_shell.exe"
+            "hash": "7ed930009091d9a0f408abe9967911e7ffbfdd1a",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/43ee4b90e33bcc0c9191d569b74e6f76585d314a/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "4ad0dc8eeae3ad92d6a1da2f1653a81fb9e3c4c1",
diff --git a/ui/base/interaction/element_identifier.h b/ui/base/interaction/element_identifier.h
index 7c14a9f..0837d84f 100644
--- a/ui/base/interaction/element_identifier.h
+++ b/ui/base/interaction/element_identifier.h
@@ -270,14 +270,13 @@
 #define DECLARE_EXPORTED_ELEMENT_IDENTIFIER_VALUE(ExportName, IdentifierName) \
   ExportName extern const ui::internal::ElementIdentifierImpl                 \
       IdentifierName##Provider;                                               \
-  ExportName constexpr ui::ElementIdentifier IdentifierName(                  \
-      &IdentifierName##Provider)
+  ExportName extern const ui::ElementIdentifier IdentifierName
 
 // Use this code in the .cc file to define a new identifier.
-#define DEFINE_ELEMENT_IDENTIFIER_VALUE(IdentifierName)                    \
-  constexpr ui::internal::ElementIdentifierImpl IdentifierName##Provider { \
-#IdentifierName                                                        \
-  }
+#define DEFINE_ELEMENT_IDENTIFIER_VALUE(IdentifierName)                   \
+  constexpr ui::internal::ElementIdentifierImpl IdentifierName##Provider{ \
+      #IdentifierName};                                                   \
+  constexpr ui::ElementIdentifier IdentifierName(&IdentifierName##Provider)
 
 // Declaring identifiers in a class:
 
diff --git a/ui/base/interaction/element_tracker.h b/ui/base/interaction/element_tracker.h
index 7949529d..99751fc7 100644
--- a/ui/base/interaction/element_tracker.h
+++ b/ui/base/interaction/element_tracker.h
@@ -307,6 +307,8 @@
 // defined below instead.
 #define DECLARE_CUSTOM_ELEMENT_EVENT_TYPE(EventName) \
   DECLARE_ELEMENT_IDENTIFIER_VALUE(EventName)
+#define DECLARE_EXPORTED_CUSTOM_ELEMENT_EVENT_TYPE(ExportName, EventName) \
+  DECLARE_EXPORTED_ELEMENT_IDENTIFIER_VALUE(ExportName, EventName)
 #define DEFINE_CUSTOM_ELEMENT_EVENT_TYPE(EventName) \
   DEFINE_ELEMENT_IDENTIFIER_VALUE(EventName)
 
diff --git a/ui/base/interaction/interactive_test.h b/ui/base/interaction/interactive_test.h
index d52be53..60de794 100644
--- a/ui/base/interaction/interactive_test.h
+++ b/ui/base/interaction/interactive_test.h
@@ -150,7 +150,7 @@
   // Calls `function` and applies `matcher` to the result. If the matcher does
   // not match, an appropriate error message is printed and the test fails.
   //
-  // `matcher` should resolve of convert to a `Matcher<R>`.
+  // `matcher` should resolve or convert to a `Matcher<R>`.
   template <typename C,
             typename M,
             typename R = internal::ReturnTypeOf<C>,
@@ -160,6 +160,21 @@
       M&& matcher,
       std::string check_description = internal::kNoCheckDescriptionSpecified);
 
+  // Checks the value of `variable` against `matcher`. The variable can be any
+  // local or class member that is guaranteed to still exist when the step is
+  // executed; if its value at the time the step is executed does not match,
+  // an appropriate error message is printed and the test fails.
+  //
+  // There is no need to wrap `variable` in e.g. `std::ref`; it is always
+  // captured by reference.
+  //
+  // `matcher` should resolve or convert to a `Matcher<T>`.
+  template <typename V, typename M, typename T = internal::MatcherTypeFor<V>>
+  [[nodiscard]] static StepBuilder CheckVariable(
+      V& variable,
+      M&& matcher,
+      std::string check_description = internal::kNoCheckDescriptionSpecified);
+
   // Checks that `check` returns true for element `element`. Will fail the test
   // sequence if `check` returns false - the callback should log any specific
   // error before returning.
@@ -943,6 +958,24 @@
 }
 
 // static
+template <typename V, typename M, typename T>
+InteractionSequence::StepBuilder InteractiveTestApi::CheckVariable(
+    V& variable,
+    M&& matcher,
+    std::string check_description) {
+  return std::move(
+      Check(base::BindOnce(
+                [](std::reference_wrapper<V> ref, testing::Matcher<T> matcher) {
+                  return internal::MatchAndExplain("CheckVariable()", matcher,
+                                                   ref.get());
+                },
+                std::ref(variable),
+                testing::Matcher<T>(std::forward<M>(matcher))))
+          .SetDescription(base::StringPrintf("CheckVariable(\"%s\")",
+                                             check_description.c_str())));
+}
+
+// static
 template <typename C, typename>
 InteractionSequence::StepBuilder InteractiveTestApi::CheckElement(
     ElementSpecifier element,
diff --git a/ui/base/interaction/interactive_test_unittest.cc b/ui/base/interaction/interactive_test_unittest.cc
index bd17fb2..8c48b2e6 100644
--- a/ui/base/interaction/interactive_test_unittest.cc
+++ b/ui/base/interaction/interactive_test_unittest.cc
@@ -427,6 +427,32 @@
   });
 }
 
+TEST_F(InteractiveTestTest, CheckVariable) {
+  int x = 0;
+  const int y = 0;
+  const char* text = "foo";
+  constexpr char kNewValue[] = "bar";
+
+  RunTestSequenceInContext(kTestContext1, CheckVariable(y, 0), Do([&]() {
+                             x = 1;
+                             text = kNewValue;
+                           }),
+                           CheckVariable(x, testing::Gt(0)),
+                           CheckVariable(text, kNewValue));
+}
+
+TEST_F(InteractiveTestTest, CheckVariableFails) {
+  int x = 0;
+
+  UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted);
+  private_test_impl().set_aborted_callback_for_testing(aborted.Get());
+
+  EXPECT_CALL_IN_SCOPE(aborted, Run, {
+    EXPECT_FALSE(RunTestSequenceInContext(kTestContext1, Do([&]() { x = 1; }),
+                                          CheckVariable(x, 0)));
+  });
+}
+
 TEST_F(InteractiveTestTest, CheckElement) {
   TestElement e1(kTestId1, kTestContext1);
   TestElement e2(kTestId2, kTestContext1);
diff --git a/ui/base/interaction/state_observer.h b/ui/base/interaction/state_observer.h
index 476c891..9143515 100644
--- a/ui/base/interaction/state_observer.h
+++ b/ui/base/interaction/state_observer.h
@@ -170,10 +170,11 @@
 
 #define DECLARE_STATE_IDENTIFIER_VALUE(ObserverType, Name) \
   DECLARE_ELEMENT_IDENTIFIER_VALUE(Name##Impl);            \
-  constexpr ui::test::StateIdentifier<ObserverType> Name(Name##Impl)
+  extern const ui::test::StateIdentifier<ObserverType> Name
 
-#define DEFINE_STATE_IDENTIFIER_VALUE(Name) \
-  DEFINE_ELEMENT_IDENTIFIER_VALUE(Name##Impl)
+#define DEFINE_STATE_IDENTIFIER_VALUE(ObserverType, Name) \
+  DEFINE_ELEMENT_IDENTIFIER_VALUE(Name##Impl);            \
+  constexpr ui::test::StateIdentifier<ObserverType> Name(Name##Impl)
 
 #define DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(ObserverType, Name) \
   DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(Name##Impl);            \
diff --git a/ui/base/test/scoped_fake_nswindow_focus.mm b/ui/base/test/scoped_fake_nswindow_focus.mm
index 0d634d5..f6ba5f1fa 100644
--- a/ui/base/test/scoped_fake_nswindow_focus.mm
+++ b/ui/base/test/scoped_fake_nswindow_focus.mm
@@ -29,6 +29,14 @@
 void ClearFocus() {
   NSWindow* window = g_fake_focused_window;
   g_fake_focused_window = nil;
+
+  // Some observers of these notifications (e.g. NSRemoteView) expect a
+  // non-nil window, and throw an exception otherwise. When the window's
+  // nil, just skip posting the notification.
+  if (window == nil) {
+    return;
+  }
+
   [[NSNotificationCenter defaultCenter]
       postNotificationName:NSWindowDidResignKeyNotification
                     object:window];
diff --git a/ui/events/ash/event_rewriter_ash.cc b/ui/events/ash/event_rewriter_ash.cc
index 919c473..d9f463d 100644
--- a/ui/events/ash/event_rewriter_ash.cc
+++ b/ui/events/ash/event_rewriter_ash.cc
@@ -26,6 +26,7 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/events/ash/keyboard_capability.h"
 #include "ui/events/ash/keyboard_device_id_event_rewriter.h"
+#include "ui/events/ash/mojom/extended_fkeys_modifier.mojom-shared.h"
 #include "ui/events/ash/mojom/modifier_key.mojom-shared.h"
 #include "ui/events/ash/mojom/simulate_right_click_modifier.mojom-shared.h"
 #include "ui/events/ash/mojom/six_pack_shortcut_modifier.mojom-shared.h"
@@ -838,6 +839,64 @@
   }
 }
 
+bool ExtendedFkeyModifiersMatch(
+    int flags,
+    ui::mojom::ExtendedFkeysModifier modifier_flag) {
+  switch (modifier_flag) {
+    case ui::mojom::ExtendedFkeysModifier::kDisabled:
+      return false;
+    case ui::mojom::ExtendedFkeysModifier::kAlt:
+      return (flags & EF_ALT_DOWN) == EF_ALT_DOWN;
+    case ui::mojom::ExtendedFkeysModifier::kShift:
+      return (flags & EF_SHIFT_DOWN) == EF_SHIFT_DOWN;
+    case ui::mojom::ExtendedFkeysModifier::kCtrlShift:
+      return (flags & (EF_SHIFT_DOWN | EF_CONTROL_DOWN)) ==
+             (EF_SHIFT_DOWN | EF_CONTROL_DOWN);
+  }
+}
+
+void RewriteExtendedFunctionKeys(EventRewriterAsh::Delegate* delegate,
+                                 const KeyEvent& event,
+                                 int device_id,
+                                 EventRewriterAsh::MutableKeyState* state) {
+  EventRewriterAsh::MutableKeyState incoming = *state;
+  static const KeyboardRemapping kExtendedFkeysRemappings[] = {
+      {// Shift+F1 -> F11.
+       {EF_SHIFT_DOWN, VKEY_F1},
+       {EF_NONE, DomCode::F11, DomKey::F11, VKEY_F11}},
+      {// Alt+F1 -> F11.
+       {EF_ALT_DOWN, VKEY_F1},
+       {EF_NONE, DomCode::F11, DomKey::F11, VKEY_F11}},
+      {// Ctrl+Shift+F1 -> F11.
+       {EF_SHIFT_DOWN | EF_CONTROL_DOWN, VKEY_F1},
+       {EF_NONE, DomCode::F11, DomKey::F11, VKEY_F11}},
+      {// Shift+F2 -> F11.
+       {EF_SHIFT_DOWN, VKEY_F2},
+       {EF_NONE, DomCode::F12, DomKey::F12, VKEY_F12}},
+      {// Alt+F2 -> F12.
+       {EF_ALT_DOWN, VKEY_F2},
+       {EF_NONE, DomCode::F12, DomKey::F12, VKEY_F12}},
+      {// Ctrl+Shift+F2 -> F12.
+       {EF_SHIFT_DOWN | EF_CONTROL_DOWN, VKEY_F2},
+       {EF_NONE, DomCode::F12, DomKey::F12, VKEY_F12}},
+  };
+
+  for (const auto& remapping : kExtendedFkeysRemappings) {
+    if (!MatchKeyboardRemapping(incoming, remapping.condition)) {
+      continue;
+    }
+    const auto shortcut =
+        delegate->GetExtendedFkeySetting(device_id, remapping.result.key_code);
+    if (!shortcut || !ExtendedFkeyModifiersMatch(remapping.condition.flags,
+                                                 shortcut.value())) {
+      continue;
+    }
+    state->flags = (incoming.flags & ~remapping.condition.flags);
+    ApplyRemapping(remapping.result, state);
+    return;
+  }
+}
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1494,6 +1553,11 @@
   if (!is_sticky_key_extension_command && !(key_event.flags() & EF_FINAL)) {
     RewriteExtendedKeys(key_event, &state);
     RewriteFunctionKeys(key_event, device_id, &state);
+    if (features::AreF11AndF12ShortcutsEnabled() &&
+        keyboard_capability_->IsChromeOSKeyboard(last_keyboard_device_id_)) {
+      RewriteExtendedFunctionKeys(delegate_, key_event,
+                                  last_keyboard_device_id_, &state);
+    }
   }
   if ((key_event.flags() == state.flags) &&
       (key_event.key_code() == state.key_code) &&
diff --git a/ui/events/ash/event_rewriter_ash.h b/ui/events/ash/event_rewriter_ash.h
index a80e1f8..a3db7ca8 100644
--- a/ui/events/ash/event_rewriter_ash.h
+++ b/ui/events/ash/event_rewriter_ash.h
@@ -15,6 +15,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "ui/events/ash/keyboard_capability.h"
+#include "ui/events/ash/mojom/extended_fkeys_modifier.mojom-shared.h"
 #include "ui/events/ash/mojom/modifier_key.mojom-shared.h"
 #include "ui/events/ash/mojom/simulate_right_click_modifier.mojom-shared.h"
 #include "ui/events/ash/mojom/six_pack_shortcut_modifier.mojom-shared.h"
@@ -187,6 +188,16 @@
         ui::mojom::SixPackShortcutModifier blocked_modifier,
         ui::mojom::SixPackShortcutModifier active_modifier,
         int device_id) = 0;
+
+    // Returns the modifier for rewriting key events to F11/F12 for ChromeOS
+    // keyboards with less than 12 top row keys. `key_code` must be either
+    // `ui::KeyboardCode::VKEY_F11` or `ui::KeyboardCode::VKEY_F12` and is used
+    // used to determine if the setting for F11 or F12 should be retrieved for
+    // the keyboard with the given `device_id`. The key event will not be
+    // rewritten if the return value is either absl::nullopt (settings for
+    // `device_id` weren't found) or if an invalid `key_code` was passed in.
+    virtual absl::optional<ui::mojom::ExtendedFkeysModifier>
+    GetExtendedFkeySetting(int device_id, ui::KeyboardCode key_code) = 0;
   };
 
   // Enum used to record the usage of the modifier keys on all devices. Do not
diff --git a/ui/events/ash/keyboard_capability.cc b/ui/events/ash/keyboard_capability.cc
index 1cce78e..b0402774 100644
--- a/ui/events/ash/keyboard_capability.cc
+++ b/ui/events/ash/keyboard_capability.cc
@@ -884,7 +884,7 @@
 bool KeyboardCapability::HasAssistantKey(const KeyboardDevice& keyboard) const {
   // Some external keyboards falsely claim to have assistant keys. However, this
   // can be trusted for internal + ChromeOS external keyboards.
-  return keyboard.has_assistant_key && IsChromeOSKeyboard(keyboard);
+  return keyboard.has_assistant_key && IsChromeOSKeyboard(keyboard.id);
 }
 
 bool KeyboardCapability::HasAssistantKeyOnAnyKeyboard() const {
@@ -898,7 +898,7 @@
 }
 
 bool KeyboardCapability::HasCapsLockKey(const KeyboardDevice& keyboard) const {
-  return !IsChromeOSKeyboard(keyboard) ||
+  return !IsChromeOSKeyboard(keyboard.id) ||
          kChromeOSKeyboardsWithCapsLock.contains(
              {keyboard.vendor_id, keyboard.product_id});
 }
@@ -1010,9 +1010,8 @@
   return false;
 }
 
-bool KeyboardCapability::IsChromeOSKeyboard(
-    const ui::KeyboardDevice& keyboard) const {
-  const auto device_type = GetDeviceType(keyboard);
+bool KeyboardCapability::IsChromeOSKeyboard(int device_id) const {
+  const auto device_type = GetDeviceType(device_id);
   return device_type == DeviceType::kDeviceInternalKeyboard ||
          device_type == DeviceType::kDeviceExternalChromeOsKeyboard;
 }
diff --git a/ui/events/ash/keyboard_capability.h b/ui/events/ash/keyboard_capability.h
index 7031f40..af93e51 100644
--- a/ui/events/ash/keyboard_capability.h
+++ b/ui/events/ash/keyboard_capability.h
@@ -339,6 +339,10 @@
   // Check if the CapsLock key exists on the given keyboard.
   bool HasCapsLockKey(const KeyboardDevice& keyboard) const;
 
+  // Finds the keyboard with the corresponding  `device_id` and checks its
+  // `DeviceType` to determine if it's a ChromeOS keyboard.
+  bool IsChromeOSKeyboard(int device_id) const;
+
   // Gets the corresponding function key for the given `action_key` on the
   // given `keyboard`.
   absl::optional<KeyboardCode> GetCorrespondingFunctionKey(
@@ -362,8 +366,6 @@
   const KeyboardInfo* GetKeyboardInfo(const KeyboardDevice& keyboard) const;
   void TrimKeyboardInfoMap();
 
-  bool IsChromeOSKeyboard(const ui::KeyboardDevice& keyboard) const;
-
   ScanCodeToEvdevKeyConverter scan_code_to_evdev_key_converter_;
 
   // Stores event device info objects so they do not need to be constructed
diff --git a/ui/events/ozone/OWNERS b/ui/events/ozone/OWNERS
index 482e8afb..b1e08aa 100644
--- a/ui/events/ozone/OWNERS
+++ b/ui/events/ozone/OWNERS
@@ -1,4 +1,3 @@
-rjkroege@chromium.org
 spang@chromium.org
 kpschoedel@chromium.org
 
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc
index 9594634..0061d398 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -606,6 +606,14 @@
   if (GetAnchorView() &&
       GetAnchorView()->GetProperty(kAnchoredDialogKey) == this)
     GetAnchorView()->ClearProperty(kAnchoredDialogKey);
+
+  if (base::FeatureList::IsEnabled(::features::kBubbleMetricsApi)) {
+    if (bubble_shown_time_.has_value()) {
+      bubble_shown_duration_ += base::TimeTicks::Now() - *bubble_shown_time_;
+      bubble_shown_time_.reset();
+    }
+    UmaHistogramLongTimes("Bubble.All.TimeVisible", bubble_shown_duration_);
+  }
 }
 
 void BubbleDialogDelegate::OnAnchorWidgetDestroying() {
@@ -970,18 +978,28 @@
 void BubbleDialogDelegate::OnBubbleWidgetVisibilityChanged(bool visible) {
   // Log time from bubble dialog delegate creation to bubble becoming
   // visible.
-  if (base::FeatureList::IsEnabled(::features::kBubbleMetricsApi) && visible &&
-      bubble_created_time_.has_value()) {
-    GetWidget()->GetCompositor()->RequestSuccessfulPresentationTimeForNextFrame(
-        base::BindOnce(
-            [](base::TimeTicks bubble_created_time,
-               base::TimeTicks presentation_timestamp) {
-              base::UmaHistogramMediumTimes(
-                  "Bubble.All.CreateToVisibleTime",
-                  presentation_timestamp - bubble_created_time);
-            },
-            *bubble_created_time_));
-    bubble_created_time_.reset();
+  if (base::FeatureList::IsEnabled(::features::kBubbleMetricsApi)) {
+    if (visible) {
+      if (bubble_created_time_.has_value()) {
+        GetWidget()
+            ->GetCompositor()
+            ->RequestSuccessfulPresentationTimeForNextFrame(base::BindOnce(
+                [](base::TimeTicks bubble_created_time,
+                   base::TimeTicks presentation_timestamp) {
+                  base::UmaHistogramMediumTimes(
+                      "Bubble.All.CreateToVisibleTime",
+                      presentation_timestamp - bubble_created_time);
+                },
+                *bubble_created_time_));
+        bubble_created_time_.reset();
+      }
+      bubble_shown_time_ = base::TimeTicks::Now();
+    } else {
+      if (bubble_shown_time_.has_value()) {
+        bubble_shown_duration_ += base::TimeTicks::Now() - *bubble_shown_time_;
+        bubble_shown_time_.reset();
+      }
+    }
   }
 
   UpdateHighlightedButton(visible);
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.h b/ui/views/bubble/bubble_dialog_delegate_view.h
index 5a6e1935..710f9bc 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.h
+++ b/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -459,6 +459,12 @@
   absl::optional<Button::ScopedAnchorHighlight> button_anchor_higlight_;
 
   absl::optional<base::TimeTicks> bubble_created_time_;
+
+  // Timestamp when the bubble turns visible.
+  absl::optional<base::TimeTicks> bubble_shown_time_;
+
+  // Cumulated time of bubble being visible.
+  base::TimeDelta bubble_shown_duration_;
 };
 
 // BubbleDialogDelegateView is a BubbleDialogDelegate that is also a View.
diff --git a/ui/views/cocoa/immersive_mode_controller_unittest.mm b/ui/views/cocoa/immersive_mode_controller_unittest.mm
index 47753258..8a6f1f9 100644
--- a/ui/views/cocoa/immersive_mode_controller_unittest.mm
+++ b/ui/views/cocoa/immersive_mode_controller_unittest.mm
@@ -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/remote_cocoa/app_shim/immersive_mode_controller.h"
+#include "components/remote_cocoa/app_shim/immersive_mode_controller_cocoa.h"
 
 #import <Cocoa/Cocoa.h>
 
@@ -11,7 +11,7 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "components/remote_cocoa/app_shim/bridged_content_view.h"
-#include "components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h"
+#include "components/remote_cocoa/app_shim/immersive_mode_tabbed_controller_cocoa.h"
 #include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #import "ui/base/cocoa/window_size_constants.h"
@@ -114,7 +114,7 @@
 TEST_F(CocoaImmersiveModeControllerTest, ImmersiveModeController) {
   // Controller under test.
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeController>(browser(), overlay());
+      std::make_unique<ImmersiveModeControllerCocoa>(browser(), overlay());
   immersive_mode_controller->Init();
   EXPECT_EQ(browser().titlebarAccessoryViewControllers.count, 1u);
 }
@@ -123,7 +123,7 @@
 TEST_F(CocoaImmersiveModeControllerTest, RevealLock) {
   // Controller under test.
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeController>(browser(), overlay());
+      std::make_unique<ImmersiveModeControllerCocoa>(browser(), overlay());
   immersive_mode_controller->Init();
 
   // Autohide top chrome.
@@ -181,8 +181,8 @@
   [fullscreen_window orderBack:nil];
 
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeController>(browser(), overlay());
-  base::WeakPtrFactory<ImmersiveModeController> weak_ptr_factory(
+      std::make_unique<ImmersiveModeControllerCocoa>(browser(), overlay());
+  base::WeakPtrFactory<ImmersiveModeControllerCocoa> weak_ptr_factory(
       immersive_mode_controller.get());
 
   // Grab the content view from the controller and add it to the test
@@ -259,8 +259,8 @@
   [fullscreen_window orderBack:nil];
 
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeController>(browser(), overlay());
-  base::WeakPtrFactory<ImmersiveModeController> weak_ptr_factory(
+      std::make_unique<ImmersiveModeControllerCocoa>(browser(), overlay());
+  base::WeakPtrFactory<ImmersiveModeControllerCocoa> weak_ptr_factory(
       immersive_mode_controller.get());
 
   NSTitlebarAccessoryViewController* titlebar_view_controller =
@@ -293,8 +293,8 @@
 TEST_F(CocoaImmersiveModeControllerTest, ToolbarVisibility) {
   // Controller under test.
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeTabbedController>(browser(), overlay(),
-                                                      tab_overlay());
+      std::make_unique<ImmersiveModeTabbedControllerCocoa>(browser(), overlay(),
+                                                           tab_overlay());
   immersive_mode_controller->Init();
 
   // NSWindowStyleMaskFullSizeContentView is set until the fullscreen transition
@@ -318,8 +318,8 @@
 TEST_F(CocoaImmersiveModeControllerTest, Tabbed) {
   // Controller under test.
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeTabbedController>(browser(), overlay(),
-                                                      tab_overlay());
+      std::make_unique<ImmersiveModeTabbedControllerCocoa>(browser(), overlay(),
+                                                           tab_overlay());
   immersive_mode_controller->Init();
 
   EXPECT_EQ(browser().titlebarAccessoryViewControllers.count, 2u);
@@ -332,8 +332,8 @@
 TEST_F(CocoaImmersiveModeControllerTest, TabbedRevealLock) {
   // Controller under test.
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeTabbedController>(browser(), overlay(),
-                                                      tab_overlay());
+      std::make_unique<ImmersiveModeTabbedControllerCocoa>(browser(), overlay(),
+                                                           tab_overlay());
   immersive_mode_controller->Init();
   immersive_mode_controller->FullscreenTransitionCompleted();
 
@@ -369,8 +369,8 @@
 TEST_F(CocoaImmersiveModeControllerTest, TabbedChildWindow) {
   // Controller under test.
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeTabbedController>(browser(), overlay(),
-                                                      tab_overlay());
+      std::make_unique<ImmersiveModeTabbedControllerCocoa>(browser(), overlay(),
+                                                           tab_overlay());
   immersive_mode_controller->Init();
   immersive_mode_controller->FullscreenTransitionCompleted();
 
@@ -396,8 +396,8 @@
 TEST_F(CocoaImmersiveModeControllerTest, TabbedChildWindowZOrder) {
   // Controller under test.
   auto immersive_mode_controller =
-      std::make_unique<ImmersiveModeTabbedController>(browser(), overlay(),
-                                                      tab_overlay());
+      std::make_unique<ImmersiveModeTabbedControllerCocoa>(browser(), overlay(),
+                                                           tab_overlay());
   immersive_mode_controller->Init();
   immersive_mode_controller->FullscreenTransitionCompleted();
 
@@ -414,21 +414,23 @@
   [popup close];
 }
 
-class MockImmersiveModeTabbedController : public ImmersiveModeTabbedController {
+class MockImmersiveModeTabbedControllerCocoa
+    : public ImmersiveModeTabbedControllerCocoa {
  public:
-  MockImmersiveModeTabbedController(NativeWidgetMacNSWindow* browser_window,
-                                    NativeWidgetMacNSWindow* overlay_window,
-                                    NativeWidgetMacNSWindow* tab_window)
-      : ImmersiveModeTabbedController(browser_window,
-                                      overlay_window,
-                                      tab_window) {}
+  MockImmersiveModeTabbedControllerCocoa(
+      NativeWidgetMacNSWindow* browser_window,
+      NativeWidgetMacNSWindow* overlay_window,
+      NativeWidgetMacNSWindow* tab_window)
+      : ImmersiveModeTabbedControllerCocoa(browser_window,
+                                           overlay_window,
+                                           tab_window) {}
   MOCK_METHOD(void, RevealLock, (), (override));
   MOCK_METHOD(void, RevealUnlock, (), (override));
 };
 
 TEST_F(CocoaImmersiveModeControllerTest, NoRevealUnlockDuringChildReordering) {
   // Controller under test.
-  testing::StrictMock<MockImmersiveModeTabbedController>
+  testing::StrictMock<MockImmersiveModeTabbedControllerCocoa>
       immersive_mode_controller(browser(), overlay(), tab_overlay());
   immersive_mode_controller.Init();
   immersive_mode_controller.FullscreenTransitionCompleted();
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
index 8b7fa02..ff5060b 100644
--- a/ui/views/cocoa/native_widget_mac_ns_window_host.mm
+++ b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
@@ -15,7 +15,6 @@
 #include "base/ranges/algorithm.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/time/time.h"
-#include "components/remote_cocoa/app_shim/immersive_mode_controller.h"
 #include "components/remote_cocoa/app_shim/immersive_mode_delegate_mac.h"
 #include "components/remote_cocoa/app_shim/mouse_capture.h"
 #include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
diff --git a/ui/views/interaction/widget_focus_observer.cc b/ui/views/interaction/widget_focus_observer.cc
index bf31c01f..079bf4e 100644
--- a/ui/views/interaction/widget_focus_observer.cc
+++ b/ui/views/interaction/widget_focus_observer.cc
@@ -16,6 +16,6 @@
   OnStateObserverStateChanged(focused_now);
 }
 
-DEFINE_STATE_IDENTIFIER_VALUE(kCurrentWidgetFocus);
+DEFINE_STATE_IDENTIFIER_VALUE(WidgetFocusObserver, kCurrentWidgetFocus);
 
 }  // namespace views::test
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm
index f426ee7..8415cbe 100644
--- a/ui/views/widget/native_widget_mac.mm
+++ b/ui/views/widget/native_widget_mac.mm
@@ -18,7 +18,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "components/crash/core/common/crash_key.h"
 #import "components/remote_cocoa/app_shim/bridged_content_view.h"
-#import "components/remote_cocoa/app_shim/immersive_mode_controller.h"
 #import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
 #import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
 #import "components/remote_cocoa/app_shim/views_nswindow_delegate.h"
diff --git a/ui/webui/resources/cr_components/omnibox/realbox_match.html b/ui/webui/resources/cr_components/omnibox/realbox_match.html
index e90df89..a071d4ac 100644
--- a/ui/webui/resources/cr_components/omnibox/realbox_match.html
+++ b/ui/webui/resources/cr_components/omnibox/realbox_match.html
@@ -23,8 +23,15 @@
   .container + .container {
     flex-direction: row;
     margin-inline-start: 40px; /* icon width + text padding */
-    padding-bottom: 12px;
     padding-top: 0;
+    padding-bottom: 12px;
+  }
+
+  .actions.inlined {
+    flex-grow: 1;
+    align-self: center;
+    padding-top: 0;
+    padding-bottom: 0;
   }
 
   #contents,
@@ -76,6 +83,10 @@
     white-space: nowrap;
   }
 
+  #text-container.simplified {
+    flex-grow: 0;
+  }
+
   :host([is-rich-suggestion]) #text-container {
     align-items: flex-start;
     flex-direction: column;
@@ -208,7 +219,7 @@
 <div class="container" aria-hidden="true">
   <div id="focus-indicator"></div>
   <cr-realbox-icon id="icon" match="[[match]]"></cr-realbox-icon>
-  <div id="text-container">
+  <div id="text-container" class$="[[simplifiedClass_]]">
     <span id="tail-suggest-prefix" hidden$="[[!tailSuggestPrefix_]]">
       <span id="prefix">[[tailSuggestPrefix_]]</span>
       <!-- This is equivalent to AutocompleteMatch::kEllipsis which is
@@ -219,6 +230,14 @@
     <span id="separator" class="dim">[[separatorText_]]</span>
     <span id="description" inner-h-t-m-l="[[descriptionHtml_]]"></span>
   </div>
+  <div class="actions container inlined" aria-hidden="true" hidden="[[!showActionsInlined_()]]">
+    <template is="dom-repeat" items="[[match.actions]]">
+      <cr-realbox-action id="action" action="[[item]]"
+        action-index="[[actionIndex_(item)]]"
+        on-execute-action="onExecuteAction_" tabindex="1">
+      </cr-realbox-action>
+    </template>
+  </div>
   <cr-icon-button id="remove" class="action-icon icon-clear"
     aria-label="[[removeButtonAriaLabel_]]"
     on-click="onRemoveButtonClick_" on-mousedown="onRemoveButtonMouseDown_"
@@ -226,7 +245,7 @@
     tabindex="2">
   </cr-icon-button>
 </div>
-<div class="container" aria-hidden="true" hidden="[[!match.actions.length]]">
+<div class="actions container underneath" aria-hidden="true" hidden="[[!showActionsUnderneath_(match)]]">
   <template is="dom-repeat" items="[[match.actions]]">
     <cr-realbox-action id="action" action="[[item]]"
       action-index="[[actionIndex_(item)]]"
diff --git a/ui/webui/resources/cr_components/omnibox/realbox_match.ts b/ui/webui/resources/cr_components/omnibox/realbox_match.ts
index c353d64..5fe059a 100644
--- a/ui/webui/resources/cr_components/omnibox/realbox_match.ts
+++ b/ui/webui/resources/cr_components/omnibox/realbox_match.ts
@@ -162,6 +162,17 @@
         type: String,
         computed: `computeTailSuggestPrefix_(match)`,
       },
+
+      /**
+         Conditional CSS class that enables styling of elements differently
+          according to feature state.
+       */
+      simplifiedClass_: {
+        type: Boolean,
+        value: () => loadTimeData.getBoolean('omniboxActionsUISimplification') ?
+            'simplified' :
+            '',
+      },
     };
   }
 
@@ -364,6 +375,17 @@
     return sideTypeToClass(this.sideType);
   }
 
+  private showActionsInlined_(): boolean {
+    // Always show inlined div when feature is enabled, so that it will
+    // grow and push other elements like remove button to the right.
+    return loadTimeData.getBoolean('omniboxActionsUISimplification');
+  }
+
+  private showActionsUnderneath_(match: AutocompleteMatch): boolean {
+    return match.actions.length > 0 &&
+        !loadTimeData.getBoolean('omniboxActionsUISimplification');
+  }
+
   /**
    * Decodes the AcMatchClassificationStyle enteries encoded in the given
    * ACMatchClassification style field, maps each entry to a CSS