diff --git a/DEPS b/DEPS
index 61beaec..c83cddc 100644
--- a/DEPS
+++ b/DEPS
@@ -269,7 +269,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e706ba895cc5bb9d2f7efe70c12d9553e2dc089f',
+  'skia_revision': 'd77f5acbcdea57af2f349ef69725d659a968d72a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -296,7 +296,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:8.20220505.2.1',
+  'fuchsia_version': 'version:8.20220506.0.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -340,7 +340,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '7979ffe0227feed94a5825d73851811d3501963f',
+  'catapult_revision': '778ecbcb2ae1bc13df4e34a82f96451a55c8a782',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -384,7 +384,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '7cbd8202e6715ee5d51314bd1e745a5243da82c1',
+  'dawn_revision': '4cb75245e3195247704d44a073fa88ffce4c1577',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -914,7 +914,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'BD7Jn9dUNGfL-fZrWigOxcOUjvTM0VYHEwPUf9Y0LOsC',
+          'version': '5LpwRnpUYpJRI7AwY-7-zUPDxVKRadX09h5M0UqHRgcC',
       },
     ],
     'condition': 'checkout_android',
@@ -1130,7 +1130,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b9dca865afd7b639bad61a124f888b7405a2cd55',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6a1494e5d76a4d03d4a0ba1847110df1a8d1c868',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1702,7 +1702,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'a912567d309f6bde49e7e0c3b0671a2e138ab96c',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '482e7ddc5c23e54a3b3c4f3143b262646b3037f8',
+    Var('webrtc_git') + '/src.git' + '@' + '7f969c0eff36cc454c54f446dc14856ecf5a8d8d',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1775,7 +1775,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2b3b14485a40211587b391b4c9954ce21497b004',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@4d311ec3c7c717f5e61f4ff43c612bf94bdf1452',
     'condition': 'checkout_src_internal',
   },
 
@@ -1783,7 +1783,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/assistant/ambient',
-        'version': 'version:background_color_name_change',
+        'version': 'version:feel_the_breeze_performance',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1827,7 +1827,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': '1cN_dthDQIAScbQiDS3eWAbmHFLERemUo_sB_koJ8ZsC',
+        'version': 'jqOOAabCIJ9bWjw9cJ36AaCiwJ6fOESnzH4CVHBi60wC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/ambient/resources/BUILD.gn b/ash/ambient/resources/BUILD.gn
index 4d31e8ec..32a40af 100644
--- a/ash/ambient/resources/BUILD.gn
+++ b/ash/ambient/resources/BUILD.gn
@@ -22,6 +22,7 @@
     "lottie/feel_the_breeze/clip_top.png",
     "lottie/feel_the_breeze/frame_image_1.png",
     "lottie/feel_the_breeze/frame_image_2.png",
+    "lottie/feel_the_breeze/string.png",
     "lottie/feel_the_breeze/tree_shadow.png",
     "lottie/float_on_by/animation.json",
     "lottie/float_on_by/shadow_a_1.png",
diff --git a/ash/ambient/resources/ambient_animation_resource_constants.h b/ash/ambient/resources/ambient_animation_resource_constants.h
index 355d7ad3..6a37950 100644
--- a/ash/ambient/resources/ambient_animation_resource_constants.h
+++ b/ash/ambient/resources/ambient_animation_resource_constants.h
@@ -19,11 +19,12 @@
 inline constexpr base::StringPiece kFrameImage1AssetId = "frame_image_1.png";
 inline constexpr base::StringPiece kFrameImage2AssetId = "frame_image_2.png";
 inline constexpr base::StringPiece kTreeShadowAssetId = "tree_shadow.png";
-inline constexpr int kFeelTheBreezeNumStaticAssets = 5;
+inline constexpr base::StringPiece kStringAssetId = "string.png";
+inline constexpr int kFeelTheBreezeNumStaticAssets = 6;
 inline constexpr std::array<base::StringPiece, kFeelTheBreezeNumStaticAssets>
-    kAllFeelTheBreezeStaticAssets = {kClipBottomAssetId, kClipTopAssetId,
+    kAllFeelTheBreezeStaticAssets = {kClipBottomAssetId,  kClipTopAssetId,
                                      kFrameImage1AssetId, kFrameImage2AssetId,
-                                     kTreeShadowAssetId};
+                                     kTreeShadowAssetId,  kStringAssetId};
 
 // Float on by.
 inline constexpr base::StringPiece kShadowA1AssetId = "shadow_a_1.png";
diff --git a/ash/ambient/resources/ambient_animation_static_resources_impl.cc b/ash/ambient/resources/ambient_animation_static_resources_impl.cc
index 524d20b3..cf9875b 100644
--- a/ash/ambient/resources/ambient_animation_static_resources_impl.cc
+++ b/ash/ambient/resources/ambient_animation_static_resources_impl.cc
@@ -55,6 +55,8 @@
                IDR_ASH_AMBIENT_LOTTIE_LOTTIE_FEEL_THE_BREEZE_FRAME_IMAGE_2_PNG},
               {ambient::resources::kTreeShadowAssetId,
                IDR_ASH_AMBIENT_LOTTIE_LOTTIE_FEEL_THE_BREEZE_TREE_SHADOW_PNG},
+              {ambient::resources::kStringAssetId,
+               IDR_ASH_AMBIENT_LOTTIE_LOTTIE_FEEL_THE_BREEZE_STRING_PNG},
               // End Assets
           }
           // End Theme: Feel the Breeze
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 8c802a3..757853b 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -1507,8 +1507,11 @@
       <message name="IDS_ASH_PHONE_HUB_NOTIFICATION_OPT_IN_SET_UP_BUTTON" desc="Label for the set up button to start the opt in flow to show notifications from the phone.">
         Set up
       </message>
+      <message name="IDS_ASH_PHONE_HUB_ALL_FEATURES_OPT_IN_DESCRIPTION" desc="Description for the notification and apps opt in view.">
+        View your phone's recent photos, media, notifications, and apps on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
+      </message>
       <message name="IDS_ASH_PHONE_HUB_NOTIFICATION_AND_APPS_OPT_IN_DESCRIPTION" desc="Description for the notification and apps opt in view.">
-        View your phone's recent photos, media, notifications, and messaging apps on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
+        View your phone's notifications and apps on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
       </message>
       <message name="IDS_ASH_PHONE_HUB_NOTIFICATION_OPT_IN_DESCRIPTION" desc="Description for the notification opt in view.">
         View your phone's notifications on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
@@ -1516,8 +1519,11 @@
       <message name="IDS_ASH_PHONE_HUB_NOTIFICATION_AND_CAMERA_ROLL_OPT_IN_DESCRIPTION" desc="Description for the notification opt in view.">
         View your phone's recent photos, media, and notifications on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
       </message>
+      <message name="IDS_ASH_PHONE_HUB_CAMERA_ROLL_AND_APPS_OPT_IN_DESCRIPTION" desc="Description for the notification opt in view.">
+        View your phone's recent photos, media, and apps on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
+      </message>
       <message name="IDS_ASH_PHONE_HUB_APPS_OPT_IN_DESCRIPTION" desc="Description for the apps opt in view.">
-        Access your phone's messaging apps on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
+        View your phone's apps on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
       </message>
       <message name="IDS_ASH_PHONE_HUB_CAMERA_ROLL_OPT_IN_DESCRIPTION" desc="Description for the camera roll opt in view.">
         View your phone's recent photos and media on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
diff --git a/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_ALL_FEATURES_OPT_IN_DESCRIPTION.png.sha1 b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_ALL_FEATURES_OPT_IN_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..6255f8fb
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_ALL_FEATURES_OPT_IN_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+3faea8751f732bae64cc2e8e1bec810beb09e10d
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_APPS_OPT_IN_DESCRIPTION.png.sha1 b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_APPS_OPT_IN_DESCRIPTION.png.sha1
index 1acaa60..d6f3ccbc 100644
--- a/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_APPS_OPT_IN_DESCRIPTION.png.sha1
+++ b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_APPS_OPT_IN_DESCRIPTION.png.sha1
@@ -1 +1 @@
-17b991295887ea1bae6a8ed93a5fed80c8a21bc8
\ No newline at end of file
+6246a0463b5d98a513c3ca85987e433ca02d6c99
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_CAMERA_ROLL_AND_APPS_OPT_IN_DESCRIPTION.png.sha1 b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_CAMERA_ROLL_AND_APPS_OPT_IN_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..1e40bd5
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_CAMERA_ROLL_AND_APPS_OPT_IN_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+abf16f6771695877e2cddc1a6cd1aff5328d7603
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_NOTIFICATION_AND_APPS_OPT_IN_DESCRIPTION.png.sha1 b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_NOTIFICATION_AND_APPS_OPT_IN_DESCRIPTION.png.sha1
index 3b91d73..958c924 100644
--- a/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_NOTIFICATION_AND_APPS_OPT_IN_DESCRIPTION.png.sha1
+++ b/ash/ash_strings_grd/IDS_ASH_PHONE_HUB_NOTIFICATION_AND_APPS_OPT_IN_DESCRIPTION.png.sha1
@@ -1 +1 @@
-168f262c0f1fdcb5820308bbebcdfdd794ff9b2e
\ No newline at end of file
+a040b64cd786c8fffcaf955b303575469fbd2163
\ No newline at end of file
diff --git a/ash/components/arc/input_overlay/resources/com.blackpanther.ninjaarashi.json b/ash/components/arc/input_overlay/resources/com.blackpanther.ninjaarashi.json
new file mode 100644
index 0000000..2ac6b622
--- /dev/null
+++ b/ash/components/arc/input_overlay/resources/com.blackpanther.ninjaarashi.json
@@ -0,0 +1,180 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+{
+  "tap": [
+    {
+      "id": 0,
+      "input_sources": [
+        "keyboard"
+      ],
+      "name": "left",
+      "key": "KeyA",
+      "location": [
+        {
+          "type": "dependent_position",
+          "anchor": [
+            0,
+            1
+          ],
+          "anchor_to_target": [
+            0.0963409,
+            -0.13591433
+          ],
+          "x_on_y": 1.260606
+        }
+      ],
+      "radius": 0.0675453
+    },
+    {
+      "id": 1,
+      "input_sources": [
+        "keyboard"
+      ],
+      "name": "right",
+      "key": "KeyD",
+      "location": [
+        {
+          "type": "dependent_position",
+          "anchor": [
+            0,
+            1
+          ],
+          "anchor_to_target": [
+            0.24641037,
+            -0.13591433
+          ],
+          "x_on_y": 3.2242424
+        }
+      ],
+      "radius": 0.0675453
+    },
+    {
+      "id": 2,
+      "input_sources": [
+        "keyboard"
+      ],
+      "name": "jump",
+      "key": "Space",
+      "location": [
+        {
+          "type": "dependent_position",
+          "anchor": [
+            1,
+            1
+          ],
+          "anchor_to_target": [
+            -0.093561836,
+            -0.16556837
+          ],
+          "x_on_y": 1.0049751
+        }
+      ],
+      "radius": 0.09060956
+    },
+    {
+      "id": 3,
+      "input_sources": [
+        "keyboard"
+      ],
+      "name": "attack",
+      "key": "KeyO",
+      "location": [
+        {
+          "type": "dependent_position",
+          "anchor": [
+            1,
+            1
+          ],
+          "anchor_to_target": [
+            -0.077350624,
+            -0.39621088
+          ],
+          "x_on_y": 0.34719336
+        }
+      ],
+      "radius": 0.06425041
+    },
+    {
+      "id": 4,
+      "input_sources": [
+        "keyboard"
+      ],
+      "name": "disguise",
+      "key": "KeyI",
+      "location": [
+        {
+          "type": "dependent_position",
+          "anchor": [
+            1,
+            1
+          ],
+          "anchor_to_target": [
+            -0.18156554,
+            -0.32042834
+          ],
+          "x_on_y": 1.0077121
+        }
+      ],
+      "radius": 0.06342669
+    },
+    {
+      "id": 5,
+      "input_sources": [
+        "keyboard"
+      ],
+      "name": "dash",
+      "key": "KeyU",
+      "location": [
+        {
+          "type": "dependent_position",
+          "anchor": [
+            1,
+            1
+          ],
+          "anchor_to_target": [
+            -0.22278833,
+            -0.13756178
+          ],
+          "x_on_y": 2.8802395
+        }
+      ],
+      "radius": 0.06342669
+    },
+    {
+      "id": 6,
+      "input_sources": [
+        "keyboard"
+      ],
+      "name": "Pause",
+      "key": "Backspace",
+      "location": [
+        {
+          "type": "dependent_position",
+          "anchor": [
+            1,
+            0
+          ],
+          "anchor_to_target": [
+            -0.036127836,
+            0.06425041
+          ],
+          "x_on_y": 1.0
+        },
+        {
+          "type": "position",
+          "anchor": [
+            1,
+            0
+          ],
+          "anchor_to_target": [
+            -0.49982375,
+            0.30957097
+          ]
+        }
+      ],
+      "radius": 0.050247118
+    }
+  ]
+}
diff --git a/ash/components/arc/input_overlay/resources/com.blackpanther.ninjaarashi2.json b/ash/components/arc/input_overlay/resources/com.blackpanther.ninjaarashi2.json
index dd51d00..7913ee8 100644
--- a/ash/components/arc/input_overlay/resources/com.blackpanther.ninjaarashi2.json
+++ b/ash/components/arc/input_overlay/resources/com.blackpanther.ninjaarashi2.json
@@ -20,12 +20,12 @@
           ],
           "anchor_to_target": [
             0.09375,
-            -0.1481481481
+            -0.14814815
           ],
           "x_on_y": 1.125
         }
       ],
-      "radius": 0.095
+      "radius": 0.08981481
     },
     {
       "id": 1,
@@ -42,16 +42,19 @@
             1
           ],
           "anchor_to_target": [
-            0.2317708333,
-            -0.1481481481
+            0.23177083,
+            -0.14814815
           ],
-          "x_on_y": 2.7812
+          "x_on_y": 2.78125
         }
       ],
-      "radius": 0.095
+      "radius": 0.08472222
     },
     {
       "id": 2,
+      "input_sources": [
+        "keyboard"
+      ],
       "name": "jump",
       "key": "Space",
       "location": [
@@ -62,13 +65,13 @@
             1
           ],
           "anchor_to_target": [
-            -0.08802083333,
-            -0.1759259259
+            -0.09086673,
+            -0.17466561
           ],
-          "x_on_y": 0.8894736842
+          "x_on_y": 0.8783784
         }
       ],
-      "radius": 0.1
+      "radius": 0.100462966
     },
     {
       "id": 3,
@@ -86,12 +89,12 @@
           ],
           "anchor_to_target": [
             -0.059375,
-            -0.4055555556
+            -0.40555555
           ],
-          "x_on_y": 0.2602739726
+          "x_on_y": 0.26027396
         }
       ],
-      "radius": 0.06574
+      "radius": 0.06574074
     },
     {
       "id": 4,
@@ -108,13 +111,13 @@
             1
           ],
           "anchor_to_target": [
-            -0.1848958333,
-            -0.3481481481
+            -0.18489583,
+            -0.34814814
           ],
-          "x_on_y": 0.9441489362
+          "x_on_y": 0.94414896
         }
       ],
-      "radius": 0.05833
+      "radius": 0.058333334
     },
     {
       "id": 5,
@@ -132,12 +135,12 @@
           ],
           "anchor_to_target": [
             -0.2234375,
-            -0.1425925926
+            -0.1425926
           ],
-          "x_on_y": 2.785714286
+          "x_on_y": 2.7857144
         }
       ],
-      "radius": 0.07
+      "radius": 0.06574074
     },
     {
       "id": 6,
@@ -154,20 +157,24 @@
             0
           ],
           "anchor_to_target": [
-            -0.05208333333,
-            0.06481481481
+            -0.052083332,
+            0.06481481
           ],
-          "x_on_y": 1.428571429
+          "x_on_y": 1.4285715
         },
         {
           "type": "position",
+          "anchor": [
+            0,
+            0
+          ],
           "anchor_to_target": [
             0.5,
-            0.2462962963
+            0.2462963
           ]
         }
       ],
-      "radius": 0.04398
+      "radius": 0.04398148
     }
   ]
 }
diff --git a/ash/components/arc/input_overlay/resources/input_overlay_resources.grd b/ash/components/arc/input_overlay/resources/input_overlay_resources.grd
index 1616bea4..643270d 100644
--- a/ash/components/arc/input_overlay/resources/input_overlay_resources.grd
+++ b/ash/components/arc/input_overlay/resources/input_overlay_resources.grd
@@ -21,6 +21,7 @@
        <include name="IDR_IO_COM_ANDROBABY_GAME2048" file="com.androbaby.game2048.json" type="BINDATA" />
        <include name="IDR_IO_CO_IMBA_ARCHERO" file="co.imba.archero.json" type="BINDATA" />
        <include name="IDR_IO_COM_DATAVISIONSTUDIO_ROGUELIKE" file="com.datavisionstudio.roguelike.json" type="BINDATA" />
+       <include name="IDR_IO_COM_BLACKPANTHER_NINJAARASHI" file="com.blackpanther.ninjaarashi.json" type="BINDATA" />
     </includes>
   </release>
 </grit>
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index d33ae1d..b6faef8 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -1137,7 +1137,7 @@
 // from the apps grid. This feature was previously named "AppListBubble".
 // https://crbug.com/1204551
 const base::Feature kProductivityLauncher{"ProductivityLauncher",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Controls whether to enable Projector.
 const base::Feature kProjector{"Projector", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ash/public/cpp/login_accelerators.cc b/ash/public/cpp/login_accelerators.cc
index 91e2126..38a555b 100644
--- a/ash/public/cpp/login_accelerators.cc
+++ b/ash/public/cpp/login_accelerators.cc
@@ -12,7 +12,6 @@
 // These strings must be kept in sync with handleAccelerator()
 // in display_manager.js.
 const char kAccelNameCancel[] = "cancel";
-const char kAccelNameVersion[] = "version";
 const char kAccelNameReset[] = "reset";
 
 }  // namespace
@@ -83,14 +82,13 @@
 
 std::string MapToWebUIAccelerator(LoginAcceleratorAction action) {
   switch (action) {
-    case LoginAcceleratorAction::kToggleSystemInfo:
-      return kAccelNameVersion;
     case LoginAcceleratorAction::kShowResetScreen:
       return kAccelNameReset;
     case LoginAcceleratorAction::kCancelScreenAction:
       return kAccelNameCancel;
     case LoginAcceleratorAction::kAppLaunchBailout:
     case LoginAcceleratorAction::kAppLaunchNetworkConfig:
+    case LoginAcceleratorAction::kToggleSystemInfo:
     case LoginAcceleratorAction::kShowFeedback:
     case LoginAcceleratorAction::kStartEnrollment:
     case LoginAcceleratorAction::kStartKioskEnrollment:
diff --git a/ash/system/phonehub/multidevice_feature_opt_in_view.cc b/ash/system/phonehub/multidevice_feature_opt_in_view.cc
index cf0808d..27bf6cd 100644
--- a/ash/system/phonehub/multidevice_feature_opt_in_view.cc
+++ b/ash/system/phonehub/multidevice_feature_opt_in_view.cc
@@ -103,9 +103,11 @@
     case PermissionsOnboardingSetUpMode::kNotification:
       return IDS_ASH_PHONE_HUB_NOTIFICATION_OPT_IN_DESCRIPTION;
     case PermissionsOnboardingSetUpMode::kNotificationAndMessagingApps:
-    case PermissionsOnboardingSetUpMode::kMessagingAppsAndCameraRoll:
-    case PermissionsOnboardingSetUpMode::kAllPermissions:
       return IDS_ASH_PHONE_HUB_NOTIFICATION_AND_APPS_OPT_IN_DESCRIPTION;
+    case PermissionsOnboardingSetUpMode::kMessagingAppsAndCameraRoll:
+      return IDS_ASH_PHONE_HUB_CAMERA_ROLL_AND_APPS_OPT_IN_DESCRIPTION;
+    case PermissionsOnboardingSetUpMode::kAllPermissions:
+      return IDS_ASH_PHONE_HUB_ALL_FEATURES_OPT_IN_DESCRIPTION;
     case PermissionsOnboardingSetUpMode::kNone:
     default:
       // Just return the default strings since the MultideviceFeatureOptInView
diff --git a/ash/webui/camera_app_ui/resources.h b/ash/webui/camera_app_ui/resources.h
index 2d895fc..e3ed0c7c 100644
--- a/ash/webui/camera_app_ui/resources.h
+++ b/ash/webui/camera_app_ui/resources.h
@@ -23,6 +23,8 @@
     {"aria_grid_off", IDS_ARIA_GRID_OFF},
     {"aria_mirror_off", IDS_ARIA_MIRROR_OFF},
     {"aria_mirror_on", IDS_ARIA_MIRROR_ON},
+    {"aria_mute_off", IDS_ARIA_MUTE_OFF},
+    {"aria_mute_on", IDS_ARIA_MUTE_ON},
     {"aria_record_type_group", IDS_ARIA_RECORD_TYPE_GROUP},
     {"aria_scan_type_group", IDS_ARIA_SCAN_TYPE_GROUP},
     {"aria_timer_10s", IDS_ARIA_TIMER_10S},
diff --git a/ash/webui/camera_app_ui/resources/js/i18n_string.ts b/ash/webui/camera_app_ui/resources/js/i18n_string.ts
index 06a05ed..45f2a96 100644
--- a/ash/webui/camera_app_ui/resources/js/i18n_string.ts
+++ b/ash/webui/camera_app_ui/resources/js/i18n_string.ts
@@ -14,6 +14,8 @@
   ARIA_GRID_OFF = 'aria_grid_off',
   ARIA_MIRROR_OFF = 'aria_mirror_off',
   ARIA_MIRROR_ON = 'aria_mirror_on',
+  ARIA_MUTE_OFF = 'aria_mute_off',
+  ARIA_MUTE_ON = 'aria_mute_on',
   ARIA_RECORD_TYPE_GROUP = 'aria_record_type_group',
   ARIA_SCAN_TYPE_GROUP = 'aria_scan_type_group',
   ARIA_TIMER_10S = 'aria_timer_10s',
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera/options.ts b/ash/webui/camera_app_ui/resources/js/views/camera/options.ts
index ece0e6e5..a094dc9 100644
--- a/ash/webui/camera_app_ui/resources/js/views/camera/options.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/camera/options.ts
@@ -89,6 +89,13 @@
     state.addObserver(state.State.TAKING, () => {
       this.updateOptionAvailability();
     });
+
+    util.bindElementAriaLabelWithState({
+      element: this.toggleMic,
+      state: state.State.MIC,
+      onLabel: I18nString.ARIA_MUTE_OFF,
+      offLabel: I18nString.ARIA_MUTE_ON,
+    });
   }
 
   private setAriaLabelForOptionButton(
diff --git a/ash/webui/camera_app_ui/resources/js/views/option_panel.ts b/ash/webui/camera_app_ui/resources/js/views/option_panel.ts
index 476910cb..a8cf622 100644
--- a/ash/webui/camera_app_ui/resources/js/views/option_panel.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/option_panel.ts
@@ -5,6 +5,7 @@
 import {assertInstanceof} from '../assert.js';
 import * as dom from '../dom.js';
 import * as nav from '../nav.js';
+import {speak} from '../spoken_msg.js';
 import * as state from '../state.js';
 import {ViewName} from '../type.js';
 import * as util from '../util.js';
@@ -55,6 +56,7 @@
         if (input.checked) {
           triggerButton.setAttribute('i18n-aria', ariaLabel);
           util.setupI18nElements(triggerButton);
+          speak(ariaLabel);
 
           onStateChanged(isDisableOption ? null : targetState);
         }
diff --git a/ash/webui/camera_app_ui/resources/js/views/review.ts b/ash/webui/camera_app_ui/resources/js/views/review.ts
index 9368b24d..78825a5 100644
--- a/ash/webui/camera_app_ui/resources/js/views/review.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/review.ts
@@ -91,7 +91,7 @@
    * Constructs the review view.
    */
   constructor(private readonly viewName: ViewName = ViewName.REVIEW) {
-    super(viewName, {defaultFocusSelector: '.primary'});
+    super(viewName, {defaultFocusSelector: '.primary', dismissByEsc: true});
 
     this.image = dom.getFrom(this.root, '.review-image', HTMLElement);
     this.video = dom.getFrom(this.root, '.review-video', HTMLVideoElement);
@@ -194,8 +194,9 @@
       }
       setupI18nElements(btnGroup.el);
     }
-
-    nav.open(this.viewName);
+    nav.open(this.viewName).then(() => {
+      onSelected.signal(null);
+    });
     const result = await onSelected.wait();
     nav.close(this.viewName);
     return result;
diff --git a/ash/webui/camera_app_ui/resources/strings/camera_strings.grd b/ash/webui/camera_app_ui/resources/strings/camera_strings.grd
index 376f394..902092f 100644
--- a/ash/webui/camera_app_ui/resources/strings/camera_strings.grd
+++ b/ash/webui/camera_app_ui/resources/strings/camera_strings.grd
@@ -683,6 +683,12 @@
       <message desc="Label for expert mode option: show all resolutions." name="IDS_EXPERT_SHOW_ALL_RESOLUTIONS">
         Show all resolutions
       </message>
+      <message desc="Label for spoken feedback to indicate that the mute button is now off." name="IDS_ARIA_MUTE_OFF">
+        Mute button off
+      </message>
+      <message desc="Label for spoken feedback to indicate that the mute button is now on." name="IDS_ARIA_MUTE_ON">
+        Mute button on
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_ARIA_MUTE_OFF.png.sha1 b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_ARIA_MUTE_OFF.png.sha1
new file mode 100644
index 0000000..4aad6cc
--- /dev/null
+++ b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_ARIA_MUTE_OFF.png.sha1
@@ -0,0 +1 @@
+0cdf98d416314468da7fdf6c05bd0bd7e02c944b
\ No newline at end of file
diff --git a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_ARIA_MUTE_ON.png.sha1 b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_ARIA_MUTE_ON.png.sha1
new file mode 100644
index 0000000..b03a059
--- /dev/null
+++ b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_ARIA_MUTE_ON.png.sha1
@@ -0,0 +1 @@
+c9f17952974ca90d8ae5be8c64f1b27c29fbf796
\ No newline at end of file
diff --git a/ash/webui/camera_app_ui/resources/utils/cca.py b/ash/webui/camera_app_ui/resources/utils/cca.py
index 81106b5..bffce35 100755
--- a/ash/webui/camera_app_ui/resources/utils/cca.py
+++ b/ash/webui/camera_app_ui/resources/utils/cca.py
@@ -96,6 +96,11 @@
         # For better debugging experience on DUT.
         '--inlineSourceMap',
         '--inlineSources',
+        # For easier developing / test cycle.
+        '--noUnusedLocals',
+        'false',
+        '--noUnusedParameters',
+        'false',
     ])
 
     build_pak_cmd = [
diff --git a/ash/webui/camera_app_ui/resources/views/main.html b/ash/webui/camera_app_ui/resources/views/main.html
index cd85c85..5de9128 100644
--- a/ash/webui/camera_app_ui/resources/views/main.html
+++ b/ash/webui/camera_app_ui/resources/views/main.html
@@ -224,10 +224,12 @@
       <div id="options-group" class="left-stripe buttons circle">
         <button id="open-ptz-panel" tabindex="0" aria-haspopup="true"
                 i18n-label="open_ptz_panel_button"
-                i18n-new-feature="new_control_toast">
+                i18n-new-feature="new_control_toast"></button>
         <button id="open-timer-panel" tabindex="0" aria-haspopup="true">
-        <button id="open-grid-panel" tabindex="0" aria-haspopup="true">
+        </button>
+        <button id="open-grid-panel" tabindex="0" aria-haspopup="true"></button>
         <button id="open-mirror-panel" tabindex="0" aria-haspopup="true">
+        </button>
       </div>
       <div class="top-stripe left-stripe buttons circle">
         <button id="open-settings" tabindex="0"
@@ -241,7 +243,7 @@
       <div class="top-stripe right-stripe circle buttons">
         <input id="toggle-mic" type="checkbox" tabindex="0"
                i18n-label="toggle_mic_button" data-state="mic"
-               data-key="toggleMic" checked>
+               i18n-aria="aria_mute_off" data-key="toggleMic" checked>
       </div>
       <div class="top-stripe right-stripe circle buttons">
         <input id="toggle-barcode" type="checkbox" tabindex="0"
@@ -338,7 +340,7 @@
           <button class="icon" tabindex="0" i18n-aria="back_button"></button>
           <div id="settings-header" i18n-text="settings_button"></div>
         </div>
-        <button id="settings-photo-resolution"class="menu-item inkdrop
+        <button id="settings-photo-resolution" class="menu-item inkdrop
                 expandable" tabindex="0">
           <div class="icon"></div>
           <div>
@@ -496,13 +498,13 @@
          aria-live="polite"></div>
     <div id="focus-ring"></div>
     <div id="tooltip" aria-hidden="true"></div>
-    <audio id="sound-tick-final" src="/sounds/tick_final.ogg">
-    <audio id="sound-tick-inc" src="/sounds/tick_inc.ogg">
-    <audio id="sound-tick-start" src="/sounds/tick_start.ogg">
-    <audio id="sound-shutter" src="/sounds/shutter.ogg">
-    <audio id="sound-rec-start" src="/sounds/record_start.ogg">
-    <audio id="sound-rec-end" src="/sounds/record_end.ogg">
-    <audio id="sound-rec-pause" src="/sounds/record_pause.ogg">
+    <audio id="sound-tick-final" src="/sounds/tick_final.ogg"></audio>
+    <audio id="sound-tick-inc" src="/sounds/tick_inc.ogg"></audio>
+    <audio id="sound-tick-start" src="/sounds/tick_start.ogg"></audio>
+    <audio id="sound-shutter" src="/sounds/shutter.ogg"></audio>
+    <audio id="sound-rec-start" src="/sounds/record_start.ogg"></audio>
+    <audio id="sound-rec-end" src="/sounds/record_end.ogg"></audio>
+    <audio id="sound-rec-pause" src="/sounds/record_pause.ogg"></audio>
     <template id="preview-video-template">
       <video id="preview-video" class="preview-content" aria-hidden="true"
         muted></video>
@@ -529,9 +531,9 @@
         <span></span>
         <div class="fps-buttons">
           <button class="fps-button fps-30" i18n-aria="label_30fps"
-                  tabindex="0">
+                  tabindex="0"></button>
           <button class="fps-button fps-60" i18n-aria="label_60fps"
-                  tabindex="0">
+                  tabindex="0"></button>
         </div>
       </label>
     </template>
diff --git a/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.html b/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.html
index e65ca84..d7add02 100644
--- a/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.html
+++ b/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.html
@@ -5,6 +5,7 @@
 
   cr-input {
     font-family: var(--shimless-hint-font-family);
+    --cr-input-error-display: none;
   }
 
   #inputValidationLabel {
@@ -13,8 +14,6 @@
     font-size: var(--shimless-hint-font-size);
     font-weight: var(--shimless-medium-font-weight);
     line-height: var(--shimless-hint-line-height);
-    padding-bottom: 8px;
-    padding-top: 8px;
   }
 
   :host([rsu-code-invalid_]) #inputValidationLabel {
@@ -58,7 +57,6 @@
       <span inner-h-t-m-l="[[rsuInstructionsText_]]"></span>
     </div>
     <div id="inputContainer">
-      <div id="inputValidationLabel">[[i18n('rsuCodeLabelText')]]</div>
       <cr-input
           id="rsuCode"
           value="{{rsuCode_}}"
@@ -68,6 +66,9 @@
           disabled="[[allButtonsDisabled]]"
           error-message="[[i18n('rsuCodeErrorLabelText')]]">
       </cr-input>
+      <div id="inputValidationLabel">
+        [[getRsuCodeLabelText_(rsuCodeInvalid_)]]
+      </div>
     </div>
   </div>
   <div slot="right-pane">
diff --git a/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.js b/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.js
index 5efc0a0..36f8bac 100644
--- a/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.js
+++ b/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.js
@@ -197,6 +197,7 @@
     // Set to false whenever the user changes the code to remove the red invalid
     // warning.
     this.rsuCodeInvalid_ = false;
+    this.rsuCode_ = this.rsuCode_.toUpperCase();
   }
 
   /**
@@ -264,6 +265,15 @@
       this.rsuCodeInvalid_ = true;
     }
   }
+
+  /**
+   * @return {string}
+   * @protected
+   */
+  getRsuCodeLabelText_() {
+    return this.rsuCodeInvalid_ ? this.i18n('rsuCodeErrorLabelText') :
+                                  this.i18n('rsuCodeLabelText');
+  }
 }
 
 customElements.define(
diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc
index 57bf0f7b..c5eb76eb 100644
--- a/base/process/launch_posix.cc
+++ b/base/process/launch_posix.cc
@@ -706,7 +706,7 @@
   alignas(16) char stack_buf[PTHREAD_STACK_MIN];
 #if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) ||   \
     defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_S390_FAMILY) || \
-    defined(ARCH_CPU_PPC64_FAMILY)
+    defined(ARCH_CPU_PPC64_FAMILY) || defined(ARCH_CPU_LOONG_FAMILY)
   // The stack grows downward.
   void* stack = stack_buf + sizeof(stack_buf);
 #else
diff --git a/base/profiler/stack_sampler_impl_unittest.cc b/base/profiler/stack_sampler_impl_unittest.cc
index 4c402bfc..276098c 100644
--- a/base/profiler/stack_sampler_impl_unittest.cc
+++ b/base/profiler/stack_sampler_impl_unittest.cc
@@ -70,13 +70,14 @@
                  TimeTicks* timestamp,
                  RegisterContext* thread_context,
                  Delegate* delegate) override {
-    std::memcpy(stack_buffer->buffer(), &fake_stack_[0], fake_stack_.size());
-    *stack_top =
-        reinterpret_cast<uintptr_t>(&fake_stack_[0] + fake_stack_.size());
-    // Set the stack pointer to be consistent with the provided fake stack.
+    std::memcpy(stack_buffer->buffer(), &fake_stack_[0],
+                fake_stack_.size() * sizeof(fake_stack_[0]));
+    *stack_top = reinterpret_cast<uintptr_t>(stack_buffer->buffer() +
+                                             fake_stack_.size());
+    // Set the stack pointer to be consistent with the copied stack.
     *thread_context = {};
     RegisterContextStackPointer(thread_context) =
-        reinterpret_cast<uintptr_t>(&fake_stack_[0]);
+        reinterpret_cast<uintptr_t>(stack_buffer->buffer());
 
     *timestamp = timestamp_;
 
@@ -107,37 +108,23 @@
 // Trivial unwinder implementation for testing.
 class TestUnwinder : public Unwinder {
  public:
-  TestUnwinder(size_t stack_size = 0,
-               std::vector<uintptr_t>* stack_copy = nullptr,
-               // Variable to fill in with the bottom address of the
-               // copied stack. This will be different than
-               // &(*stack_copy)[0] because |stack_copy| is a copy of the
-               // copy so does not share memory with the actual copy.
-               uintptr_t* stack_copy_bottom = nullptr)
-      : stack_size_(stack_size),
-        stack_copy_(stack_copy),
-        stack_copy_bottom_(stack_copy_bottom) {}
+  explicit TestUnwinder(std::vector<uintptr_t>* stack_copy)
+      : stack_copy_(stack_copy) {}
 
   bool CanUnwindFrom(const Frame& current_frame) const override { return true; }
 
   UnwindResult TryUnwind(RegisterContext* thread_context,
                          uintptr_t stack_top,
                          std::vector<Frame>* stack) const override {
-    if (stack_copy_) {
-      auto* bottom = reinterpret_cast<uintptr_t*>(
-          RegisterContextStackPointer(thread_context));
-      auto* top = bottom + stack_size_;
-      *stack_copy_ = std::vector<uintptr_t>(bottom, top);
-    }
-    if (stack_copy_bottom_)
-      *stack_copy_bottom_ = RegisterContextStackPointer(thread_context);
+    auto* bottom = reinterpret_cast<uintptr_t*>(
+        RegisterContextStackPointer(thread_context));
+    *stack_copy_ =
+        std::vector<uintptr_t>(bottom, reinterpret_cast<uintptr_t*>(stack_top));
     return UnwindResult::kCompleted;
   }
 
  private:
-  size_t stack_size_;
   raw_ptr<std::vector<uintptr_t>> stack_copy_;
-  raw_ptr<uintptr_t> stack_copy_bottom_;
 };
 
 // Records invocations of calls to OnStackCapture()/UpdateModules().
@@ -279,8 +266,7 @@
   std::vector<uintptr_t> stack_copy;
   StackSamplerImpl stack_sampler_impl(
       std::make_unique<TestStackCopier>(stack),
-      MakeUnwindersFactory(
-          std::make_unique<TestUnwinder>(stack.size(), &stack_copy)),
+      MakeUnwindersFactory(std::make_unique<TestUnwinder>(&stack_copy)),
       &module_cache);
 
   stack_sampler_impl.Initialize();
@@ -302,8 +288,7 @@
   TimeTicks timestamp = TimeTicks::UnixEpoch();
   StackSamplerImpl stack_sampler_impl(
       std::make_unique<TestStackCopier>(stack, timestamp),
-      MakeUnwindersFactory(
-          std::make_unique<TestUnwinder>(stack.size(), &stack_copy)),
+      MakeUnwindersFactory(std::make_unique<TestUnwinder>(&stack_copy)),
       &module_cache);
 
   stack_sampler_impl.Initialize();
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 10f82ac6..c2ab73e 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-8.20220505.3.1
+8.20220506.1.1
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
index 3507754..56de677 100644
--- a/cc/tiles/gpu_image_decode_cache.cc
+++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -2861,8 +2861,17 @@
                              image_data->upload_scale_mip_level;
   bool quality_is_compatible =
       CalculateDesiredFilterQuality(draw_image) <= image_data->quality;
-  bool color_is_compatible =
-      image_data->target_color_params == draw_image.target_color_params();
+  sk_sp<SkColorSpace> decoded_target_colorspace =
+      ColorSpaceForImageDecode(draw_image, image_data->mode);
+  bool color_is_compatible = false;
+  if (!decoded_target_colorspace ||
+      !gfx::ColorSpace(*decoded_target_colorspace).IsPQOrHLG()) {
+    color_is_compatible = image_data->target_color_params.color_space ==
+                          draw_image.target_color_space();
+  } else {
+    color_is_compatible =
+        image_data->target_color_params == draw_image.target_color_params();
+  }
   if (!color_is_compatible)
     return false;
   if (is_scaled && (!scale_is_compatible || !quality_is_compatible))
diff --git a/chrome/VERSION b/chrome/VERSION
index 3aad9fe..25ffec9 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=103
 MINOR=0
-BUILD=5046
+BUILD=5047
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 0297f2c1..c732fd6 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -592,6 +592,7 @@
   "java/src/org/chromium/chrome/browser/findinpage/FindToolbarObserver.java",
   "java/src/org/chromium/chrome/browser/findinpage/FindToolbarPhone.java",
   "java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java",
+  "java/src/org/chromium/chrome/browser/firstrun/ChildAccountStatusSupplier.java",
   "java/src/org/chromium/chrome/browser/firstrun/DefaultSearchEngineFirstRunFragment.java",
   "java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java",
   "java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 48bc880..5e34d9bb 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -111,6 +111,7 @@
   "junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java",
   "junit/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollectorTest.java",
   "junit/src/org/chromium/chrome/browser/findinpage/FindToolbarManagerTest.java",
+  "junit/src/org/chromium/chrome/browser/firstrun/ChildAccountStatusSupplierTest.java",
   "junit/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfoTest.java",
   "junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java",
   "junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java",
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java
index a4cc6a7..f0c7a088 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java
@@ -198,10 +198,17 @@
                 .ViewHolder viewHolder = TestThreadUtils.runOnUiThreadBlocking(
                 () -> new AutofillAssistantCollectUserDataTestHelper.ViewHolder(coordinator));
 
-        /* Initially, everything is invisible. */
+        // Set WebContents such that editors can be built.
+        TestThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> model.set(AssistantCollectUserDataModel.WEB_CONTENTS,
+                                mTestRule.getWebContents()));
+
+        // Initially, everything is invisible.
         onView(is(coordinator.getView())).check(matches(not(isDisplayed())));
 
-        /* PR is visible, but no section was requested: all sections should be invisible. */
+        // User data block is visible, but no section was requested: all sections should be
+        // invisible.
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantCollectUserDataModel.VISIBLE, true));
         onView(is(coordinator.getView())).check(matches(isDisplayed()));
@@ -209,7 +216,7 @@
         onView(is(viewHolder.mPaymentSection)).check(matches(not(isDisplayed())));
         onView(is(viewHolder.mShippingSection)).check(matches(not(isDisplayed())));
 
-        /* Contact details should be visible if either name, phone, or email is requested. */
+        // Contact details should be visible if either name, phone, or email is requested.
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantCollectUserDataModel.REQUEST_NAME, true));
         onView(is(viewHolder.mContactSection)).check(matches(isDisplayed()));
@@ -241,22 +248,31 @@
         onView(is(viewHolder.mPaymentSection)).check(matches(not(isDisplayed())));
         onView(is(viewHolder.mShippingSection)).check(matches(not(isDisplayed())));
 
-        /* Payment method section visibility test. */
+        // Payment method section visibility test.
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantCollectUserDataModel.REQUEST_PAYMENT, true));
         onView(is(viewHolder.mPaymentSection)).check(matches(isDisplayed()));
 
-        /* Shipping address visibility test. */
+        // Shipping address visibility test.
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS, true));
         onView(is(viewHolder.mShippingSection)).check(matches(isDisplayed()));
 
-        /* Login section visibility test. */
+        // Login section visibility test.
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE, true));
+        onView(is(viewHolder.mLoginsSection)).check(matches(not(isDisplayed())));
+        TestThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> model.set(AssistantCollectUserDataModel.AVAILABLE_LOGINS,
+                                Collections.singletonList(new AssistantLoginChoice("id",
+                                        /* label= */ "Guest", /* sublabel= */ "Description",
+                                        /* sublabelAccessibilityHint= */ "", /* priority= */ 0,
+                                        /* infoPopup= */ null,
+                                        /* editButtonContentDescription= */ ""))));
         onView(is(viewHolder.mLoginsSection)).check(matches(isDisplayed()));
 
-        /* Prepended section visibility test. */
+        // Prepended section visibility test.
         List<AssistantAdditionalSectionFactory> prependedSections = new ArrayList<>();
         prependedSections.add(
                 new AssistantStaticTextSection.Factory("Prepended section", "Lorem ipsum."));
@@ -264,17 +280,26 @@
                 ()
                         -> model.set(AssistantCollectUserDataModel.PREPENDED_SECTIONS,
                                 prependedSections));
-        /* Login section is top-most regular section. */
+        // Login section is top-most regular section, the prepended section should be above that.
         onView(withText("Prepended section")).check(isAbove(is(viewHolder.mLoginsSection)));
 
-        /* Appended section visibility test. */
+        // Appended section visibility test.
         List<AssistantAdditionalSectionFactory> appendedSections = new ArrayList<>();
         appendedSections.add(
                 new AssistantStaticTextSection.Factory("Appended section", "Lorem ipsum."));
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> model.set(AssistantCollectUserDataModel.APPENDED_SECTIONS, appendedSections));
-        /* Shipping address is bottom-most regular section. */
+        // Shipping address is bottom-most regular section, the appended section should be below
+        // that.
         onView(withText("Appended section")).check(isBelow(is(viewHolder.mShippingSection)));
+
+        // Sections without items and without editor should be hidden. Removing WebContents will
+        // clear the editors.
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> model.set(AssistantCollectUserDataModel.WEB_CONTENTS, null));
+        onView(is(viewHolder.mContactSection)).check(matches(not(isDisplayed())));
+        onView(is(viewHolder.mPaymentSection)).check(matches(not(isDisplayed())));
+        onView(is(viewHolder.mShippingSection)).check(matches(not(isDisplayed())));
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java
index ced10dc..4129fd1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java
@@ -25,7 +25,6 @@
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.share.ChromeShareExtras;
 import org.chromium.chrome.browser.share.ShareDelegate;
@@ -171,9 +170,6 @@
         }
 
         private void showShareIph() {
-            if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SHARED_HIGHLIGHTING_V2)) {
-                return;
-            }
             View view = mTab.getView();
             int padding = view.getResources().getDimensionPixelSize(
                     R.dimen.iph_shared_highlighting_padding_top);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ChildAccountStatusSupplier.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ChildAccountStatusSupplier.java
new file mode 100644
index 0000000..2cf322ad
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ChildAccountStatusSupplier.java
@@ -0,0 +1,59 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.firstrun;
+
+import android.os.SystemClock;
+
+import org.chromium.base.Callback;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.supplier.OneshotSupplier;
+import org.chromium.base.supplier.OneshotSupplierImpl;
+import org.chromium.components.signin.AccountManagerFacade;
+import org.chromium.components.signin.AccountManagerFacadeProvider;
+import org.chromium.components.signin.AccountUtils;
+
+/**
+ * Fetches the child account status to be used by other FRE components.
+ *
+ * TODO(https://crbug.com/1320374): Check app restrictions to speed up this listener.
+ */
+public class ChildAccountStatusSupplier implements OneshotSupplier<Boolean> {
+    private final OneshotSupplierImpl<Boolean> mValue = new OneshotSupplierImpl<>();
+
+    /**
+     * Creates ChildAccountStatusSupplier. This doesn't actually start fetching the child account
+     * status until {@link #startFetchingChildAccountStatus()} is invoked.
+     */
+    public ChildAccountStatusSupplier() {}
+
+    /**
+     * Starts the process to obtain the child account status from {@link AccountManagerFacade}.
+     * Should be invoked after AccountManagerFacade instance has been already set.
+     *
+     * TODO(https://crbug.com/1320487): Add Supplier to AccountManagerFacadeProvider and remove this
+     *                                  method.
+     */
+    public void startFetchingChildAccountStatus() {
+        long childAccountStatusStart = SystemClock.elapsedRealtime();
+        AccountManagerFacadeProvider.getInstance().getAccounts().then(accounts -> {
+            AccountUtils.checkChildAccountStatus(
+                    AccountManagerFacadeProvider.getInstance(), accounts, (isChild, account) -> {
+                        RecordHistogram.recordTimesHistogram("MobileFre.ChildAccountStatusDuration",
+                                SystemClock.elapsedRealtime() - childAccountStatusStart);
+                        mValue.set(isChild);
+                    });
+        });
+    }
+
+    @Override
+    public Boolean onAvailable(Callback<Boolean> callback) {
+        return mValue.onAvailable(callback);
+    }
+
+    @Override
+    public Boolean get() {
+        return mValue.get();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
index 62e9ab8..c3ecc507 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -23,7 +23,6 @@
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.BooleanSupplier;
-import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
@@ -101,8 +100,6 @@
     // Use hasValue() to simplify access. Will be null before initialized.
     private final OneshotSupplierImpl<Boolean> mNativeSideIsInitializedSupplier =
             new OneshotSupplierImpl<>();
-    private final OneshotSupplierImpl<Boolean> mChildAccountStatusSupplier =
-            new OneshotSupplierImpl<>();
 
     private FirstRunFlowSequencer mFirstRunFlowSequencer;
 
@@ -250,6 +247,8 @@
         // needs to register the synthetic trial group. See https://crbug.com/1295692 for details.
         FREMobileIdentityConsistencyFieldTrial.createFirstRunTrial();
 
+        super.triggerLayoutInflation();
+
         initializeStateFromLaunchData();
         RecordHistogram.recordTimesHistogram("MobileFre.FromLaunch.TriggerLayoutInflation",
                 SystemClock.elapsedRealtime() - mIntentCreationElapsedRealtimeMs);
@@ -266,13 +265,11 @@
                     findViewById(android.R.id.content), () -> mPages.size() > 0);
         }
 
-        mFirstRunFlowSequencer = new FirstRunFlowSequencer(this) {
+        mFirstRunFlowSequencer = new FirstRunFlowSequencer(this, getChildAccountStatusSupplier()) {
             @Override
             public void onFlowIsKnown(Bundle freProperties) {
                 assert freProperties != null;
                 mFreProperties = freProperties;
-                mChildAccountStatusSupplier.set(
-                        mFreProperties.getBoolean(SyncConsentFirstRunFragment.IS_CHILD_ACCOUNT));
 
                 onInternalStateChanged();
 
@@ -602,11 +599,6 @@
     }
 
     @Override
-    public OneshotSupplier<Boolean> getChildAccountStatusListener() {
-        return mChildAccountStatusSupplier;
-    }
-
-    @Override
     public void showInfoPage(@StringRes int url) {
         CustomTabActivity.showInfoPage(
                 this, LocalizationUtils.substituteLocalePlaceholder(getString(url)));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java
index a4bfa09..7617ea6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java
@@ -11,6 +11,8 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 
+import androidx.annotation.CallSuper;
+
 import org.chromium.base.IntentUtils;
 import org.chromium.base.Log;
 import org.chromium.base.metrics.RecordHistogram;
@@ -50,6 +52,7 @@
     private final FirstRunAppRestrictionInfo mFirstRunAppRestrictionInfo;
     private final OneshotSupplierImpl<PolicyService> mPolicyServiceSupplier;
     private final PolicyLoadListener mPolicyLoadListener;
+    private final ChildAccountStatusSupplier mChildAccountStatusSupplier;
 
     private final long mStartTime;
     private long mNativeInitializedTime;
@@ -59,6 +62,7 @@
         mPolicyServiceSupplier = new OneshotSupplierImpl<>();
         mPolicyLoadListener =
                 new PolicyLoadListener(mFirstRunAppRestrictionInfo, mPolicyServiceSupplier);
+        mChildAccountStatusSupplier = new ChildAccountStatusSupplier();
         mStartTime = SystemClock.elapsedRealtime();
         mPolicyLoadListener.onAvailable(this::onPolicyLoadListenerAvailable);
     }
@@ -74,8 +78,15 @@
         return true;
     }
 
-    // Activity:
+    @Override
+    @CallSuper
+    public void triggerLayoutInflation() {
+        // ChildAccountStatusSupplier can't be created in the constructor, as AccountManagerFacade
+        // instance is not set yet there.
+        mChildAccountStatusSupplier.startFetchingChildAccountStatus();
+    }
 
+    // Activity:
     @Override
     public void onPause() {
         super.onPause();
@@ -179,6 +190,13 @@
     }
 
     /**
+     * Returns the supplier that supplies child account status.
+     */
+    public OneshotSupplier<Boolean> getChildAccountStatusSupplier() {
+        return mChildAccountStatusSupplier;
+    }
+
+    /**
      * If the first run activity was triggered by a custom tab, notify app associated with
      * custom tab whether first run was completed.
      * @param freIntent First run activity intent.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
index ffd05d2d..f40dc01 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -10,7 +10,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.SystemClock;
 import android.provider.Settings;
 
 import androidx.annotation.VisibleForTesting;
@@ -20,6 +19,7 @@
 import org.chromium.base.IntentUtils;
 import org.chromium.base.Log;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.LaunchIntentDispatcher;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
-import org.chromium.components.signin.AccountUtils;
 import org.chromium.components.signin.identitymanager.ConsentLevel;
 import org.chromium.components.signin.identitymanager.IdentityManager;
 
@@ -110,9 +109,6 @@
     }
 
     private final Activity mActivity;
-    private boolean mIsChild;
-    private List<Account> mGoogleAccounts;
-
     /**
      * The delegate to be used by the Sequencer. By default, it's an instance of
      * {@link FirstRunFlowSequencerDelegate}, unless it's overridden by {@code sDelegateForTesting}.
@@ -122,6 +118,10 @@
     /** If not null, overrides {@code mDelegate} for this object during tests. */
     private static FirstRunFlowSequencerDelegate sDelegateForTesting;
 
+    private boolean mIsFlowKnown;
+    private Boolean mIsChild;
+    private List<Account> mGoogleAccounts;
+
     /**
      * Callback that is called once the flow is determined.
      * If the properties is null, the First Run experience needs to finish and
@@ -130,29 +130,29 @@
      */
     public abstract void onFlowIsKnown(Bundle freProperties);
 
-    public FirstRunFlowSequencer(Activity activity) {
+    public FirstRunFlowSequencer(
+            Activity activity, OneshotSupplier<Boolean> childAccountStatusSupplier) {
         mActivity = activity;
+
         mDelegate = sDelegateForTesting != null ? sDelegateForTesting
                                                 : new FirstRunFlowSequencerDelegate();
+
+        childAccountStatusSupplier.onAvailable(this::setChildAccountStatus);
     }
 
     /**
      * Starts determining parameters for the First Run.
      * Once finished, calls onFlowIsKnown().
+     *
+     * TODO(https://crbug.com/1320487): Add Supplier to AccountManagerFacadeProvider and remove this
+     *                                  method.
      */
     void start() {
-        long childAccountStatusStart = SystemClock.elapsedRealtime();
         AccountManagerFacadeProvider.getInstance().getAccounts().then(accounts -> {
-            AccountUtils.checkChildAccountStatus(
-                    AccountManagerFacadeProvider.getInstance(), accounts, (isChild, account) -> {
-                        RecordHistogram.recordCount1MHistogram(
-                                "Signin.AndroidDeviceAccountsNumberWhenEnteringFRE",
-                                Math.min(accounts.size(), 2));
-                        RecordHistogram.recordTimesHistogram("MobileFre.ChildAccountStatusDuration",
-                                SystemClock.elapsedRealtime() - childAccountStatusStart);
-                        initializeSharedState(isChild, accounts);
-                        processFreEnvironmentPreNative();
-                    });
+            RecordHistogram.recordCount1MHistogram(
+                    "Signin.AndroidDeviceAccountsNumberWhenEnteringFRE",
+                    Math.min(accounts.size(), 2));
+            setAccountList(accounts);
         });
     }
 
@@ -165,12 +165,25 @@
         return mDelegate.shouldShowSyncConsentPage(mActivity, mGoogleAccounts, mIsChild);
     }
 
-    private void initializeSharedState(boolean isChild, List<Account> accounts) {
+    private void setChildAccountStatus(boolean isChild) {
+        assert mIsChild == null;
         mIsChild = isChild;
-        mGoogleAccounts = accounts;
+        maybeProcessFreEnvironmentPreNative();
     }
 
-    private void processFreEnvironmentPreNative() {
+    private void setAccountList(List<Account> accounts) {
+        assert mGoogleAccounts == null && accounts != null;
+        mGoogleAccounts = accounts;
+        maybeProcessFreEnvironmentPreNative();
+    }
+
+    private void maybeProcessFreEnvironmentPreNative() {
+        // Wait till both child account status and the list of accounts are available.
+        if (mIsChild == null || mGoogleAccounts == null) return;
+
+        if (mIsFlowKnown) return;
+        mIsFlowKnown = true;
+
         Bundle freProperties = new Bundle();
         freProperties.putBoolean(SyncConsentFirstRunFragment.IS_CHILD_ACCOUNT, mIsChild);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
index 32b81ff..17d4878 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
@@ -88,5 +88,5 @@
     /**
      * Returns the supplier that supplies child account status.
      */
-    OneshotSupplier<Boolean> getChildAccountStatusListener();
+    OneshotSupplier<Boolean> getChildAccountStatusSupplier();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
index 052afce0..44c3d1c8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
@@ -84,9 +84,11 @@
 
     @Override
     public void triggerLayoutInflation() {
+        super.triggerLayoutInflation();
+
         setFinishOnTouchOutside(true);
 
-        mFirstRunFlowSequencer = new FirstRunFlowSequencer(this) {
+        mFirstRunFlowSequencer = new FirstRunFlowSequencer(this, getChildAccountStatusSupplier()) {
             @Override
             public void onFlowIsKnown(Bundle freProperties) {
                 if (freProperties == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFirstRunFragment.java
index 8bba45b8..00c8d97 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFirstRunFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFirstRunFragment.java
@@ -63,7 +63,7 @@
         super.onAttach(context);
         getPageDelegate().getPolicyLoadListener().onAvailable(
                 hasPolicies -> notifyCoordinatorWhenNativePolicyAndChildStatusAreLoaded());
-        getPageDelegate().getChildAccountStatusListener().onAvailable(
+        getPageDelegate().getChildAccountStatusSupplier().onAvailable(
                 ignored -> notifyCoordinatorWhenNativePolicyAndChildStatusAreLoaded());
         if (getPageDelegate().isLaunchedFromCct()) {
             mSkipTosDialogPolicyListener = new SkipTosDialogPolicyListener(
@@ -232,7 +232,7 @@
         if (getPageDelegate() == null) return;
 
         if (mSigninFirstRunCoordinator != null && mNativeInitialized
-                && getPageDelegate().getChildAccountStatusListener().get() != null
+                && getPageDelegate().getChildAccountStatusSupplier().get() != null
                 && getPageDelegate().getPolicyLoadListener().get() != null) {
             mSigninFirstRunCoordinator.onNativePolicyAndChildStatusLoaded(
                     getPageDelegate().getPolicyLoadListener().get());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
index c36e064..2464e025 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
@@ -11,6 +11,7 @@
 
 import static org.hamcrest.Matchers.is;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.when;
 
 import android.accounts.Account;
@@ -360,7 +361,7 @@
     }
 
     private void unblockOnFlowIsKnown() {
-        Mockito.verify(mAccountManagerFacade).getAccounts();
+        Mockito.verify(mAccountManagerFacade, atLeastOnce()).getAccounts();
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> mAccountsPromise.fulfill(Collections.emptyList()));
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java
index 984e32d..91f36cab 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentRenderTest.java
@@ -150,7 +150,7 @@
             mFragment.onNativeInitialized();
             OneshotSupplierImpl<Boolean> childAccountStatusListener = new OneshotSupplierImpl<>();
             childAccountStatusListener.set(false);
-            when(mFirstRunPageDelegateMock.getChildAccountStatusListener())
+            when(mFirstRunPageDelegateMock.getChildAccountStatusSupplier())
                     .thenReturn(childAccountStatusListener);
         });
         mFragment.setPageDelegate(mFirstRunPageDelegateMock);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java
index c840b59..6769647 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java
@@ -175,7 +175,7 @@
         when(mPolicyLoadListenerMock.get()).thenReturn(false);
         when(mFirstRunPageDelegateMock.getPolicyLoadListener()).thenReturn(mPolicyLoadListenerMock);
         when(mChildAccountStatusListenerMock.get()).thenReturn(false);
-        when(mFirstRunPageDelegateMock.getChildAccountStatusListener())
+        when(mFirstRunPageDelegateMock.getChildAccountStatusSupplier())
                 .thenReturn(mChildAccountStatusListenerMock);
         when(mFirstRunPageDelegateMock.isLaunchedFromCct()).thenReturn(false);
         mChromeActivityTestRule.startMainActivityOnBlankPage();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/ChildAccountStatusSupplierTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/ChildAccountStatusSupplierTest.java
new file mode 100644
index 0000000..8385466
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/ChildAccountStatusSupplierTest.java
@@ -0,0 +1,113 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.firstrun;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.os.Looper;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.metrics.UmaRecorderHolder;
+import org.chromium.base.metrics.test.ShadowRecordHistogram;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
+
+/**
+ * Tests for {@link ChildAccountStatusSupplier}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {ShadowRecordHistogram.class})
+public class ChildAccountStatusSupplierTest {
+    private static final String ADULT_ACCOUNT_EMAIL = "adult.account@gmail.com";
+    private static final String CHILD_ACCOUNT_EMAIL =
+            AccountManagerTestRule.generateChildEmail(/*baseName=*/"account@gmail.com");
+
+    @Rule
+    public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
+
+    private ChildAccountStatusSupplier mSupplier;
+
+    @Before
+    public void setUp() {
+        mSupplier = new ChildAccountStatusSupplier();
+    }
+
+    @After
+    public void tearDown() {
+        UmaRecorderHolder.resetForTesting();
+        ShadowRecordHistogram.reset();
+    }
+
+    @Test
+    public void testUnsetByDefault() {
+        // Supplier shouldn't be set and should not record any histograms until it can obtain the
+        // list of accounts from AccountManagerFacade.
+        assertNull(mSupplier.get());
+        assertEquals(0,
+                ShadowRecordHistogram.getHistogramTotalCountForTesting(
+                        "MobileFre.ChildAccountStatusDuration"));
+    }
+
+    @Test
+    public void testNoAccounts() {
+        mSupplier.startFetchingChildAccountStatus();
+        shadowOf(Looper.getMainLooper()).idle();
+
+        assertFalse(mSupplier.get());
+        assertEquals(1,
+                ShadowRecordHistogram.getHistogramTotalCountForTesting(
+                        "MobileFre.ChildAccountStatusDuration"));
+    }
+
+    @Test
+    public void testOneChildAccount() {
+        mAccountManagerTestRule.addAccount(CHILD_ACCOUNT_EMAIL);
+
+        mSupplier.startFetchingChildAccountStatus();
+        shadowOf(Looper.getMainLooper()).idle();
+
+        assertTrue(mSupplier.get());
+        assertEquals(1,
+                ShadowRecordHistogram.getHistogramTotalCountForTesting(
+                        "MobileFre.ChildAccountStatusDuration"));
+    }
+
+    @Test
+    public void testNonChildAccount() {
+        mAccountManagerTestRule.addAccount(ADULT_ACCOUNT_EMAIL);
+
+        mSupplier.startFetchingChildAccountStatus();
+        shadowOf(Looper.getMainLooper()).idle();
+
+        assertFalse(mSupplier.get());
+        assertEquals(1,
+                ShadowRecordHistogram.getHistogramTotalCountForTesting(
+                        "MobileFre.ChildAccountStatusDuration"));
+    }
+
+    @Test
+    public void testOneChildAccountWithNonChildAccounts() {
+        mAccountManagerTestRule.addAccount(CHILD_ACCOUNT_EMAIL);
+        mAccountManagerTestRule.addAccount(ADULT_ACCOUNT_EMAIL);
+
+        mSupplier.startFetchingChildAccountStatus();
+        shadowOf(Looper.getMainLooper()).idle();
+
+        assertTrue(mSupplier.get());
+        assertEquals(1,
+                ShadowRecordHistogram.getHistogramTotalCountForTesting(
+                        "MobileFre.ChildAccountStatusDuration"));
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java
index e01cb665..155c85715 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java
@@ -95,8 +95,22 @@
         public Bundle returnedBundle;
         public boolean calledOnFlowIsKnown;
 
+        private final ChildAccountStatusSupplier mChildAccountStatusSupplier;
+
         public TestFirstRunFlowSequencer(Activity activity) {
-            super(activity);
+            this(activity, new ChildAccountStatusSupplier());
+        }
+
+        private TestFirstRunFlowSequencer(
+                Activity activity, ChildAccountStatusSupplier childAccountStatusSupplier) {
+            super(activity, childAccountStatusSupplier);
+            mChildAccountStatusSupplier = childAccountStatusSupplier;
+        }
+
+        @Override
+        public void start() {
+            super.start();
+            mChildAccountStatusSupplier.startFetchingChildAccountStatus();
         }
 
         @Override
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 4fd80b1e..332feb2 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -191,7 +191,6 @@
 #define IDC_BOOKMARKS_MENU              40029
 #define IDC_SHOW_SIGNIN                 40030
 #define IDC_EXTENSION_ERRORS            40031
-#define IDC_SHOW_SIGNIN_ERROR           40032
 #define IDC_SHOW_SETTINGS_CHANGE_FIRST  40033
 #define IDC_SHOW_SETTINGS_CHANGE_LAST   40133
 #define IDC_SHOW_AVATAR_MENU            40134
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index f08d5f8..31b619ae 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -915,17 +915,6 @@
       </if>
 
       <!-- Sync/sign-in error messages -->
-      <if expr="not chromeos_ash">
-        <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when the user's sign-in credentials are out of date.">
-          Chromium could not sync your data because your account sign-in details are out of date.
-        </message>
-        <message name="IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when sync is not available for their domain.">
-          Chromium could not sync your data because Sync is not available for your domain.
-        </message>
-        <message name="IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when there's an error signing in.">
-          Chromium could not sync your data due to an error signing in.
-        </message>
-      </if>
       <if expr="chromeos_ash">
         <message name="IDS_SIGNIN_ERROR_SECONDARY_ACCOUNT_DISPLAY_SOURCE" desc="Context title shown in the notification header of sign-in error notification for ChromiumOS Secondary Accounts.">
           ChromiumOS System
@@ -1470,7 +1459,7 @@
       <message name="IDS_PRIVACY_SANDBOX_DIALOG_NOTICE_BOTTOM_SUMMARY" desc="A conclusion paragraph for the entire page. It sits beneath the “More control over the ads you see” subtitle but it’s no more associated with that topic than “Limit sharing between sites”. * “in Chrome settings”: The URL is chrome://settings/privacySandbox. We don’t make it a live link because we need the users to stay in this moment until they make a choice.">
         You can learn more about these features in Chromium settings.
       </message>
-      
+
       <!-- ChromiumUpdater Strings -->
       <if expr="is_win">
         <message name="IDS_FRIENDLY_COMPANY_NAME" desc="Company name">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 45931c7a..37dd0fd 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -9982,39 +9982,6 @@
         </message>
       </if>
 
-      <if expr="not use_titlecase">
-        <message name="IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_ACCEPT" desc="The accept button in the sync error bubble view when sync is not available for their domain.">
-          OK...
-        </message>
-        <if expr="chromeos_ash">
-          <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT" desc="The accept button in the sync error bubble view/notification when the user needs to sign out and sign in again to ChromeOS.">
-            Sign out then sign in again...
-          </message>
-          <message name="IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM" desc="The sync error wrench menu item when the user needs to sign out and sign in again to ChromeOS.">
-            Sign out then sign in again...
-          </message>
-        </if>
-        <if expr="not chromeos_ash">
-          <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT" desc="The accept button in the sync error bubble view when the user needs to sign in again.">
-            Sign in again...
-          </message>
-          <message name="IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM" desc="The sync error wrench menu item when the user needs to sign in again.">
-              Sign in again...
-          </message>
-        </if>
-      </if>
-      <if expr="use_titlecase">
-        <message name="IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_ACCEPT" desc="The accept button in the sync error bubble view when sync is not available for their domain.">
-          OK...
-        </message>
-        <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT" desc="The accept button in the sync error bubble view when the user needs to sign in again.">
-          Sign in Again...
-        </message>
-        <message name="IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM" desc="The sync error wrench menu item when the user needs to sign in again.">
-          Sign in Again...
-        </message>
-      </if>
-
       <!-- Android uses native UI to handle Sync settings -->
       <if expr="not is_android">
         <!-- Sync options dialog strings -->
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 3b453b4..f4b4a6e 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -957,17 +957,6 @@
       </if>
 
       <!-- Sync/sign-in error messages -->
-      <if expr="not chromeos_ash">
-        <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when the user's sign-in credentials are out of date.">
-          Google Chrome could not sync your data because your account sign-in details are out of date.
-        </message>
-        <message name="IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when sync is not available for their domain.">
-          Google Chrome could not sync your data because Sync is not available for your domain.
-        </message>
-        <message name="IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when there's an error signing in.">
-          Google Chrome could not sync your data due to an error signing in.
-        </message>
-      </if>
       <if expr="chromeos_ash">
         <if expr="reven">
           <message name="IDS_SIGNIN_ERROR_SECONDARY_ACCOUNT_DISPLAY_SOURCE" desc="Context title shown in the notification header of sign-in error notification for ChromeOS Flex Secondary Accounts.">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index e8e6d83..69a4785a 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2564,6 +2564,7 @@
       "//components/services/screen_ai",
       "//components/services/screen_ai/public/cpp:screen_ai_service_router_factory",
       "//components/services/screen_ai/public/cpp:utilities",
+      "//components/services/screen_ai/public/mojom",
     ]
   }
 
@@ -6254,10 +6255,6 @@
       "profiles/profile_statistics_factory.h",
       "signin/force_signin_verifier.cc",
       "signin/force_signin_verifier.h",
-      "signin/signin_global_error.cc",
-      "signin/signin_global_error.h",
-      "signin/signin_global_error_factory.cc",
-      "signin/signin_global_error_factory.h",
       "signin/signin_manager.cc",
       "signin/signin_manager.h",
       "signin/signin_manager_factory.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a80974cc..ccd7f74d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -6891,9 +6891,6 @@
      FEATURE_VALUE_TYPE(features::kCopyLinkToText)},
 #endif  // !BUILDFLAG(IS_ANDROID)
 
-    {"shared-highlighting-v2", flag_descriptions::kSharedHighlightingV2Name,
-     flag_descriptions::kSharedHighlightingV2Description, kOsAll,
-     FEATURE_VALUE_TYPE(shared_highlighting::kSharedHighlightingV2)},
     {"shared-highlighting-amp", flag_descriptions::kSharedHighlightingAmpName,
      flag_descriptions::kSharedHighlightingAmpDescription, kOsAll,
      FEATURE_VALUE_TYPE(shared_highlighting::kSharedHighlightingAmp)},
diff --git a/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.cc b/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.cc
index c15344f..dcf070c 100644
--- a/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.cc
+++ b/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.cc
@@ -189,7 +189,8 @@
     int rph_id,
     const crash_reporter::CrashMetricsReporter::ReportedCrashTypeSet&
         reported_counts) {
-  if (rph_id != web_contents()->GetMainFrame()->GetProcess()->GetID())
+  if (rph_id !=
+      web_contents()->GetPrimaryPage().GetMainDocument().GetProcess()->GetID())
     return;
   if (!reported_counts.count(
           crash_reporter::CrashMetricsReporter::ProcessedCrashCounts::
@@ -270,17 +271,17 @@
 
   start_monitor_timestamp_ = base::TimeTicks::Now();
 
-  content::RenderFrameHost* main_frame = web_contents()->GetMainFrame();
-  DCHECK(main_frame);
+  content::RenderFrameHost& main_frame =
+      web_contents()->GetPrimaryPage().GetMainDocument();
 
   // Connections to the renderer will not be recreated when coming out of the
   // cache so prevent us from getting in there in the first place.
   content::BackForwardCache::DisableForRenderFrameHost(
-      main_frame,
+      &main_frame,
       back_forward_cache::DisabledReason(
           back_forward_cache::DisabledReasonId::kOomInterventionTabHelper));
 
-  content::RenderProcessHost* render_process_host = main_frame->GetProcess();
+  content::RenderProcessHost* render_process_host = main_frame.GetProcess();
   DCHECK(render_process_host);
   render_process_host->BindReceiver(intervention_.BindNewPipeAndPassReceiver());
   DCHECK(!receiver_.is_bound());
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
index 398a63b..52aa307 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
@@ -169,16 +169,16 @@
   if (!LoadFromDictionary(*dict, /* lazy_icon_load= */ true))
     return false;
 
-  // If the icon was previously downloaded using a different url, do not use
-  // that icon.
-  if (GetLastIconUrl(*dict) != icon_url_)
-    return false;
-
   if (LoadLaunchUrlFromDictionary(*dict)) {
     SetStatus(Status::kInstalled);
     return true;
   }
 
+  // If the icon was previously downloaded using a different url and the app has
+  // not been installed earlier, do not use that icon.
+  if (GetLastIconUrl(*dict) != icon_url_)
+    return false;
+
   // Wait while icon is loaded.
   if (status_ == Status::kInit)
     SetStatus(Status::kLoading);
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
index bb1c749a..0be2b76c 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
@@ -79,7 +79,9 @@
   const GURL install_url_;  // installation url.
   GURL launch_url_;         // app launch url.
 
-  GURL icon_url_;  // Url of the icon in case nothing is cached.
+  // Url for loading the app icon in case the app has not been installed earlier
+  // and a user opened the App menu in the login screen.
+  GURL icon_url_;
   // Used to download icon from |icon_url_|.
   std::unique_ptr<IconFetcher> icon_fetcher_;
 
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
index 3a0d55d..6cd9709 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <codecvt>
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h"
 
 #include "base/path_service.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_data_delegate.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -35,6 +37,8 @@
 const char kIconBadPath[] = "chrome/test/data/load_image/image.html";
 const char kIconUrl[] = "/load_image/image.png";
 const char kIconUrl2[] = "/load_image/fail_image.png";
+const char kIconExampleUrl1[] = "https://example.com/icon1.png";
+const char kIconExampleUrl2[] = "https://example.com/icon2.png";
 const char kLastIconUrlKey[] = "last_icon_url";
 const char kLaunchUrl[] = "https://example.com/launch";
 const char kStartUrl[] = "https://example.com/start";
@@ -45,6 +49,16 @@
   return test_data_dir.Append(valid ? kIconPath : kIconBadPath);
 }
 
+void PopulateIcon(WebAppInstallInfo* web_app_info,
+                  const std::string& icon_url_str) {
+  IconsMap icons_map;
+  const GURL icon_url(icon_url_str);
+  std::vector<SkBitmap> bmp = {web_app::CreateSquareIcon(32, SK_ColorWHITE)};
+  icons_map.emplace(icon_url, bmp);
+
+  web_app::PopulateProductIcons(web_app_info, &icons_map);
+}
+
 }  // namespace
 
 class WebKioskAppDataTest : public InProcessBrowserTest,
@@ -102,7 +116,7 @@
 IN_PROC_BROWSER_TEST_F(WebKioskAppDataTest, NoIconCached) {
   WebKioskAppData app_data(this, kAppId, EmptyAccountId(), GURL(kAppUrl),
                            std::string(), /*icon_url*/ GURL());
-  app_data.LoadFromCache();
+  EXPECT_FALSE(app_data.LoadFromCache());
   // The app will stay in the INIT state if there is nothing to be loaded from
   // cache.
   EXPECT_EQ(app_data.status(), WebKioskAppData::Status::kInit);
@@ -114,7 +128,7 @@
   SetCached(/*installed = */ false);
   WebKioskAppData app_data(this, kAppId, EmptyAccountId(), GURL(kAppUrl),
                            std::string(), /*icon_url*/ GURL());
-  app_data.LoadFromCache();
+  EXPECT_TRUE(app_data.LoadFromCache());
   app_data.LoadIcon();
   WaitForAppDataChange(2);
 
@@ -164,7 +178,7 @@
 
   WebKioskAppData app_data(this, kAppId, EmptyAccountId(), GURL(kAppUrl),
                            kAppTitle2, /*icon_url=*/icon_url);
-  app_data.LoadFromCache();
+  EXPECT_TRUE(app_data.LoadFromCache());
   // Icon is stored in cache.
   EXPECT_EQ(app_data.status(), WebKioskAppData::Status::kLoading);
 
@@ -204,7 +218,7 @@
                            kAppTitle2,
                            /*icon_url*/ test_server.GetURL(kIconUrl2));
 
-  app_data.LoadFromCache();
+  EXPECT_FALSE(app_data.LoadFromCache());
   // No icon was loaded from cache because urls are different.
   EXPECT_EQ(app_data.status(), WebKioskAppData::Status::kInit);
 
@@ -246,6 +260,34 @@
   EXPECT_EQ(app_data.GetLaunchableUrl(), GURL(kStartUrl));
 }
 
+IN_PROC_BROWSER_TEST_F(WebKioskAppDataTest,
+                       PRE_CanLoadFromCacheAfterUpdatingFromWebAppInfo) {
+  // We do not use |icon_url| for loading icon in this test, it is set to
+  // correctly test |LoadFromCache| function.
+  WebKioskAppData app_data(this, kAppId, EmptyAccountId(), GURL(kAppUrl), "",
+                           /*icon_url=*/GURL(kIconExampleUrl1));
+
+  EXPECT_EQ(app_data.status(), WebKioskAppData::Status::kInit);
+  EXPECT_EQ(app_data.GetLaunchableUrl(), GURL(kAppUrl));
+  EXPECT_TRUE(app_data.icon().isNull());
+
+  WebAppInstallInfo app_info;
+  app_info.start_url = GURL(kStartUrl);
+  std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
+  app_info.title = convert.from_bytes(kAppTitle);
+  PopulateIcon(&app_info, kIconExampleUrl1);
+
+  app_data.UpdateFromWebAppInfo(app_info);
+}
+
+IN_PROC_BROWSER_TEST_F(WebKioskAppDataTest,
+                       CanLoadFromCacheAfterUpdatingFromWebAppInfo) {
+  WebKioskAppData app_data(this, kAppId, EmptyAccountId(), GURL(kAppUrl), "",
+                           /*icon_url=*/GURL(kIconExampleUrl2));
+
+  EXPECT_TRUE(app_data.LoadFromCache());
+}
+
 IN_PROC_BROWSER_TEST_F(WebKioskAppDataTest, InvalidIcon) {
   SetCached(/*installed = */ false, /*icon_valid=*/false);
   WebKioskAppData app_data(this, kAppId, EmptyAccountId(), GURL(kAppUrl),
diff --git a/chrome/browser/ash/arc/input_overlay/input_overlay_resources_util.cc b/chrome/browser/ash/arc/input_overlay/input_overlay_resources_util.cc
index d919cd91..5f5063c3 100644
--- a/chrome/browser/ash/arc/input_overlay/input_overlay_resources_util.cc
+++ b/chrome/browser/ash/arc/input_overlay/input_overlay_resources_util.cc
@@ -21,6 +21,7 @@
       {"com.androbaby.game2048", IDR_IO_COM_ANDROBABY_GAME2048},
       {"co.imba.archero", IDR_IO_CO_IMBA_ARCHERO},
       {"com.datavisionstudio.roguelike", IDR_IO_COM_DATAVISIONSTUDIO_ROGUELIKE},
+      {"com.blackpanther.ninjaarashi", IDR_IO_COM_BLACKPANTHER_NINJAARASHI},
   };
 
   auto it = resource_id_map.find(package_name);
diff --git a/chrome/browser/ash/crostini/crostini_export_import_notification_controller.cc b/chrome/browser/ash/crostini/crostini_export_import_notification_controller.cc
index 5ab0497..381c178 100644
--- a/chrome/browser/ash/crostini/crostini_export_import_notification_controller.cc
+++ b/chrome/browser/ash/crostini/crostini_export_import_notification_controller.cc
@@ -100,7 +100,7 @@
         if (!button_index.has_value()) {
           return;
         }
-        DCHECK(*button_index == 1);
+        DCHECK_EQ(0, *button_index);
         CrostiniExportImport::GetForProfile(profile)->CancelOperation(
             type, container_id);
       },
diff --git a/chrome/browser/ash/input_method/multi_word_suggester.cc b/chrome/browser/ash/input_method/multi_word_suggester.cc
index 94f1b61d..0d8ae426 100644
--- a/chrome/browser/ash/input_method/multi_word_suggester.cc
+++ b/chrome/browser/ash/input_method/multi_word_suggester.cc
@@ -127,12 +127,16 @@
 MultiWordSuggester::~MultiWordSuggester() = default;
 
 void MultiWordSuggester::OnFocus(int context_id) {
+  // Some parts of the code reserve negative/zero context_id for unfocused
+  // context. As a result we should make sure it is not being erroneously set to
+  // a negative number, and cause unexpected behaviour.
+  DCHECK(context_id);
   focused_context_id_ = context_id;
   state_.ResetSuggestion();
 }
 
 void MultiWordSuggester::OnBlur() {
-  focused_context_id_ = 0;
+  focused_context_id_ = absl::nullopt;
   state_.ResetSuggestion();
 }
 
@@ -217,10 +221,15 @@
 }
 
 bool MultiWordSuggester::AcceptSuggestion(size_t index) {
+  if (!focused_context_id_.has_value()) {
+    LOG(ERROR) << "suggest: Failed to accept suggestion. No context id.";
+    return false;
+  }
+
   std::string error;
-  suggestion_handler_->AcceptSuggestion(focused_context_id_, &error);
+  suggestion_handler_->AcceptSuggestion(*focused_context_id_, &error);
   if (!error.empty()) {
-    LOG(ERROR) << "suggest: failed to accept suggestion - " << error;
+    LOG(ERROR) << "suggest: Failed to accept suggestion - " << error;
     return false;
   }
 
@@ -238,8 +247,12 @@
 }
 
 void MultiWordSuggester::DismissSuggestion() {
+  if (!focused_context_id_.has_value()) {
+    LOG(ERROR) << "suggest: Failed to dismiss suggestion. No context id.";
+    return;
+  }
   std::string error;
-  suggestion_handler_->DismissSuggestion(focused_context_id_, &error);
+  suggestion_handler_->DismissSuggestion(*focused_context_id_, &error);
   if (!error.empty()) {
     LOG(ERROR) << "suggest: Failed to dismiss suggestion - " << error;
     return;
@@ -274,6 +287,10 @@
 
 void MultiWordSuggester::DisplaySuggestion(
     const SuggestionState::Suggestion& suggestion) {
+  if (!focused_context_id_.has_value()) {
+    LOG(ERROR) << "suggest: Failed to show suggestion. No context id.";
+    return;
+  }
   ui::ime::SuggestionDetails details;
   details.text = suggestion.text;
   details.show_accept_annotation = false;
@@ -285,7 +302,7 @@
       kSuggestionSelectedMessage, base::UTF16ToUTF8(details.text).c_str()));
 
   std::string error;
-  suggestion_handler_->SetSuggestion(focused_context_id_, details, &error);
+  suggestion_handler_->SetSuggestion(*focused_context_id_, details, &error);
   if (!error.empty()) {
     LOG(ERROR) << "suggest: Failed to show suggestion in assistive framework"
                << " - " << error;
@@ -293,9 +310,13 @@
 }
 
 void MultiWordSuggester::SetSuggestionHighlight(bool highlighted) {
+  if (!focused_context_id_.has_value()) {
+    LOG(ERROR) << "suggest: Failed to set button highlighted. No context id.";
+    return;
+  }
   std::string error;
   suggestion_handler_->SetButtonHighlighted(
-      focused_context_id_, suggestion_button_, highlighted, &error);
+      *focused_context_id_, suggestion_button_, highlighted, &error);
   if (!error.empty()) {
     LOG(ERROR) << "Failed to set button highlighted. " << error;
   }
diff --git a/chrome/browser/ash/input_method/multi_word_suggester.h b/chrome/browser/ash/input_method/multi_word_suggester.h
index cd15ac5..b848b999 100644
--- a/chrome/browser/ash/input_method/multi_word_suggester.h
+++ b/chrome/browser/ash/input_method/multi_word_suggester.h
@@ -144,8 +144,8 @@
   // Announce the given message to the user.
   void Announce(const std::u16string& message);
 
-  // The currently focused input (zero if none are focused)
-  int focused_context_id_ = 0;
+  // The currently focused input (nullopt if none are focused)
+  absl::optional<int> focused_context_id_;
 
   // Not owned by this class
   SuggestionHandlerInterface* suggestion_handler_;
diff --git a/chrome/browser/ash/input_method/multi_word_suggester_unittest.cc b/chrome/browser/ash/input_method/multi_word_suggester_unittest.cc
index 12e78d1..da5be937 100644
--- a/chrome/browser/ash/input_method/multi_word_suggester_unittest.cc
+++ b/chrome/browser/ash/input_method/multi_word_suggester_unittest.cc
@@ -111,6 +111,22 @@
   EXPECT_EQ(suggestion_handler_.GetSuggestionText(), u"hello there!");
 }
 
+TEST_F(MultiWordSuggesterTest,
+       AfterBlurDoesNotDisplayRelevantExternalSuggestions) {
+  std::vector<TextSuggestion> suggestions = {
+      TextSuggestion{.mode = TextSuggestionMode::kPrediction,
+                     .type = TextSuggestionType::kMultiWord,
+                     .text = "hello there!"}};
+
+  suggester_->OnFocus(kFocusedContextId);
+  suggester_->OnSurroundingTextChanged(u"", 0, 0);
+  suggester_->OnBlur();
+  suggester_->OnExternalSuggestionsUpdated(suggestions);
+
+  EXPECT_FALSE(suggestion_handler_.GetShowingSuggestion());
+  EXPECT_NE(suggestion_handler_.GetContextId(), kFocusedContextId);
+}
+
 TEST_F(MultiWordSuggesterTest, AcceptsSuggestionOnTabPress) {
   std::vector<TextSuggestion> suggestions = {
       TextSuggestion{.mode = TextSuggestionMode::kPrediction,
@@ -129,6 +145,22 @@
   EXPECT_EQ(suggestion_handler_.GetSuggestionText(), u"");
 }
 
+TEST_F(MultiWordSuggesterTest, DoesNotAcceptSuggestionAfterBlur) {
+  std::vector<TextSuggestion> suggestions = {
+      TextSuggestion{.mode = TextSuggestionMode::kPrediction,
+                     .type = TextSuggestionType::kMultiWord,
+                     .text = "hi there!"},
+  };
+
+  suggester_->OnFocus(kFocusedContextId);
+  suggester_->OnSurroundingTextChanged(u"", 0, 0);
+  suggester_->OnExternalSuggestionsUpdated(suggestions);
+  suggester_->OnBlur();
+  SendKeyEvent(suggester_.get(), ui::DomCode::TAB);
+
+  EXPECT_FALSE(suggestion_handler_.GetAcceptedSuggestion());
+}
+
 TEST_F(MultiWordSuggesterTest, DoesNotAcceptSuggestionOnNonTabKeypress) {
   std::vector<TextSuggestion> suggestions = {
       TextSuggestion{.mode = TextSuggestionMode::kPrediction,
@@ -199,6 +231,22 @@
   EXPECT_EQ(suggestion_handler_.GetSuggestionText(), u"");
 }
 
+TEST_F(MultiWordSuggesterTest, DoesNotHighlightAfterBlur) {
+  std::vector<TextSuggestion> suggestions = {
+      TextSuggestion{.mode = TextSuggestionMode::kPrediction,
+                     .type = TextSuggestionType::kMultiWord,
+                     .text = "hi there!"},
+  };
+
+  suggester_->OnFocus(kFocusedContextId);
+  suggester_->OnSurroundingTextChanged(u"", 0, 0);
+  suggester_->OnExternalSuggestionsUpdated(suggestions);
+  suggester_->OnBlur();
+  SendKeyEvent(suggester_.get(), ui::DomCode::ARROW_DOWN);
+
+  EXPECT_FALSE(suggestion_handler_.GetHighlightedSuggestion());
+}
+
 TEST_F(MultiWordSuggesterTest, HighlightsSuggestionOnDownArrow) {
   std::vector<TextSuggestion> suggestions = {
       TextSuggestion{.mode = TextSuggestionMode::kPrediction,
diff --git a/chrome/browser/ash/login/ui/login_display_host_common.cc b/chrome/browser/ash/login/ui/login_display_host_common.cc
index 929585a..2748097 100644
--- a/chrome/browser/ash/login/ui/login_display_host_common.cc
+++ b/chrome/browser/ash/login/ui/login_display_host_common.cc
@@ -414,6 +414,13 @@
     return true;
   }
 
+  if (action == LoginAcceleratorAction::kToggleSystemInfo) {
+    if (!GetOobeUI())
+      return false;
+    GetOobeUI()->GetCoreOobeView()->ToggleSystemInfo();
+    return true;
+  }
+
   // This path should only handle screen-specific acceletators, so we do not
   // need to create WebUI here.
   if (IsWizardControllerCreated() &&
diff --git a/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash_unittest.cc b/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash_unittest.cc
index 88cd3b8f..8a258672 100644
--- a/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash_unittest.cc
+++ b/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash_unittest.cc
@@ -936,7 +936,6 @@
   expect_robot_auth_fetch_failure_ = true;
   RunTest();
   ExpectFailedEnrollment(EnrollmentStatus::ROBOT_REFRESH_FETCH_FAILED);
-  EXPECT_EQ(net::HTTP_BAD_REQUEST, status_.http_status());
 }
 
 TEST_P(DeviceCloudPolicyManagerAshEnrollmentTest,
diff --git a/chrome/browser/ash/policy/enrollment/enrollment_handler.cc b/chrome/browser/ash/policy/enrollment/enrollment_handler.cc
index 2d5834d..fd94775 100644
--- a/chrome/browser/ash/policy/enrollment/enrollment_handler.cc
+++ b/chrome/browser/ash/policy/enrollment/enrollment_handler.cc
@@ -634,10 +634,21 @@
   StartJoinAdDomain();
 }
 
-void EnrollmentHandler::OnDeviceAccountTokenError(EnrollmentStatus status) {
-  CHECK(enrollment_step_ == STEP_ROBOT_AUTH_FETCH ||
-        enrollment_step_ == STEP_STORE_ROBOT_AUTH);
-  ReportResult(status);
+void EnrollmentHandler::OnDeviceAccountTokenFetchError(
+    absl::optional<DeviceManagementStatus> dm_status) {
+  CHECK_EQ(enrollment_step_, STEP_ROBOT_AUTH_FETCH);
+  if (dm_status.has_value()) {
+    ReportResult(EnrollmentStatus::ForRobotAuthFetchError(dm_status.value()));
+  } else {
+    ReportResult(EnrollmentStatus::ForStatus(
+        EnrollmentStatus::ROBOT_REFRESH_FETCH_FAILED));
+  }
+}
+
+void EnrollmentHandler::OnDeviceAccountTokenStoreError() {
+  CHECK_EQ(enrollment_step_, STEP_STORE_ROBOT_AUTH);
+  ReportResult(EnrollmentStatus::ForStatus(
+      EnrollmentStatus::ROBOT_REFRESH_STORE_FAILED));
 }
 
 void EnrollmentHandler::OnDeviceAccountClientError(
diff --git a/chrome/browser/ash/policy/enrollment/enrollment_handler.h b/chrome/browser/ash/policy/enrollment/enrollment_handler.h
index b0dfab2b..b687f31 100644
--- a/chrome/browser/ash/policy/enrollment/enrollment_handler.h
+++ b/chrome/browser/ash/policy/enrollment/enrollment_handler.h
@@ -116,7 +116,9 @@
   // DeviceAccountInitializer::Delegate:
   void OnDeviceAccountTokenFetched(bool empty_token) override;
   void OnDeviceAccountTokenStored() override;
-  void OnDeviceAccountTokenError(EnrollmentStatus status) override;
+  void OnDeviceAccountTokenFetchError(
+      absl::optional<DeviceManagementStatus> dm_status) override;
+  void OnDeviceAccountTokenStoreError() override;
   void OnDeviceAccountClientError(DeviceManagementStatus status) override;
   enterprise_management::DeviceServiceApiAccessRequest::DeviceType
   GetRobotAuthCodeDeviceType() override;
diff --git a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
index c235889..01cf891 100644
--- a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
+++ b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
@@ -76,56 +76,85 @@
                                            int32_t x,
                                            int32_t y,
                                            int32_t width,
-                                           int32_t height) {
+                                           int32_t height,
+                                           SetWindowBoundsCallback callback) {
   aura::Window* target = GetWindow(id);
   // TODO(crbug.com/1253318): Ensure this works with multiple screens.
-  if (target) {
-    target->SetBounds(gfx::Rect(x, y, width, height));
+  if (!target) {
+    std::move(callback).Run(
+        blink::mojom::CrosWindowManagementStatus::kWindowNotFound);
+    return;
   }
+
+  target->SetBounds(gfx::Rect(x, y, width, height));
+  std::move(callback).Run(blink::mojom::CrosWindowManagementStatus::kSuccess);
 }
 
 void WindowManagementImpl::SetFullscreen(const base::UnguessableToken& id,
-                                         bool fullscreen) {
+                                         bool fullscreen,
+                                         SetFullscreenCallback callback) {
   views::Widget* widget = GetWidget(id);
-  if (widget) {
-    widget->SetFullscreen(fullscreen);
+  if (!widget) {
+    std::move(callback).Run(
+        blink::mojom::CrosWindowManagementStatus::kWindowNoWidget);
+    return;
   }
+  widget->SetFullscreen(fullscreen);
+  std::move(callback).Run(blink::mojom::CrosWindowManagementStatus::kSuccess);
 }
 
-void WindowManagementImpl::Maximize(const base::UnguessableToken& id) {
+void WindowManagementImpl::Maximize(const base::UnguessableToken& id,
+                                    MaximizeCallback callback) {
   aura::Window* target = GetWindow(id);
-  // TODO(b/223320570): Add error handling for stale ids.
   if (!target) {
+    std::move(callback).Run(
+        blink::mojom::CrosWindowManagementStatus::kWindowNotFound);
     return;
   }
 
   // Returns null when id points to non top level window or is null itself.
   WindowState* state = WindowState::Get(target);
-  if (state) {
-    state->Maximize();
+  if (!state) {
+    std::move(callback).Run(
+        blink::mojom::CrosWindowManagementStatus::kWindowNoWindowState);
+    return;
   }
+
+  state->Maximize();
+  std::move(callback).Run(blink::mojom::CrosWindowManagementStatus::kSuccess);
 }
 
-void WindowManagementImpl::Minimize(const base::UnguessableToken& id) {
+void WindowManagementImpl::Minimize(const base::UnguessableToken& id,
+                                    MinimizeCallback callback) {
   aura::Window* target = GetWindow(id);
-  // TODO(b/223320570): Add error handling for stale ids.
   if (!target) {
+    std::move(callback).Run(
+        blink::mojom::CrosWindowManagementStatus::kWindowNotFound);
     return;
   }
 
   // Returns null when id points to non top level window or is null itself.
   WindowState* state = WindowState::Get(target);
-  if (state) {
-    state->Minimize();
+  if (!state) {
+    std::move(callback).Run(
+        blink::mojom::CrosWindowManagementStatus::kWindowNoWindowState);
+    return;
   }
+
+  state->Minimize();
+  std::move(callback).Run(blink::mojom::CrosWindowManagementStatus::kSuccess);
 }
 
-void WindowManagementImpl::Focus(const base::UnguessableToken& id) {
+void WindowManagementImpl::Focus(const base::UnguessableToken& id,
+                                 FocusCallback callback) {
   aura::Window* target = GetWindow(id);
-  // TODO(b/223320570): Add error handling for stale ids.
-  if (target) {
-    target->Focus();
+  if (!target) {
+    std::move(callback).Run(
+        blink::mojom::CrosWindowManagementStatus::kWindowNotFound);
+    return;
   }
+  target->Focus();
+  std::move(callback).Run(blink::mojom::CrosWindowManagementStatus::kSuccess);
 }
 
 void WindowManagementImpl::Close(const base::UnguessableToken& id) {
diff --git a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h
index 90e588a0..b813512 100644
--- a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h
+++ b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h
@@ -30,16 +30,20 @@
                        int32_t x,
                        int32_t y,
                        int32_t width,
-                       int32_t height) override;
+                       int32_t height,
+                       SetWindowBoundsCallback callback) override;
 
   void SetFullscreen(const base::UnguessableToken& id,
-                     bool fullscreen) override;
+                     bool fullscreen,
+                     SetFullscreenCallback callback) override;
 
-  void Maximize(const base::UnguessableToken& id) override;
+  void Maximize(const base::UnguessableToken& id,
+                MaximizeCallback callback) override;
 
-  void Minimize(const base::UnguessableToken& id) override;
+  void Minimize(const base::UnguessableToken& id,
+                MinimizeCallback callback) override;
 
-  void Focus(const base::UnguessableToken& id) override;
+  void Focus(const base::UnguessableToken& id, FocusCallback callback) override;
 
   void Close(const base::UnguessableToken& id) override;
 
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index ba090e4..d0796c5 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -360,14 +360,9 @@
   ASSERT_TRUE(RunTest("webnavigation/forwardBack")) << message_;
 }
 
-// TODO(crbug.com/1313923): Flaky on Mac10.14
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_ForwardBack DISABLED_ForwardBack
-#else
-#define MAYBE_ForwardBack ForwardBack
-#endif
+// TODO(crbug.com/1313923): Flaky on several platforms.
 IN_PROC_BROWSER_TEST_F(WebNavigationApiBackForwardCacheTest,
-                       MAYBE_ForwardBack) {
+                       DISABLED_ForwardBack) {
   ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(RunExtensionTest("webnavigation/backForwardCache")) << message_;
 }
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index b2463be0..cc8f8e9 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2862,11 +2862,6 @@
 const char kEnableVulkanName[] = "Vulkan";
 const char kEnableVulkanDescription[] = "Use vulkan as the graphics backend.";
 
-const char kSharedHighlightingV2Name[] = "Shared Highlighting 2.0";
-const char kSharedHighlightingV2Description[] =
-    "Improvements to Shared Highlighting. Including ability to reshare or "
-    "remove a highlight.";
-
 const char kSharedHighlightingAmpName[] = "Shared Highlighting for AMP Viewers";
 const char kSharedHighlightingAmpDescription[] =
     "Enables Shared Highlighting for AMP Viwers.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index b7aafdaf..65dc0c0 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1610,9 +1610,6 @@
 extern const char kEnableVulkanName[];
 extern const char kEnableVulkanDescription[];
 
-extern const char kSharedHighlightingV2Name[];
-extern const char kSharedHighlightingV2Description[];
-
 extern const char kSharedHighlightingAmpName[];
 extern const char kSharedHighlightingAmpDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 64a4ab8f..2b53794 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -114,7 +114,6 @@
     &features::kNetworkServiceInProcess,
     &features::kPredictivePrefetchingAllowedOnAllConnectionTypes,
     &shared_highlighting::kPreemptiveLinkToTextGeneration,
-    &shared_highlighting::kSharedHighlightingV2,
     &shared_highlighting::kSharedHighlightingAmp,
     &features::kElasticOverscroll,
     &features::kElidePrioritizationOfPreNativeBootstrapTasks,
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 55e42a0..1229a1b 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
@@ -485,7 +485,6 @@
     public static final String SHARE_BUTTON_IN_TOP_TOOLBAR = "ShareButtonInTopToolbar";
     public static final String SHARE_CROW_BUTTON = "ShareCrowButton";
     public static final String SHARED_CLIPBOARD_UI = "SharedClipboardUI";
-    public static final String SHARED_HIGHLIGHTING_V2 = "SharedHighlightingV2";
     public static final String SHARED_HIGHLIGHTING_AMP = "SharedHighlightingAmp";
     public static final String SHOPPING_LIST = "ShoppingList";
     public static final String SHOW_EXTENDED_PRELOADING_SETTING = "ShowExtendedPreloadingSetting";
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.h b/chrome/browser/metrics/chrome_metrics_service_accessor.h
index 9cf99637..b124e8b 100644
--- a/chrome/browser/metrics/chrome_metrics_service_accessor.h
+++ b/chrome/browser/metrics/chrome_metrics_service_accessor.h
@@ -81,6 +81,10 @@
 class MetricsReportingHandler;
 }
 
+namespace segmentation_platform {
+class FieldTrialRegisterImpl;
+}
+
 namespace feed {
 class FeedServiceBridge;
 class FeedServiceDelegateImpl;
@@ -144,6 +148,7 @@
   friend class safe_browsing::IncidentReportingService;
   friend class safe_browsing::internal::ReporterRunner;
   friend class safe_browsing::SafeBrowsingService;
+  friend class segmentation_platform::FieldTrialRegisterImpl;
   friend class ChromeMetricsServiceClient;
   friend class ChromePasswordManagerClient;
   friend void welcome::JoinOnboardingGroup(Profile* profile);
diff --git a/chrome/browser/metrics/perf/perf_events_collector.cc b/chrome/browser/metrics/perf/perf_events_collector.cc
index 0840c2e..e4aa2bb 100644
--- a/chrome/browser/metrics/perf/perf_events_collector.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector.cc
@@ -12,7 +12,6 @@
 #include "base/files/file_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/rand_util.h"
-#include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
@@ -38,9 +37,6 @@
 const base::Feature kCWPCollectionOnHostAndGuest{
     "CWPCollectionOnHostAndGuest", base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kCWPCollectsETM{"CWPCollectsETM",
-                                    base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Name the histogram that represents the success and various failure modes for
 // parsing CPU frequencies.
 const char kParseFrequenciesHistogramName[] =
@@ -151,68 +147,65 @@
 
 // Collect precise=3 (:ppp) cycle events on microarchitectures and kernels that
 // support it.
-const char kPerfCyclesPPPCmd[] = "-- record -a -e cycles:ppp -c 1000003";
+const char kPerfCyclesPPPCmd[] = "perf record -a -e cycles:ppp -c 1000003";
 
 const char kPerfFPCallgraphPPPCmd[] =
-    "-- record -a -e cycles:ppp -g -c 4000037";
+    "perf record -a -e cycles:ppp -g -c 4000037";
 
 const char kPerfLBRCallgraphPPPCmd[] =
-    "-- record -a -e cycles:ppp -c 4000037 --call-graph lbr";
+    "perf record -a -e cycles:ppp -c 4000037 --call-graph lbr";
 
-const char kPerfCyclesPPPHGCmd[] = "-- record -a -e cycles:pppHG -c 1000003";
+const char kPerfCyclesPPPHGCmd[] = "perf record -a -e cycles:pppHG -c 1000003";
 
 const char kPerfFPCallgraphPPPHGCmd[] =
-    "-- record -a -e cycles:pppHG -g -c 4000037";
+    "perf record -a -e cycles:pppHG -g -c 4000037";
 
 // Collect default (imprecise) cycle events everywhere else.
-const char kPerfCyclesCmd[] = "-- record -a -e cycles -c 1000003";
+const char kPerfCyclesCmd[] = "perf record -a -e cycles -c 1000003";
 
-const char kPerfCyclesHGCmd[] = "-- record -a -e cycles:HG -c 1000003";
+const char kPerfCyclesHGCmd[] = "perf record -a -e cycles:HG -c 1000003";
 
-const char kPerfFPCallgraphCmd[] = "-- record -a -e cycles -g -c 4000037";
+const char kPerfFPCallgraphCmd[] = "perf record -a -e cycles -g -c 4000037";
 
-const char kPerfFPCallgraphHGCmd[] = "-- record -a -e cycles:HG -g -c 4000037";
+const char kPerfFPCallgraphHGCmd[] =
+    "perf record -a -e cycles:HG -g -c 4000037";
 
 const char kPerfLBRCallgraphCmd[] =
-    "-- record -a -e cycles -c 6000011 --call-graph lbr";
+    "perf record -a -e cycles -c 6000011 --call-graph lbr";
 
-const char kPerfLBRCmd[] = "-- record -a -e r20c4 -b -c 800011";
+const char kPerfLBRCmd[] = "perf record -a -e r20c4 -b -c 800011";
 
 // Silvermont, Airmont, Goldmont don't have a branches taken event. Therefore,
 // we sample on the branches retired event.
-const char kPerfLBRCmdAtom[] = "-- record -a -e rc4 -b -c 800011";
+const char kPerfLBRCmdAtom[] = "perf record -a -e rc4 -b -c 800011";
 
 // The following events count misses in the last level caches and level 2 TLBs.
 
 // TLB miss cycles for IvyBridge, Haswell, Broadwell and SandyBridge.
 const char kPerfITLBMissCyclesCmdIvyBridge[] =
-    "-- record -a -e itlb_misses.walk_duration -c 30001";
+    "perf record -a -e itlb_misses.walk_duration -c 30001";
 
 const char kPerfDTLBMissCyclesCmdIvyBridge[] =
-    "-- record -a -e dtlb_load_misses.walk_duration -g -c 350003";
+    "perf record -a -e dtlb_load_misses.walk_duration -g -c 350003";
 
 // TLB miss cycles for Skylake, Kabylake, Tigerlake.
 const char kPerfITLBMissCyclesCmdSkylake[] =
-    "-- record -a -e itlb_misses.walk_pending -c 30001";
+    "perf record -a -e itlb_misses.walk_pending -c 30001";
 
 const char kPerfDTLBMissCyclesCmdSkylake[] =
-    "-- record -a -e dtlb_load_misses.walk_pending -g -c 350003";
+    "perf record -a -e dtlb_load_misses.walk_pending -g -c 350003";
 
 // TLB miss cycles for Atom, including Silvermont, Airmont and Goldmont.
 const char kPerfITLBMissCyclesCmdAtom[] =
-    "-- record -a -e page_walks.i_side_cycles -c 30001";
+    "perf record -a -e page_walks.i_side_cycles -c 30001";
 
 const char kPerfDTLBMissCyclesCmdAtom[] =
-    "-- record -a -e page_walks.d_side_cycles -g -c 350003";
+    "perf record -a -e page_walks.d_side_cycles -g -c 350003";
 
-const char kPerfLLCMissesCmd[] = "-- record -a -e r412e -g -c 30007";
+const char kPerfLLCMissesCmd[] = "perf record -a -e r412e -g -c 30007";
 // Precise events (request zero skid) for last level cache misses.
-const char kPerfLLCMissesPreciseCmd[] = "-- record -a -e r412e:pp -g -c 30007";
-
-// ETM for ARM boards including trogdor and herobrine.
-const char kPerfETMCmd[] =
-    "--run_inject --inject_args inject;--itrace=i512il;--strip -- record -a -e "
-    "cs_etm/autofdo/";
+const char kPerfLLCMissesPreciseCmd[] =
+    "perf record -a -e r412e:pp -g -c 30007";
 
 const std::vector<RandomSelector::WeightAndValue> GetDefaultCommands_x86_64(
     const CPUIdentity& cpuid) {
@@ -311,41 +304,21 @@
   return cmds;
 }
 
-std::vector<RandomSelector::WeightAndValue> GetDefaultCommands_aarch64(
-    const std::string& model) {
-  using WeightAndValue = RandomSelector::WeightAndValue;
-  std::vector<WeightAndValue> cmds;
-
-  if (base::FeatureList::IsEnabled(kCWPCollectsETM) &&
-      (model == "TROGDOR" || model == "HEROBRINE")) {
-    cmds.emplace_back(WeightAndValue(50.0, kPerfCyclesHGCmd));
-    cmds.emplace_back(WeightAndValue(20.0, kPerfFPCallgraphHGCmd));
-    cmds.emplace_back(WeightAndValue(30.0, kPerfETMCmd));
-  } else {
-    cmds.emplace_back(WeightAndValue(80.0, kPerfCyclesHGCmd));
-    cmds.emplace_back(WeightAndValue(20.0, kPerfFPCallgraphHGCmd));
-  }
-  return cmds;
-}
-
 }  // namespace
 
 namespace internal {
 
-std::vector<RandomSelector::WeightAndValue> GetDefaultCommandsForCpuModel(
-    const CPUIdentity& cpuid,
-    const std::string& model) {
+std::vector<RandomSelector::WeightAndValue> GetDefaultCommandsForCpu(
+    const CPUIdentity& cpuid) {
   using WeightAndValue = RandomSelector::WeightAndValue;
 
   if (cpuid.arch == "x86_64")  // 64-bit x86
     return GetDefaultCommands_x86_64(cpuid);
 
-  if (cpuid.arch == "aarch64")  // ARM64
-    return GetDefaultCommands_aarch64(model);
-
   std::vector<WeightAndValue> cmds;
-  if (cpuid.arch == "x86" ||     // 32-bit x86, or...
-      cpuid.arch == "armv7l") {  // ARM32
+  if (cpuid.arch == "x86" ||      // 32-bit x86, or...
+      cpuid.arch == "armv7l" ||   // ARM32
+      cpuid.arch == "aarch64") {  // ARM64
     if (base::FeatureList::IsEnabled(kCWPCollectionOnHostAndGuest)) {
       cmds.emplace_back(WeightAndValue(80.0, kPerfCyclesHGCmd));
       cmds.emplace_back(WeightAndValue(20.0, kPerfFPCallgraphHGCmd));
@@ -388,8 +361,8 @@
       base::BindOnce(&PerfCollector::ParseCPUFrequencies, task_runner,
                      weak_factory_.GetWeakPtr()));
 
-  CHECK(command_selector_.SetOdds(internal::GetDefaultCommandsForCpuModel(
-      GetCPUIdentity(), base::SysInfo::HardwareModelName())));
+  CHECK(command_selector_.SetOdds(
+      internal::GetDefaultCommandsForCpu(GetCPUIdentity())));
   std::map<std::string, std::string> params;
   if (variations::GetVariationParams(kCWPFieldTrialName, &params)) {
     SetCollectionParamsFromVariationParams(params);
@@ -511,13 +484,13 @@
 }
 
 std::unique_ptr<PerfOutputCall> PerfCollector::CreatePerfOutputCall(
+    base::TimeDelta duration,
     const std::vector<std::string>& perf_args,
-    bool disable_cpu_idle,
     PerfOutputCall::DoneCallback callback) {
   DCHECK(debugd_client_provider_.get());
   return std::make_unique<PerfOutputCall>(
-      debugd_client_provider_->debug_daemon_client(), perf_args,
-      disable_cpu_idle, std::move(callback));
+      debugd_client_provider_->debug_daemon_client(), duration, perf_args,
+      std::move(callback));
 }
 
 void PerfCollector::OnPerfOutputComplete(
@@ -664,30 +637,24 @@
   return true;
 }
 
-// static
-PerfCollector::EventType PerfCollector::CommandEventType(
-    const std::vector<std::string>& args) {
-  if (args.size() < 4)
-    return EventType::kOther;
+namespace internal {
 
-  bool isRecord = false;
-  for (size_t i = 0; i + 1 < args.size(); ++i) {
-    if (!isRecord && args[i] == "record") {
-      isRecord = true;
-      continue;
-    }
-    if (isRecord && args[i] == "-e") {
-      // Cycles event can be either the raw 'cycles' event, or the event name
-      // can be annotated with some qualifier suffix. Check for all cases.
-      if (args[i + 1] == "cycles" || args[i + 1].rfind("cycles:", 0) == 0)
-        return EventType::kCycles;
-      if (args[i + 1].rfind("cs_etm/autofdo", 0) == 0)
-        return EventType::kETM;
-    }
+bool CommandSamplesCPUCycles(const std::vector<std::string>& args) {
+  // Command must start with "perf record".
+  if (args.size() < 4 || args[0] != "perf" || args[1] != "record")
+    return false;
+  // Cycles event can be either the raw 'cycles' event, or the event name can be
+  // annotated with some qualifier suffix. Check for all cases.
+  for (size_t i = 2; i + 1 < args.size(); ++i) {
+    if (args[i] == "-e" &&
+        (args[i + 1] == "cycles" || args[i + 1].rfind("cycles:", 0) == 0))
+      return true;
   }
-  return EventType::kOther;
+  return false;
 }
 
+}  // namespace internal
+
 void PerfCollector::CollectProfile(
     std::unique_ptr<SampledProfile> sampled_profile) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -700,24 +667,19 @@
     return;
   }
 
-  // Prepend the duration to the command before splitting.
-  std::vector<std::string> command = base::SplitString(
-      base::StrCat({"--duration ",
-                    base::NumberToString(
-                        collection_params().collection_duration.InSeconds()),
-                    " ", command_selector_.Select()}),
-      kPerfCommandDelimiter, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-  auto event_type = CommandEventType(command);
+  std::vector<std::string> command =
+      base::SplitString(command_selector_.Select(), kPerfCommandDelimiter,
+                        base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+  bool has_cycles = internal::CommandSamplesCPUCycles(command);
 
   DCHECK(sampled_profile->has_trigger_event());
   current_trigger_ = sampled_profile->trigger_event();
 
   perf_output_call_ = CreatePerfOutputCall(
-      command, event_type == EventType::kETM,
+      collection_params().collection_duration, command,
       base::BindOnce(&PerfCollector::OnPerfOutputComplete,
                      weak_factory_.GetWeakPtr(), std::move(incognito_observer),
-                     std::move(sampled_profile),
-                     event_type == EventType::kCycles));
+                     std::move(sampled_profile), has_cycles));
 }
 
 // static
diff --git a/chrome/browser/metrics/perf/perf_events_collector.h b/chrome/browser/metrics/perf/perf_events_collector.h
index d5d7be4..e215184 100644
--- a/chrome/browser/metrics/perf/perf_events_collector.h
+++ b/chrome/browser/metrics/perf/perf_events_collector.h
@@ -10,7 +10,6 @@
 #include <string>
 #include <vector>
 
-#include "base/time/time.h"
 #include "chrome/browser/metrics/perf/metric_collector.h"
 #include "chrome/browser/metrics/perf/perf_output.h"
 #include "chrome/browser/metrics/perf/random_selector.h"
@@ -48,8 +47,8 @@
  protected:
   // For testing to mock PerfOutputCall.
   virtual std::unique_ptr<PerfOutputCall> CreatePerfOutputCall(
-      const std::vector<std::string>& quipper_args,
-      bool disable_cpu_idle,
+      base::TimeDelta duration,
+      const std::vector<std::string>& perf_args,
       PerfOutputCall::DoneCallback callback);
 
   void OnPerfOutputComplete(
@@ -145,15 +144,6 @@
   SampledProfile::TriggerEvent current_trigger_ =
       SampledProfile::UNKNOWN_TRIGGER_EVENT;
 
-  // Enumeration representing event types that need additional treatment
-  // during or after the collection.
-  enum class EventType {
-    kOther,
-    kCycles,
-    kETM,
-  };
-  static EventType CommandEventType(const std::vector<std::string>& args);
-
  private:
   // Change the values in |collection_params_| and the commands in
   // |command_selector| for any keys that are present in |params|.
@@ -181,9 +171,8 @@
 
 // Return the default set of perf commands and their odds of selection given
 // the identity of the CPU in |cpuid|.
-std::vector<RandomSelector::WeightAndValue> GetDefaultCommandsForCpuModel(
-    const CPUIdentity& cpuid,
-    const std::string& model);
+std::vector<RandomSelector::WeightAndValue> GetDefaultCommandsForCpu(
+    const CPUIdentity& cpuid);
 
 // For the "PerfCommand::"-prefixed keys in |params|, return the cpu specifier
 // that is the narrowest match for the CPU identified by |cpuid|.
diff --git a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
index d062a43..221b730 100644
--- a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
@@ -15,13 +15,10 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
-#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
-#include "base/system/sys_info.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/time/time.h"
 #include "chrome/browser/metrics/perf/cpu_identity.h"
 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
 #include "components/variations/variations_associated_data.h"
@@ -36,33 +33,32 @@
 
 const char kPerfCommandDelimiter[] = " ";
 
-const char kPerfCyclesCmd[] = "-- record -a -e cycles -c 1000003";
-const char kPerfCyclesHGCmd[] = "-- record -a -e cycles:HG -c 1000003";
-const char kPerfFPCallgraphCmd[] = "-- record -a -e cycles -g -c 4000037";
-const char kPerfFPCallgraphHGCmd[] = "-- record -a -e cycles:HG -g -c 4000037";
+const char kPerfCyclesCmd[] = "perf record -a -e cycles -c 1000003";
+const char kPerfCyclesHGCmd[] = "perf record -a -e cycles:HG -c 1000003";
+const char kPerfFPCallgraphCmd[] = "perf record -a -e cycles -g -c 4000037";
+const char kPerfFPCallgraphHGCmd[] =
+    "perf record -a -e cycles:HG -g -c 4000037";
 const char kPerfLBRCallgraphCmd[] =
-    "-- record -a -e cycles -c 6000011 --call-graph lbr";
-const char kPerfCyclesPPPCmd[] = "-- record -a -e cycles:ppp -c 1000003";
-const char kPerfCyclesPPPHGCmd[] = "-- record -a -e cycles:pppHG -c 1000003";
+    "perf record -a -e cycles -c 6000011 --call-graph lbr";
+const char kPerfCyclesPPPCmd[] = "perf record -a -e cycles:ppp -c 1000003";
+const char kPerfCyclesPPPHGCmd[] = "perf record -a -e cycles:pppHG -c 1000003";
 const char kPerfFPCallgraphPPPCmd[] =
-    "-- record -a -e cycles:ppp -g -c 4000037";
+    "perf record -a -e cycles:ppp -g -c 4000037";
 const char kPerfFPCallgraphPPPHGCmd[] =
-    "-- record -a -e cycles:pppHG -g -c 4000037";
+    "perf record -a -e cycles:pppHG -g -c 4000037";
 const char kPerfLBRCallgraphPPPCmd[] =
-    "-- record -a -e cycles:ppp -c 4000037 --call-graph lbr";
-const char kPerfLBRCmd[] = "-- record -a -e r20c4 -b -c 800011";
-const char kPerfLBRCmdAtom[] = "-- record -a -e rc4 -b -c 800011";
+    "perf record -a -e cycles:ppp -c 4000037 --call-graph lbr";
+const char kPerfLBRCmd[] = "perf record -a -e r20c4 -b -c 800011";
+const char kPerfLBRCmdAtom[] = "perf record -a -e rc4 -b -c 800011";
 const char kPerfITLBMissCyclesCmdIvyBridge[] =
-    "-- record -a -e itlb_misses.walk_duration -c 30001";
+    "perf record -a -e itlb_misses.walk_duration -c 30001";
 const char kPerfITLBMissCyclesCmdSkylake[] =
-    "-- record -a -e itlb_misses.walk_pending -c 30001";
+    "perf record -a -e itlb_misses.walk_pending -c 30001";
 const char kPerfITLBMissCyclesCmdAtom[] =
-    "-- record -a -e page_walks.i_side_cycles -c 30001";
-const char kPerfLLCMissesCmd[] = "-- record -a -e r412e -g -c 30007";
-const char kPerfLLCMissesPreciseCmd[] = "-- record -a -e r412e:pp -g -c 30007";
-const char kPerfETMCmd[] =
-    "--run_inject --inject_args inject;--itrace=i512il;--strip -- record -a -e "
-    "cs_etm/autofdo/";
+    "perf record -a -e page_walks.i_side_cycles -c 30001";
+const char kPerfLLCMissesCmd[] = "perf record -a -e r412e -g -c 30007";
+const char kPerfLLCMissesPreciseCmd[] =
+    "perf record -a -e r412e:pp -g -c 30007";
 
 // Converts a protobuf to serialized format as a byte vector.
 std::vector<uint8_t> SerializeMessageToVector(
@@ -101,17 +97,6 @@
   return proto;
 }
 
-base::TimeDelta GetDuration(const std::vector<std::string>& quipper_args) {
-  for (auto it = quipper_args.begin(); it != quipper_args.end(); ++it) {
-    if (*it == "--duration" && it != quipper_args.end()) {
-      int dur;
-      if (base::StringToInt(*(it + 1), &dur))
-        return base::Seconds(dur);
-    }
-  }
-  return base::Seconds(0);
-}
-
 // A mock PerfOutputCall class for testing, which outputs example perf data
 // after the profile duration elapses.
 class FakePerfOutputCall : public PerfOutputCall {
@@ -197,8 +182,6 @@
   using PerfCollector::collection_params;
   using PerfCollector::CollectPSICPU;
   using PerfCollector::command_selector;
-  using PerfCollector::CommandEventType;
-  using PerfCollector::EventType;
   using PerfCollector::Init;
   using PerfCollector::IsRunning;
   using PerfCollector::LacrosChannelAndVersion;
@@ -212,18 +195,15 @@
   bool collection_stopped() { return collection_stopped_; }
   bool collection_done() { return !real_callback_; }
 
-  base::TimeDelta elapsed_duration;
-
  protected:
   std::unique_ptr<PerfOutputCall> CreatePerfOutputCall(
-      const std::vector<std::string>& quipper_args,
-      bool disable_cpu_idle,
+      base::TimeDelta duration,
+      const std::vector<std::string>& perf_args,
       PerfOutputCall::DoneCallback callback) override {
     real_callback_ = std::move(callback);
-    elapsed_duration = GetDuration(quipper_args);
 
     return std::make_unique<FakePerfOutputCall>(
-        elapsed_duration,
+        duration,
         base::BindOnce(&TestPerfCollector::OnCollectionDone,
                        base::Unretained(this)),
         base::BindOnce(&TestPerfCollector::OnCollectionStopped,
@@ -243,26 +223,14 @@
 const base::TimeDelta kPeriodicCollectionInterval = base::Hours(1);
 const base::TimeDelta kCollectionDuration = base::Seconds(2);
 
-// A wrapper around CommandEventType, to test if a perf command samples
-// the cycles event. The wrapper takes a command as a string, while the
-// wrapped CommandEventType takes the command split into words.
+// A wrapper around internal::CommandSamplesCPUCycles, to test if a perf command
+// samples the cycles event. The wrapper takes a command as a string, while the
+// wrapped internal::CommandSamplesCPUCycles takes the command split into words.
 bool DoesCommandSampleCycles(std::string command) {
-  using EventType = TestPerfCollector::EventType;
   std::vector<std::string> cmd_args =
       base::SplitString(command, kPerfCommandDelimiter, base::KEEP_WHITESPACE,
                         base::SPLIT_WANT_ALL);
-  return TestPerfCollector::CommandEventType(cmd_args) == EventType::kCycles;
-}
-
-// A wrapper around CommandEventType, to test if a perf command samples
-// the etm event. The wrapper takes a command as a string, while the
-// wrapped CommandEventType takes the command split into words.
-bool DoesCommandSampleETM(std::string command) {
-  using EventType = TestPerfCollector::EventType;
-  std::vector<std::string> cmd_args =
-      base::SplitString(command, kPerfCommandDelimiter, base::KEEP_WHITESPACE,
-                        base::SPLIT_WANT_ALL);
-  return TestPerfCollector::CommandEventType(cmd_args) == EventType::kETM;
+  return internal::CommandSamplesCPUCycles(cmd_args);
 }
 
 }  // namespace
@@ -296,8 +264,6 @@
     perf_collector_->Init();
     // PerfCollector requires the user to be logged in.
     perf_collector_->RecordUserLogin(base::TimeTicks::Now());
-
-    perf_collector_->elapsed_duration = base::Seconds(0);
   }
 
   void TearDown() override {
@@ -330,20 +296,6 @@
   EXPECT_GT(perf_collector_->max_frequencies_mhz().size(), 0u);
 }
 
-TEST_F(PerfCollectorTest, PrependDuration) {
-  // Timer is active after login and a periodic collection is scheduled.
-  EXPECT_TRUE(perf_collector_->IsRunning());
-  base::HistogramTester histogram_tester;
-
-  // Advance the clock by a periodic collection interval to trigger
-  // a collection.
-  task_environment_.FastForwardBy(kPeriodicCollectionInterval);
-  EXPECT_EQ(perf_collector_->elapsed_duration, kCollectionDuration);
-  histogram_tester.ExpectUniqueSample(
-      "ChromeOS.CWP.CollectPerf",
-      TestPerfCollector::CollectionAttemptStatus::SUCCESS, 1);
-}
-
 TEST_F(PerfCollectorTest, NoCollectionWhenProfileCacheFull) {
   // Timer is active after login and a periodic collection is scheduled.
   EXPECT_TRUE(perf_collector_->IsRunning());
@@ -493,7 +445,7 @@
   cpuid.model_name = "";
   cpuid.release = "3.8.11";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -529,7 +481,7 @@
   cpuid.model_name = "";
   cpuid.release = "3.8.11";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesHGCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -546,7 +498,7 @@
   cpuid.model_name = "";
   cpuid.release = "3.8.11";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -579,7 +531,7 @@
   cpuid.model_name = "";
   cpuid.release = "3.8.11";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -618,7 +570,7 @@
   cpuid.model_name = "";
   cpuid.release = "3.18.0";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 3UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   // We have both FP and LBR based callstacks.
@@ -653,7 +605,7 @@
   cpuid.model_name = "";
   cpuid.release = "5.4.64";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 3UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd);
   // We have both FP and LBR based callstacks.
@@ -691,7 +643,7 @@
   cpuid.model_name = "";
   cpuid.release = "5.4.64";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 3UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesPPPHGCmd);
   // We have both FP and LBR based callstacks.
@@ -710,7 +662,7 @@
   cpuid.model_name = "";
   cpuid.release = "4.4.196";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -749,7 +701,7 @@
   cpuid.model_name = "";
   cpuid.release = "4.14.214";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesPPPCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -787,7 +739,7 @@
   cpuid.model = 0x70;  // Excavator
   cpuid.model_name = "";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -809,7 +761,7 @@
   cpuid.model = 0;
   cpuid.model_name = "";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -836,11 +788,11 @@
   cpuid.model = 0;
   cpuid.model_name = "";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
-  EXPECT_EQ(cmds[0].value, kPerfCyclesHGCmd);
+  EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
-  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphHGCmd);
+  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
@@ -866,7 +818,7 @@
   cpuid.model = 0;
   cpuid.model_name = "";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesHGCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -874,27 +826,6 @@
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
 }
 
-TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_Arm64_ETM) {
-  const base::Feature kCWPCollectsETM{"CWPCollectsETM",
-                                      base::FEATURE_DISABLED_BY_DEFAULT};
-  feature_list_.InitAndEnableFeature(kCWPCollectsETM);
-  CPUIdentity cpuid;
-  cpuid.arch = "aarch64";
-  cpuid.vendor = "";
-  cpuid.family = 0;
-  cpuid.model = 0;
-  cpuid.model_name = "";
-  std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "TROGDOR");
-  ASSERT_GE(cmds.size(), 2UL);
-  EXPECT_EQ(cmds[0].value, kPerfCyclesHGCmd);
-  EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
-  EXPECT_EQ(cmds[1].value, kPerfFPCallgraphHGCmd);
-  EXPECT_TRUE(DoesCommandSampleCycles(cmds[1].value));
-  EXPECT_EQ(cmds[2].value, kPerfETMCmd);
-  EXPECT_TRUE(DoesCommandSampleETM(cmds[2].value));
-}
-
 TEST_F(PerfCollectorTest, DefaultCommandsBasedOnArch_x86_32) {
   CPUIdentity cpuid;
   cpuid.arch = "x86";
@@ -903,7 +834,7 @@
   cpuid.model = 0x2f;  // Westmere
   cpuid.model_name = "";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   ASSERT_GE(cmds.size(), 2UL);
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -930,7 +861,7 @@
   cpuid.model = 0;
   cpuid.model_name = "";
   std::vector<RandomSelector::WeightAndValue> cmds =
-      internal::GetDefaultCommandsForCpuModel(cpuid, "");
+      internal::GetDefaultCommandsForCpu(cpuid);
   EXPECT_EQ(1UL, cmds.size());
   EXPECT_EQ(cmds[0].value, kPerfCyclesCmd);
   EXPECT_TRUE(DoesCommandSampleCycles(cmds[0].value));
@@ -1242,94 +1173,6 @@
       TestPerfCollector::ParseLacrosPath::kUnrecognized, 1);
 }
 
-TEST_F(PerfCollectorTest, CommandEventType) {
-  using EventType = TestPerfCollector::EventType;
-  EXPECT_EQ(TestPerfCollector::CommandEventType({"--duration", "0", "--",
-                                                 "record", "-a", "-e", "cycles",
-                                                 "-c", "1000003"}),
-            EventType::kCycles);
-  EXPECT_EQ(TestPerfCollector::CommandEventType({"--duration", "0", "--",
-                                                 "record", "-a", "-e", "cycles",
-                                                 "-g", "-c", "4000037"}),
-            EventType::kCycles);
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--", "record", "-a", "-e", "cycles", "-c",
-                 "4000037", "--call-graph", "lbr"}),
-            EventType::kCycles);
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--", "record", "-a", "-e", "cycles:ppp",
-                 "-c", "1000003"}),
-            EventType::kCycles);
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--", "record", "-a", "-e", "cycles:ppp",
-                 "-g", "-c", "4000037"}),
-            EventType::kCycles);
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--", "record", "-a", "-e", "cycles:ppp",
-                 "-c", "4000037", "--call-graph", "lbr"}),
-            EventType::kCycles);
-
-  EXPECT_EQ(TestPerfCollector::CommandEventType({"--duration", "0", "--",
-                                                 "record", "-a", "-e", "r20c4",
-                                                 "-b", "-c", "200011"}),
-            EventType::kOther);
-  EXPECT_EQ(TestPerfCollector::CommandEventType({"--duration", "0", "--",
-                                                 "record", "-a", "-e", "rc4",
-                                                 "-b", "-c", "300001"}),
-            EventType::kOther);
-  EXPECT_EQ(
-      TestPerfCollector::CommandEventType({"--duration", "0", "--", "record",
-                                           "-a", "-e", "r0481", "-c", "2003"}),
-      EventType::kOther);
-  EXPECT_EQ(
-      TestPerfCollector::CommandEventType({"--duration", "0", "--", "record",
-                                           "-a", "-e", "r13d0", "-c", "2003"}),
-      EventType::kOther);
-  EXPECT_EQ(TestPerfCollector::CommandEventType({"--duration", "0", "--",
-                                                 "record", "-a", "-e",
-                                                 "iTLB-misses", "-c", "2003"}),
-            EventType::kOther);
-  EXPECT_EQ(TestPerfCollector::CommandEventType({"--duration", "0", "--",
-                                                 "record", "-a", "-e",
-                                                 "dTLB-misses", "-c", "2003"}),
-            EventType::kOther);
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--", "record", "-a", "-e", "cache-misses",
-                 "-c", "10007"}),
-            EventType::kOther);
-
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--", "record", "-a", "-e", "instructions",
-                 "-e", "cycles", "-c", "1000003"}),
-            EventType::kCycles);
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--", "record", "-a", "-e", "instructions",
-                 "-e", "cycles:ppp", "-c", "1000003"}),
-            EventType::kCycles);
-
-  EXPECT_EQ(TestPerfCollector::CommandEventType({"--duration", "0", "--",
-                                                 "stat", "-a", "-e", "cycles",
-                                                 "-e", "instructions"}),
-            EventType::kOther);
-
-  EXPECT_EQ(
-      TestPerfCollector::CommandEventType(
-          {"--duration", "0", "--", "record", "-e", "cs_etm/autofdo/", "-a"}),
-      EventType::kETM);
-  EXPECT_EQ(
-      TestPerfCollector::CommandEventType(
-          {"--duration", "0", "--", "record", "-e", "cs_etm/autofdo/u", "-a"}),
-      EventType::kETM);
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--", "record", "-e",
-                 "cs_etm/autofdo,preset=1/", "-a"}),
-            EventType::kETM);
-  EXPECT_EQ(TestPerfCollector::CommandEventType(
-                {"--duration", "0", "--run_inject", "--inject_args", "-b", "--",
-                 "record", "-e", "cs_etm/autofdo/", "-a"}),
-            EventType::kETM);
-}
-
 class PerfCollectorCollectionParamsTest : public testing::Test {
  public:
   PerfCollectorCollectionParamsTest() {}
@@ -1357,8 +1200,7 @@
 
 TEST_F(PerfCollectorCollectionParamsTest, Commands_EmptyExperiment) {
   std::vector<RandomSelector::WeightAndValue> default_cmds =
-      internal::GetDefaultCommandsForCpuModel(
-          GetCPUIdentity(), base::SysInfo::HardwareModelName());
+      internal::GetDefaultCommandsForCpu(GetCPUIdentity());
   std::map<std::string, std::string> params;
   ASSERT_TRUE(variations::AssociateVariationParams(
       "ChromeOSWideProfilingCollection", "group_name", params));
@@ -1373,8 +1215,7 @@
 
 TEST_F(PerfCollectorCollectionParamsTest, Commands_InvalidValues) {
   std::vector<RandomSelector::WeightAndValue> default_cmds =
-      internal::GetDefaultCommandsForCpuModel(
-          GetCPUIdentity(), base::SysInfo::HardwareModelName());
+      internal::GetDefaultCommandsForCpu(GetCPUIdentity());
   std::map<std::string, std::string> params;
   // Use the "default" cpu specifier since we don't want to predict what CPU
   // this test is running on. (CPU detection is tested above.)
@@ -1401,8 +1242,7 @@
 TEST_F(PerfCollectorCollectionParamsTest, Commands_Override) {
   using WeightAndValue = RandomSelector::WeightAndValue;
   std::vector<RandomSelector::WeightAndValue> default_cmds =
-      internal::GetDefaultCommandsForCpuModel(
-          GetCPUIdentity(), base::SysInfo::HardwareModelName());
+      internal::GetDefaultCommandsForCpu(GetCPUIdentity());
   std::map<std::string, std::string> params;
   // Use the "default" cpu specifier since we don't want to predict what CPU
   // this test is running on. (CPU detection is tested above.)
@@ -1469,4 +1309,46 @@
             parsed_params.restore_session.max_collection_delay);
 }
 
+TEST(PerfCollectorInternalTest, CommandSamplesCPUCycles) {
+  EXPECT_TRUE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "cycles", "-c", "1000003"}));
+  EXPECT_TRUE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "cycles", "-g", "-c", "4000037"}));
+  EXPECT_TRUE(internal::CommandSamplesCPUCycles({"perf", "record", "-a", "-e",
+                                                 "cycles", "-c", "4000037",
+                                                 "--call-graph", "lbr"}));
+  EXPECT_TRUE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "cycles:ppp", "-c", "1000003"}));
+  EXPECT_TRUE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "cycles:ppp", "-g", "-c", "4000037"}));
+  EXPECT_TRUE(internal::CommandSamplesCPUCycles({"perf", "record", "-a", "-e",
+                                                 "cycles:ppp", "-c", "4000037",
+                                                 "--call-graph", "lbr"}));
+
+  EXPECT_FALSE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "r20c4", "-b", "-c", "200011"}));
+  EXPECT_FALSE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "rc4", "-b", "-c", "300001"}));
+  EXPECT_FALSE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "r0481", "-c", "2003"}));
+  EXPECT_FALSE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "r13d0", "-c", "2003"}));
+  EXPECT_FALSE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "iTLB-misses", "-c", "2003"}));
+  EXPECT_FALSE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "dTLB-misses", "-c", "2003"}));
+  EXPECT_FALSE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "cache-misses", "-c", "10007"}));
+
+  EXPECT_TRUE(internal::CommandSamplesCPUCycles({"perf", "record", "-a", "-e",
+                                                 "instructions", "-e", "cycles",
+                                                 "-c", "1000003"}));
+  EXPECT_TRUE(internal::CommandSamplesCPUCycles(
+      {"perf", "record", "-a", "-e", "instructions", "-e", "cycles:ppp", "-c",
+       "1000003"}));
+
+  EXPECT_FALSE(internal::CommandSamplesCPUCycles(
+      {"perf", "stat", "-a", "-e", "cycles", "-e", "instructions"}));
+}
+
 }  // namespace metrics
diff --git a/chrome/browser/metrics/perf/perf_output.cc b/chrome/browser/metrics/perf/perf_output.cc
index 4446400b..2e812d943 100644
--- a/chrome/browser/metrics/perf/perf_output.cc
+++ b/chrome/browser/metrics/perf/perf_output.cc
@@ -17,12 +17,12 @@
 namespace metrics {
 
 PerfOutputCall::PerfOutputCall(chromeos::DebugDaemonClient* debug_daemon_client,
-                               const std::vector<std::string>& quipper_args,
-                               bool disable_cpu_idle,
+                               base::TimeDelta duration,
+                               const std::vector<std::string>& perf_args,
                                DoneCallback callback)
     : debug_daemon_client_(debug_daemon_client),
-      quipper_args_(quipper_args),
-      disable_cpu_idle_(disable_cpu_idle),
+      duration_(duration),
+      perf_args_(perf_args),
       done_callback_(std::move(callback)),
       pending_stop_(false) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -37,7 +37,7 @@
           &PerfOutputCall::OnIOComplete, weak_factory_.GetWeakPtr()));
   DCHECK(debug_daemon_client_);
   debug_daemon_client_->GetPerfOutput(
-      quipper_args_, disable_cpu_idle_, pipe_write_end.get(),
+      duration_, perf_args_, pipe_write_end.get(),
       base::BindOnce(&PerfOutputCall::OnGetPerfOutput,
                      weak_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/metrics/perf/perf_output.h b/chrome/browser/metrics/perf/perf_output.h
index 070bd85..e533308 100644
--- a/chrome/browser/metrics/perf/perf_output.h
+++ b/chrome/browser/metrics/perf/perf_output.h
@@ -36,8 +36,8 @@
   using DoneCallback = base::OnceCallback<void(std::string perf_stdout)>;
 
   PerfOutputCall(chromeos::DebugDaemonClient* debug_daemon_client,
-                 const std::vector<std::string>& quipper_args,
-                 bool disable_cpu_idle,
+                 base::TimeDelta duration,
+                 const std::vector<std::string>& perf_args,
                  DoneCallback callback);
 
   PerfOutputCall(const PerfOutputCall&) = delete;
@@ -66,8 +66,8 @@
   std::unique_ptr<chromeos::PipeReader> perf_data_pipe_reader_;
 
   // Saved arguments.
-  std::vector<std::string> quipper_args_;
-  bool disable_cpu_idle_;
+  base::TimeDelta duration_;
+  std::vector<std::string> perf_args_;
   DoneCallback done_callback_;
 
   // Whether Stop() is called before OnGetPerfOutput() has returned the session
diff --git a/chrome/browser/metrics/perf/perf_output_unittest.cc b/chrome/browser/metrics/perf/perf_output_unittest.cc
index 28d295f..fd49f44 100644
--- a/chrome/browser/metrics/perf/perf_output_unittest.cc
+++ b/chrome/browser/metrics/perf/perf_output_unittest.cc
@@ -50,12 +50,13 @@
   return proto;
 }
 
-// Perf session ID returned by the GetPerfOutputV2 DBus method call.
+// Perf session ID returned by the GetPerfOutputFd DBus method call.
 const uint64_t kFakePerfSssionId = 101;
-// Quipper command line arguments for running perf.
-const std::vector<std::string> kQuipperArgs{
-    "--duration", "4",      "--", "perf", "record", "-a",
-    "-e",         "cycles", "-g", "-c",   "4000037"};
+// Profile collection duration is 4 seconds.
+const base::TimeDelta kProfileDuration = base::Seconds(4);
+// Perf command line arguments.
+const std::vector<std::string> kPerfArgs{"perf",   "record", "-a", "-e",
+                                         "cycles", "-g",     "-c", "4000037"};
 
 // This fakes DebugDaemonClient by serving example perf data when the profiling
 // duration elapses.
@@ -71,8 +72,8 @@
     EXPECT_FALSE(perf_output_file_.IsValid());
   }
 
-  void GetPerfOutput(const std::vector<std::string>& quipper_args,
-                     bool disable_cpu_idle,
+  void GetPerfOutput(base::TimeDelta duration,
+                     const std::vector<std::string>& perf_args,
                      int file_descriptor,
                      chromeos::DBusMethodCallback<uint64_t> callback) override {
     // We will write perf output to this pipe FD. dup() |file_descriptor|
@@ -157,7 +158,7 @@
 // Test getting perf output after profile duration elapses.
 TEST_F(PerfOutputCallTest, GetPerfOutput) {
   perf_output_call_ = std::make_unique<PerfOutputCall>(
-      debug_daemon_client_.get(), kQuipperArgs, false,
+      debug_daemon_client_.get(), kProfileDuration, kPerfArgs,
       base::BindOnce(&PerfOutputCallTest::OnPerfOutputComplete,
                      base::Unretained(this)));
   // Not yet collected.
@@ -177,7 +178,7 @@
 // Test stopping the perf session and get perf output right away.
 TEST_F(PerfOutputCallTest, Stop) {
   perf_output_call_ = std::make_unique<PerfOutputCall>(
-      debug_daemon_client_.get(), kQuipperArgs, false,
+      debug_daemon_client_.get(), kProfileDuration, kPerfArgs,
       base::BindOnce(&PerfOutputCallTest::OnPerfOutputComplete,
                      base::Unretained(this)));
   // Not yet collected.
diff --git a/chrome/browser/metrics/perf/profile_provider_unittest_main.cc b/chrome/browser/metrics/perf/profile_provider_unittest_main.cc
index ce3f5a0..cdc71f4f 100644
--- a/chrome/browser/metrics/perf/profile_provider_unittest_main.cc
+++ b/chrome/browser/metrics/perf/profile_provider_unittest_main.cc
@@ -153,9 +153,10 @@
     std::map<std::string, std::string> field_trial_params;
     // Only "cycles" event is supported.
     field_trial_params.insert(std::make_pair(
-        "PerfCommand::default::0", "-- record -a -e cycles -c 1000003"));
-    field_trial_params.insert(std::make_pair(
-        "PerfCommand::default::1", "-- record -a -e cycles -g -c 4000037"));
+        "PerfCommand::default::0", "50 perf record -a -e cycles -c 1000003"));
+    field_trial_params.insert(
+        std::make_pair("PerfCommand::default::1",
+                       "50 perf record -a -e cycles -g -c 4000037"));
     ASSERT_TRUE(variations::AssociateVariationParams(
         "ChromeOSWideProfilingCollection", "group_name", field_trial_params));
     field_trial_ = base::FieldTrialList::CreateFieldTrial(
diff --git a/chrome/browser/password_manager/password_scripts_fetcher_factory.cc b/chrome/browser/password_manager/password_scripts_fetcher_factory.cc
index 40695e70..dedccf7b 100644
--- a/chrome/browser/password_manager/password_scripts_fetcher_factory.cc
+++ b/chrome/browser/password_manager/password_scripts_fetcher_factory.cc
@@ -4,11 +4,12 @@
 
 #include "chrome/browser/password_manager/password_scripts_fetcher_factory.h"
 
+#include <memory>
+
 #include "base/no_destructor.h"
-#include "chrome/browser/browser_process.h"
+#include "chrome/browser/autofill_assistant/common_dependencies_chrome.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/common/channel_info.h"
 #include "components/autofill_assistant/browser/public/autofill_assistant.h"
 #include "components/autofill_assistant/browser/public/autofill_assistant_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -16,24 +17,10 @@
 #include "components/password_manager/core/browser/password_scripts_fetcher_impl.h"
 #include "components/password_manager/core/browser/saved_passwords_capabilities_fetcher.h"
 #include "components/password_manager/core/common/password_manager_features.h"
-#include "components/variations/service/variations_service.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
 
-namespace {
-
-std::string GetCountryCode() {
-  variations::VariationsService* variations_service =
-      g_browser_process->variations_service();
-  // Use fallback "ZZ" if no country is available.
-  if (!variations_service || variations_service->GetLatestCountry().empty())
-    return "ZZ";
-  return base::ToUpperASCII(variations_service->GetLatestCountry());
-}
-
-}  // namespace
-
 PasswordScriptsFetcherFactory::PasswordScriptsFetcherFactory()
     : BrowserContextKeyedServiceFactory(
           "PasswordScriptsFetcher",
@@ -59,12 +46,10 @@
     content::BrowserContext* browser_context) const {
   if (base::FeatureList::IsEnabled(
           password_manager::features::kPasswordDomainCapabilitiesFetching)) {
-    // TODO(crbug.com/1314010): Replace these dependencies by a |Dependencies|
-    // or |PlatformDependencies| object.
     std::unique_ptr<autofill_assistant::AutofillAssistant> autofill_assistant =
         autofill_assistant::AutofillAssistantFactory::CreateForBrowserContext(
-            browser_context, chrome::GetChannel(), GetCountryCode(),
-            g_browser_process->GetApplicationLocale());
+            browser_context,
+            std::make_unique<autofill_assistant::CommonDependenciesChrome>());
 
     std::unique_ptr<CapabilitiesServiceImpl> service =
         std::make_unique<CapabilitiesServiceImpl>(
diff --git a/chrome/browser/policy/cbcm_invalidations_initializer.cc b/chrome/browser/policy/cbcm_invalidations_initializer.cc
index 22df39d..588dfa4 100644
--- a/chrome/browser/policy/cbcm_invalidations_initializer.cc
+++ b/chrome/browser/policy/cbcm_invalidations_initializer.cc
@@ -71,7 +71,12 @@
     std::move(callback_).Run(true);
   }
 
-  void OnDeviceAccountTokenError(EnrollmentStatus status) override {
+  void OnDeviceAccountTokenFetchError(
+      absl::optional<DeviceManagementStatus> /*dm_status*/) override {
+    std::move(callback_).Run(false);
+  }
+
+  void OnDeviceAccountTokenStoreError() override {
     std::move(callback_).Run(false);
   }
 
diff --git a/chrome/browser/policy/device_account_initializer.cc b/chrome/browser/policy/device_account_initializer.cc
index 12cff831..2133462 100644
--- a/chrome/browser/policy/device_account_initializer.cc
+++ b/chrome/browser/policy/device_account_initializer.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/device_identity/device_oauth2_token_service.h"
 #include "chrome/browser/device_identity/device_oauth2_token_service_factory.h"
-#include "chrome/browser/policy/enrollment_status.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/policy/core/common/cloud/dm_auth.h"
 #include "google_apis/gaia/gaia_auth_util.h"
@@ -27,8 +26,6 @@
 #include "net/http/http_status_code.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
-#include "components/policy/core/common/cloud/dm_auth.h"
-
 namespace em = enterprise_management;
 
 namespace policy {
@@ -59,8 +56,7 @@
     const std::string& auth_code) {
   if (status != DM_STATUS_SUCCESS) {
     handling_request_ = false;
-    delegate_->OnDeviceAccountTokenError(
-        EnrollmentStatus::ForRobotAuthFetchError(status));
+    delegate_->OnDeviceAccountTokenFetchError(status);
     return;
   }
   if (auth_code.empty()) {
@@ -112,8 +108,7 @@
   // response is bad (empty access token returned).
   LOG(ERROR) << "OAuth protocol error while fetching API refresh token.";
   handling_request_ = false;
-  delegate_->OnDeviceAccountTokenError(
-      EnrollmentStatus::ForRobotRefreshFetchError(net::HTTP_BAD_REQUEST));
+  delegate_->OnDeviceAccountTokenFetchError(/*dm_status=*/absl::nullopt);
 }
 
 // GaiaOAuthClient::Delegate network error when fetching refresh token.
@@ -121,8 +116,7 @@
   LOG(ERROR) << "Network error while fetching API refresh token: "
              << response_code;
   handling_request_ = false;
-  delegate_->OnDeviceAccountTokenError(
-      EnrollmentStatus::ForRobotRefreshFetchError(response_code));
+  delegate_->OnDeviceAccountTokenFetchError(/*dm_status=*/absl::nullopt);
 }
 
 void DeviceAccountInitializer::StoreToken() {
@@ -137,8 +131,7 @@
   handling_request_ = false;
   if (!result) {
     LOG(ERROR) << "Failed to store API refresh token.";
-    delegate_->OnDeviceAccountTokenError(EnrollmentStatus::ForStatus(
-        EnrollmentStatus::ROBOT_REFRESH_STORE_FAILED));
+    delegate_->OnDeviceAccountTokenStoreError();
     return;
   }
   delegate_->OnDeviceAccountTokenStored();
diff --git a/chrome/browser/policy/device_account_initializer.h b/chrome/browser/policy/device_account_initializer.h
index 1417490..961cf2d 100644
--- a/chrome/browser/policy/device_account_initializer.h
+++ b/chrome/browser/policy/device_account_initializer.h
@@ -9,17 +9,15 @@
 #include <string>
 
 #include "base/memory/raw_ptr.h"
-#include "chrome/browser/policy/enrollment_status.h"
-
 #include "base/memory/weak_ptr.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace policy {
-class EnrollmentStatus;
 
 // Implements the logic that initializes device account during enrollment.
 //   1. Download the OAuth2 authorization code for device-level API access.
@@ -43,8 +41,13 @@
     // Called when OAuth2 refresh token is successfully stored.
     virtual void OnDeviceAccountTokenStored() = 0;
 
-    // Called when an error happens during token fetching or saving.
-    virtual void OnDeviceAccountTokenError(EnrollmentStatus status) = 0;
+    // Called when an error happens during token fetching. `dm_status` is
+    // nullopt if error happened before requesting device management service.
+    virtual void OnDeviceAccountTokenFetchError(
+        absl::optional<DeviceManagementStatus> dm_status) = 0;
+
+    // Called when an error happens during token saving.
+    virtual void OnDeviceAccountTokenStoreError() = 0;
 
     // Called when an error happens during cloud policy client calls.
     virtual void OnDeviceAccountClientError(DeviceManagementStatus status) = 0;
diff --git a/chrome/browser/policy/enrollment_status.cc b/chrome/browser/policy/enrollment_status.cc
index 4dfa0a9..d1a755d 100644
--- a/chrome/browser/policy/enrollment_status.cc
+++ b/chrome/browser/policy/enrollment_status.cc
@@ -12,7 +12,7 @@
 // static
 EnrollmentStatus EnrollmentStatus::ForStatus(Status status) {
   return CreateEnrollmentStatusWithoutLockError(
-      status, DM_STATUS_SUCCESS, net::HTTP_OK, CloudPolicyStore::STATUS_OK,
+      status, DM_STATUS_SUCCESS, CloudPolicyStore::STATUS_OK,
       CloudPolicyValidatorBase::VALIDATION_OK);
 }
 
@@ -20,39 +20,32 @@
 EnrollmentStatus EnrollmentStatus::ForRegistrationError(
     DeviceManagementStatus client_status) {
   return CreateEnrollmentStatusWithoutLockError(
-      REGISTRATION_FAILED, client_status, net::HTTP_OK,
-      CloudPolicyStore::STATUS_OK, CloudPolicyValidatorBase::VALIDATION_OK);
+      REGISTRATION_FAILED, client_status, CloudPolicyStore::STATUS_OK,
+      CloudPolicyValidatorBase::VALIDATION_OK);
 }
 
 // static
 EnrollmentStatus EnrollmentStatus::ForRobotAuthFetchError(
     DeviceManagementStatus client_status) {
   return CreateEnrollmentStatusWithoutLockError(
-      ROBOT_AUTH_FETCH_FAILED, client_status, net::HTTP_OK,
-      CloudPolicyStore::STATUS_OK, CloudPolicyValidatorBase::VALIDATION_OK);
-}
-
-// static
-EnrollmentStatus EnrollmentStatus::ForRobotRefreshFetchError(int http_status) {
-  return CreateEnrollmentStatusWithoutLockError(
-      ROBOT_REFRESH_FETCH_FAILED, DM_STATUS_SUCCESS, http_status,
-      CloudPolicyStore::STATUS_OK, CloudPolicyValidatorBase::VALIDATION_OK);
+      ROBOT_AUTH_FETCH_FAILED, client_status, CloudPolicyStore::STATUS_OK,
+      CloudPolicyValidatorBase::VALIDATION_OK);
 }
 
 // static
 EnrollmentStatus EnrollmentStatus::ForFetchError(
     DeviceManagementStatus client_status) {
   return CreateEnrollmentStatusWithoutLockError(
-      POLICY_FETCH_FAILED, client_status, net::HTTP_OK,
-      CloudPolicyStore::STATUS_OK, CloudPolicyValidatorBase::VALIDATION_OK);
+      POLICY_FETCH_FAILED, client_status, CloudPolicyStore::STATUS_OK,
+      CloudPolicyValidatorBase::VALIDATION_OK);
 }
 
 // static
 EnrollmentStatus EnrollmentStatus::ForValidationError(
     CloudPolicyValidatorBase::Status validation_status) {
   return CreateEnrollmentStatusWithoutLockError(
-      VALIDATION_FAILED, DM_STATUS_SUCCESS, net::HTTP_OK,
-      CloudPolicyStore::STATUS_OK, validation_status);
+      VALIDATION_FAILED, DM_STATUS_SUCCESS, CloudPolicyStore::STATUS_OK,
+      validation_status);
 }
 
 // static
@@ -60,15 +53,14 @@
     CloudPolicyStore::Status store_error,
     CloudPolicyValidatorBase::Status validation_status) {
   return CreateEnrollmentStatusWithoutLockError(STORE_ERROR, DM_STATUS_SUCCESS,
-                                                net::HTTP_OK, store_error,
-                                                validation_status);
+                                                store_error, validation_status);
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 // static
 EnrollmentStatus EnrollmentStatus::ForLockError(
     ash::InstallAttributes::LockResult lock_status) {
-  return EnrollmentStatus(LOCK_ERROR, DM_STATUS_SUCCESS, net::HTTP_OK,
+  return EnrollmentStatus(LOCK_ERROR, DM_STATUS_SUCCESS,
                           CloudPolicyStore::STATUS_OK,
                           CloudPolicyValidatorBase::VALIDATION_OK, lock_status);
 }
@@ -76,13 +68,11 @@
 EnrollmentStatus::EnrollmentStatus(
     EnrollmentStatus::Status status,
     DeviceManagementStatus client_status,
-    int http_status,
     CloudPolicyStore::Status store_status,
     CloudPolicyValidatorBase::Status validation_status,
     ash::InstallAttributes::LockResult lock_status)
     : status_(status),
       client_status_(client_status),
-      http_status_(http_status),
       store_status_(store_status),
       validation_status_(validation_status),
       lock_status_(lock_status) {}
@@ -90,12 +80,10 @@
 EnrollmentStatus::EnrollmentStatus(
     EnrollmentStatus::Status status,
     DeviceManagementStatus client_status,
-    int http_status,
     CloudPolicyStore::Status store_status,
     CloudPolicyValidatorBase::Status validation_status)
     : status_(status),
       client_status_(client_status),
-      http_status_(http_status),
       store_status_(store_status),
       validation_status_(validation_status) {}
 #endif
@@ -104,15 +92,14 @@
 EnrollmentStatus EnrollmentStatus::CreateEnrollmentStatusWithoutLockError(
     Status status,
     DeviceManagementStatus client_status,
-    int http_status,
     CloudPolicyStore::Status store_status,
     CloudPolicyValidatorBase::Status validation_status) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  return EnrollmentStatus(status, client_status, http_status, store_status,
+  return EnrollmentStatus(status, client_status, store_status,
                           validation_status,
                           ash::InstallAttributes::LOCK_SUCCESS);
 #else
-  return EnrollmentStatus(status, client_status, http_status, store_status,
+  return EnrollmentStatus(status, client_status, store_status,
                           validation_status);
 #endif
 }
diff --git a/chrome/browser/policy/enrollment_status.h b/chrome/browser/policy/enrollment_status.h
index 88c093e..08db653 100644
--- a/chrome/browser/policy/enrollment_status.h
+++ b/chrome/browser/policy/enrollment_status.h
@@ -69,7 +69,6 @@
   static EnrollmentStatus ForFetchError(DeviceManagementStatus client_status);
   static EnrollmentStatus ForRobotAuthFetchError(
       DeviceManagementStatus client_status);
-  static EnrollmentStatus ForRobotRefreshFetchError(int http_status);
   static EnrollmentStatus ForValidationError(
       CloudPolicyValidatorBase::Status validation_status);
   static EnrollmentStatus ForStoreError(
@@ -82,7 +81,6 @@
 
   Status status() const { return status_; }
   DeviceManagementStatus client_status() const { return client_status_; }
-  int http_status() const { return http_status_; }
   CloudPolicyStore::Status store_status() const { return store_status_; }
   CloudPolicyValidatorBase::Status validation_status() const {
     return validation_status_;
@@ -97,14 +95,12 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   EnrollmentStatus(Status status,
                    DeviceManagementStatus client_status,
-                   int http_status,
                    CloudPolicyStore::Status store_status,
                    CloudPolicyValidatorBase::Status validation_status,
                    ash::InstallAttributes::LockResult lock_status);
 #else
   EnrollmentStatus(Status status,
                    DeviceManagementStatus client_status,
-                   int http_status,
                    CloudPolicyStore::Status store_status,
                    CloudPolicyValidatorBase::Status validation_status);
 #endif
@@ -114,13 +110,11 @@
   static EnrollmentStatus CreateEnrollmentStatusWithoutLockError(
       Status status,
       DeviceManagementStatus client_status,
-      int http_status,
       CloudPolicyStore::Status store_status,
       CloudPolicyValidatorBase::Status validation_status);
 
   Status status_;
   DeviceManagementStatus client_status_;
-  int http_status_;
   CloudPolicyStore::Status store_status_;
   CloudPolicyValidatorBase::Status validation_status_;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
index 5482de9e79..0f16a0c8 100644
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
@@ -173,8 +173,6 @@
     status_->completion_time = base::TimeTicks::Now();
   }
 
-  forwarding_client_->OnReceiveResponse(std::move(resource_response_),
-                                        mojo::ScopedDataPipeConsumerHandle());
   RunEventQueue();
 }
 
@@ -255,8 +253,7 @@
   if (estimated_length_ > 0)
     body_content_.reserve(estimated_length_);
 
-  if (body)
-    OnStartLoadingResponseBody(std::move(body));
+  OnStartLoadingResponseBody(std::move(body));
 }
 
 void StreamingSearchPrefetchURLLoader::OnReceiveRedirect(
@@ -304,12 +301,7 @@
 
 void StreamingSearchPrefetchURLLoader::OnStartLoadingResponseBody(
     mojo::ScopedDataPipeConsumerHandle body) {
-  if (forwarding_client_) {
-    DCHECK(!streaming_prefetch_request_);
-    forwarding_client_->OnStartLoadingResponseBody(std::move(body));
-    return;
-  }
-
+  DCHECK(!forwarding_client_);
   serving_from_data_ = true;
 
   pipe_drainer_ =
@@ -368,7 +360,8 @@
       base::BindRepeating(&StreamingSearchPrefetchURLLoader::OnHandleReady,
                           weak_factory_.GetWeakPtr()));
 
-  forwarding_client_->OnStartLoadingResponseBody(std::move(consumer_handle));
+  forwarding_client_->OnReceiveResponse(std::move(resource_response_),
+                                        std::move(consumer_handle));
 
   PushData();
 }
diff --git a/chrome/browser/prerender/omnibox_prerender_browsertest.cc b/chrome/browser/prerender/omnibox_prerender_browsertest.cc
index 77bb485c..7d8b03c 100644
--- a/chrome/browser/prerender/omnibox_prerender_browsertest.cc
+++ b/chrome/browser/prerender/omnibox_prerender_browsertest.cc
@@ -252,10 +252,10 @@
 #endif
 }
 
-class PrerenderOmniboxSearchSuggestionBrowserTestBase
+class PrerenderOmniboxSearchSuggestionBrowserTest
     : public OmniboxPrerenderBrowserTest {
  public:
-  PrerenderOmniboxSearchSuggestionBrowserTestBase() {
+  PrerenderOmniboxSearchSuggestionBrowserTest() {
     feature_list_.InitWithFeatures(
         {features::kSupportSearchSuggestionForPrerender2}, {});
   }
@@ -274,24 +274,12 @@
     search_engine_server_.ServeFilesFromDirectory(
         base::PathService::CheckedGet(chrome::DIR_TEST_DATA));
     ASSERT_TRUE(search_engine_server_.Start());
+    SetUrlTemplate();
+  }
 
-    TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(
-        chrome_test_utils::GetProfile(this));
-    ASSERT_TRUE(model);
-    search_test_utils::WaitForTemplateURLServiceToLoad(model);
-    ASSERT_TRUE(model->loaded());
-    TemplateURLData data;
-    data.SetShortName(kSearchDomain16);
-    data.SetKeyword(data.short_name());
-    data.SetURL(
-        search_engine_server_
-            .GetURL(
-                kSearchDomain,
-                "/title1.html?q={searchTerms}&{google:prefetchSource}type=test")
-            .spec());
-    TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
-    ASSERT_TRUE(template_url);
-    model->SetUserSelectedDefaultSearchProvider(template_url);
+  void SetNewUrlTemplate(const std::string& prerender_page_target) {
+    prerender_page_target_ = prerender_page_target;
+    SetUrlTemplate();
   }
 
  protected:
@@ -306,7 +294,7 @@
 
   GURL GetSearchSuggestionUrl(const std::string& search_terms,
                               bool is_prerender) {
-    std::string url_template = "/title1.html?q=$1$2&type=test";
+    std::string url_template = prerender_page_target_ + "?q=$1$2&type=test";
     return search_engine_server_.GetURL(
         kSearchDomain,
         base::ReplaceStringPlaceholders(
@@ -377,17 +365,38 @@
     return match;
   }
 
+  void SetUrlTemplate() {
+    TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(
+        chrome_test_utils::GetProfile(this));
+    ASSERT_TRUE(model);
+    search_test_utils::WaitForTemplateURLServiceToLoad(model);
+    ASSERT_TRUE(model->loaded());
+    TemplateURLData data;
+    data.SetShortName(kSearchDomain16);
+    data.SetKeyword(data.short_name());
+    data.SetURL(
+        search_engine_server_
+            .GetURL(kSearchDomain,
+                    prerender_page_target_ +
+                        "?q={searchTerms}&{google:prefetchSource}type=test")
+            .spec());
+    TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
+    ASSERT_TRUE(template_url);
+    model->SetUserSelectedDefaultSearchProvider(template_url);
+  }
+
   constexpr static char kSearchDomain[] = "a.test";
   constexpr static char16_t kSearchDomain16[] = u"a.test";
-  base::test::ScopedFeatureList feature_list_;
   PrerenderManager* prerender_manager_;
   net::test_server::EmbeddedTestServer search_engine_server_{
       net::test_server::EmbeddedTestServer::TYPE_HTTPS};
+  std::string prerender_page_target_ = "/title1.html";
+  base::test::ScopedFeatureList feature_list_;
 };
 
 class PrerenderOmniboxSearchSuggestionReloadBrowserTest
     : public testing::WithParamInterface<bool>,
-      public PrerenderOmniboxSearchSuggestionBrowserTestBase {
+      public PrerenderOmniboxSearchSuggestionBrowserTest {
  public:
   PrerenderOmniboxSearchSuggestionReloadBrowserTest() {
     // Disable BFCache, to test the HTTP Cache path.
@@ -448,7 +457,7 @@
 }
 
 class PrerenderOmniboxSearchSuggestionExpiryBrowserTest
-    : public PrerenderOmniboxSearchSuggestionBrowserTestBase {
+    : public PrerenderOmniboxSearchSuggestionBrowserTest {
  public:
   PrerenderOmniboxSearchSuggestionExpiryBrowserTest() {
     feature_list_.InitWithFeaturesAndParameters(
@@ -576,4 +585,53 @@
       internal::kHistogramPrerenderPredictionStatusDefaultSearchEngine, 2);
 }
 
+// Verifies that prerendering functions in document are properly exposed when
+// triggered by search suggestion.
+IN_PROC_BROWSER_TEST_F(
+    PrerenderOmniboxSearchSuggestionBrowserTest,
+    PrerenderFunctionsProperlyExportedWhenInitiatedByOmnibox) {
+  const GURL kInitialUrl = embedded_test_server()->GetURL("/empty.html");
+  ASSERT_TRUE(GetActiveWebContents());
+  ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), kInitialUrl));
+  InitializePrerenderManager();
+  EXPECT_EQ(true,
+            EvalJs(GetActiveWebContents(), "document.prerendering === false"));
+  EXPECT_EQ(
+      0,
+      EvalJs(GetActiveWebContents(),
+             "performance.getEntriesByType('navigation')[0].activationStart"));
+  EXPECT_EQ(true, EvalJs(GetActiveWebContents(),
+                         "'onprerenderingchange' in document"));
+
+  SetNewUrlTemplate("/prerender/onprerendering_check.html");
+  GURL kPrerenderingUrl =
+      GetSearchSuggestionUrl("prerender222", /*is_prerender=*/true);
+  PrerenderQuery("prerender222", kPrerenderingUrl);
+
+  int host_id = prerender_helper().GetHostForUrl(kPrerenderingUrl);
+  content::RenderFrameHost* prerender_frame_host =
+      prerender_helper().GetPrerenderedMainFrameHost(host_id);
+  prerender_helper().WaitForPrerenderLoadCompletion(host_id);
+  EXPECT_EQ(true,
+            EvalJs(prerender_frame_host, "document.prerendering === true"));
+  EXPECT_EQ(
+      0,
+      EvalJs(prerender_frame_host,
+             "performance.getEntriesByType('navigation')[0].activationStart"));
+  EXPECT_EQ(true,
+            EvalJs(prerender_frame_host, "'onprerenderingchange' in document"));
+
+  NavigateToPrerenderedResult(kPrerenderingUrl);
+
+  EXPECT_EQ(true,
+            EvalJs(prerender_frame_host, "document.prerendering === false"));
+  EXPECT_LT(
+      0.0,
+      EvalJs(prerender_frame_host,
+             "performance.getEntriesByType('navigation')[0].activationStart")
+          .ExtractDouble());
+  EXPECT_EQ(true, EvalJs(prerender_frame_host,
+                         "onprerenderingchange_observed_promise"));
+}
+
 }  // namespace
diff --git a/chrome/browser/resources/chromeos/login/components/display_manager_types.js b/chrome/browser/resources/chromeos/login/components/display_manager_types.js
index 3e9a83a5..9384843a 100644
--- a/chrome/browser/resources/chromeos/login/components/display_manager_types.js
+++ b/chrome/browser/resources/chromeos/login/components/display_manager_types.js
@@ -55,4 +55,3 @@
  * Must be kept in sync with webui_accelerator_mapping.cc.
  */
 /* #export */ const ACCELERATOR_CANCEL = 'cancel';
-/* #export */ const ACCELERATOR_VERSION = 'version';
diff --git a/chrome/browser/resources/chromeos/login/cr_ui.js b/chrome/browser/resources/chromeos/login/cr_ui.js
index 1a3f310..2e0316d 100644
--- a/chrome/browser/resources/chromeos/login/cr_ui.js
+++ b/chrome/browser/resources/chromeos/login/cr_ui.js
@@ -85,11 +85,10 @@
     }
 
     /**
-     * Updates version label visibility.
-     * @param {boolean} show True if version label should be visible.
+     * Toggles system info visibility.
      */
-    static showVersion(show) {
-      Oobe.getInstance().showVersion(show);
+    static toggleSystemInfo() {
+      Oobe.getInstance().toggleSystemInfo();
     }
 
     /**
diff --git a/chrome/browser/resources/chromeos/login/display_manager.js b/chrome/browser/resources/chromeos/login/display_manager.js
index fdf23d1..ba6253a 100644
--- a/chrome/browser/resources/chromeos/login/display_manager.js
+++ b/chrome/browser/resources/chromeos/login/display_manager.js
@@ -11,7 +11,7 @@
 // #import {loadTimeData} from './i18n_setup.js';
 // #import {OobeTypes} from './components/oobe_types.m.js';
 
- // #import {DISPLAY_TYPE, ACCELERATOR_CANCEL, ACCELERATOR_VERSION, SCREEN_DEVICE_DISABLED, OOBE_UI_STATE, SCREEN_WELCOME } from './components/display_manager_types.m.js';
+ // #import {DISPLAY_TYPE, ACCELERATOR_CANCEL, SCREEN_DEVICE_DISABLED, OOBE_UI_STATE, SCREEN_WELCOME } from './components/display_manager_types.m.js';
 // #import {MultiTapDetector} from './multi_tap_detector.m.js';
 // #import {keyboard} from './keyboard_utils.m.js'
 
@@ -84,12 +84,6 @@
       this.currentStep_ = 0;
 
       /**
-       * Whether version label can be toggled by ACCELERATOR_VERSION.
-       * @type {boolean}
-       */
-      this.allowToggleVersion_ = false;
-
-      /**
        * Whether keyboard navigation flow is enforced.
        * @type {boolean}
        */
@@ -224,13 +218,10 @@
     }
 
     /**
-     * Shows/hides version labels.
-     * @param {boolean} show Whether labels should be visible by default. If
-     *     false, visibility can be toggled by ACCELERATOR_VERSION.
+     * Toggles system info visibility.
      */
-    showVersion(show) {
-      $('version-labels').hidden = !show;
-      this.allowToggleVersion_ = !show;
+    toggleSystemInfo() {
+      $('version-labels').hidden = !$('version-labels').hidden;
     }
 
     /**
@@ -258,10 +249,6 @@
         if (this.currentScreen && this.currentScreen.cancel) {
           this.currentScreen.cancel();
         }
-      } else if (name == ACCELERATOR_VERSION) {
-        if (this.allowToggleVersion_) {
-          $('version-labels').hidden = !$('version-labels').hidden;
-        }
       }
     }
 
diff --git a/chrome/browser/segmentation_platform/segmentation_platform_config.cc b/chrome/browser/segmentation_platform/segmentation_platform_config.cc
index 3bd58f6..b9ee3aa 100644
--- a/chrome/browser/segmentation_platform/segmentation_platform_config.cc
+++ b/chrome/browser/segmentation_platform/segmentation_platform_config.cc
@@ -10,6 +10,7 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
 #include "chrome/browser/segmentation_platform/default_model/low_user_engagement_model.h"
 #include "components/optimization_guide/proto/models.pb.h"
 #include "components/segmentation_platform/public/config.h"
@@ -240,4 +241,26 @@
   return nullptr;
 }
 
+FieldTrialRegisterImpl::FieldTrialRegisterImpl() = default;
+FieldTrialRegisterImpl::~FieldTrialRegisterImpl() = default;
+
+void FieldTrialRegisterImpl::RegisterFieldTrial(base::StringPiece trial_name,
+                                                base::StringPiece group_name) {
+  // The register method is called early in startup once the platform is
+  // initialized. So, in most cases the client will register the field trial
+  // before uploading the first UMA log of the current session. We do not want
+  // to annotate logs from the previous session. (These comes in two types:
+  // histograms persisted from the previous session or stability information
+  // about the previous session.) Groups are not stable across sessions; we
+  // don't know if the current segmentation applies to the previous session.
+  // Incidentally, the platform records metrics to track the movement between
+  // groups.
+  // TODO(ssid): Move to a MetricsProvider approach to fill the groups so we are
+  // able to track how often we miss the first session log due to delays in
+  // platform initialization.
+  ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
+      trial_name, group_name,
+      variations::SyntheticTrialAnnotationMode::kCurrentLog);
+}
+
 }  // namespace segmentation_platform
diff --git a/chrome/browser/segmentation_platform/segmentation_platform_config.h b/chrome/browser/segmentation_platform/segmentation_platform_config.h
index b2f7cc7..1d800487 100644
--- a/chrome/browser/segmentation_platform/segmentation_platform_config.h
+++ b/chrome/browser/segmentation_platform/segmentation_platform_config.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/public/field_trial_register.h"
 
 namespace segmentation_platform {
 struct Config;
@@ -21,6 +22,20 @@
 std::unique_ptr<ModelProvider> GetSegmentationDefaultModelProvider(
     optimization_guide::proto::OptimizationTarget target);
 
+// Implementation of FieldTrialRegister that uses synthetic field trials to
+// record segmentation groups.
+class FieldTrialRegisterImpl : public FieldTrialRegister {
+ public:
+  FieldTrialRegisterImpl();
+  ~FieldTrialRegisterImpl() override;
+  FieldTrialRegisterImpl(const FieldTrialRegisterImpl&) = delete;
+  FieldTrialRegisterImpl& operator=(const FieldTrialRegisterImpl&) = delete;
+
+  // FieldTrialRegister:
+  void RegisterFieldTrial(base::StringPiece trial_name,
+                          base::StringPiece group_name) override;
+};
+
 }  // namespace segmentation_platform
 
 #endif  // CHROME_BROWSER_SEGMENTATION_PLATFORM_SEGMENTATION_PLATFORM_CONFIG_H_
diff --git a/chrome/browser/segmentation_platform/segmentation_platform_service_factory.cc b/chrome/browser/segmentation_platform/segmentation_platform_service_factory.cc
index 2cc5b41c..174e947 100644
--- a/chrome/browser/segmentation_platform/segmentation_platform_service_factory.cc
+++ b/chrome/browser/segmentation_platform/segmentation_platform_service_factory.cc
@@ -89,6 +89,7 @@
   params->profile_prefs = profile->GetPrefs();
   params->local_state = g_browser_process->local_state();
   params->configs = GetSegmentationPlatformConfig();
+  params->field_trial_register = std::make_unique<FieldTrialRegisterImpl>();
 
   auto* service = new SegmentationPlatformServiceImpl(std::move(params));
 
diff --git a/chrome/browser/sharing/sharing_dialog_data.h b/chrome/browser/sharing/sharing_dialog_data.h
index 8091f16..74c8add 100644
--- a/chrome/browser/sharing/sharing_dialog_data.h
+++ b/chrome/browser/sharing/sharing_dialog_data.h
@@ -9,7 +9,7 @@
 #include <string>
 #include <vector>
 
-#include "base/callback_forward.h"
+#include "base/callback.h"
 #include "chrome/browser/sharing/sharing_app.h"
 #include "chrome/browser/sharing/sharing_metrics.h"
 #include "components/sync_device_info/device_info.h"
diff --git a/chrome/browser/signin/signin_global_error.cc b/chrome/browser/signin/signin_global_error.cc
deleted file mode 100644
index 9c48f86..0000000
--- a/chrome/browser/signin/signin_global_error.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/signin/signin_global_error.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/identity_manager_factory.h"
-#include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/chrome_pages.h"
-#include "chrome/browser/ui/global_error/global_error_service.h"
-#include "chrome/browser/ui/global_error/global_error_service_factory.h"
-#include "chrome/browser/ui/singleton_tabs.h"
-#include "chrome/browser/ui/webui/signin/login_ui_service.h"
-#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/signin/public/base/signin_metrics.h"
-#include "components/signin/public/identity_manager/identity_manager.h"
-#include "net/base/url_util.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if !BUILDFLAG(IS_ANDROID)
-#include "chrome/browser/signin/signin_promo.h"
-#endif
-
-SigninGlobalError::SigninGlobalError(
-    SigninErrorController* error_controller,
-    Profile* profile)
-    : profile_(profile),
-      error_controller_(error_controller) {
-  error_controller_->AddObserver(this);
-}
-
-SigninGlobalError::~SigninGlobalError() {
-  DCHECK(!error_controller_)
-      << "SigninGlobalError::Shutdown() was not called";
-}
-
-bool SigninGlobalError::HasError() {
-  return HasMenuItem();
-}
-
-void SigninGlobalError::Shutdown() {
-  error_controller_->RemoveObserver(this);
-  error_controller_ = nullptr;
-}
-
-bool SigninGlobalError::HasMenuItem() {
-  return error_controller_->HasError();
-}
-
-int SigninGlobalError::MenuItemCommandID() {
-  return IDC_SHOW_SIGNIN_ERROR;
-}
-
-std::u16string SigninGlobalError::MenuItemLabel() {
-  // Notify the user if there's an auth error the user should know about.
-  if (error_controller_->HasError())
-    return l10n_util::GetStringUTF16(IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM);
-  return std::u16string();
-}
-
-void SigninGlobalError::ExecuteMenuItem(Browser* browser) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (error_controller_->auth_error().state() !=
-      GoogleServiceAuthError::NONE) {
-    DVLOG(1) << "Signing out the user to fix a sync error.";
-    // TODO(beng): seems like this could just call chrome::AttemptUserExit().
-    chrome::ExecuteCommand(browser, IDC_EXIT);
-    return;
-  }
-#endif
-
-  // Global errors don't show up in the wrench menu on mobile.
-#if !BUILDFLAG(IS_ANDROID)
-  LoginUIService* login_ui = LoginUIServiceFactory::GetForProfile(profile_);
-  if (login_ui->current_login_ui()) {
-    login_ui->current_login_ui()->FocusUI();
-    return;
-  }
-
-  browser->window()->ShowAvatarBubbleFromAvatarButton(
-      BrowserWindow::AVATAR_BUBBLE_MODE_REAUTH,
-      signin_metrics::AccessPoint::ACCESS_POINT_MENU, false);
-#endif
-}
-
-bool SigninGlobalError::HasBubbleView() {
-  return !GetBubbleViewMessages().empty();
-}
-
-std::u16string SigninGlobalError::GetBubbleViewTitle() {
-  return l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE);
-}
-
-std::vector<std::u16string> SigninGlobalError::GetBubbleViewMessages() {
-  std::vector<std::u16string> messages;
-
-  // If the user isn't signed in, no need to display an error bubble.
-  auto* identity_manager =
-      IdentityManagerFactory::GetForProfileIfExists(profile_);
-  if (identity_manager &&
-      !identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)) {
-    return messages;
-  }
-
-  if (!error_controller_->HasError())
-    return messages;
-
-  switch (error_controller_->auth_error().state()) {
-    // TODO(rogerta): use account id in error messages.
-
-    // User credentials are invalid (bad acct, etc).
-    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
-    case GoogleServiceAuthError::SERVICE_ERROR:
-      messages.push_back(l10n_util::GetStringUTF16(
-          IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE));
-      break;
-
-    // Sync service is not available for this account's domain.
-    case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
-      messages.push_back(l10n_util::GetStringUTF16(
-          IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE));
-      break;
-
-    // Generic message for "other" errors.
-    default:
-      messages.push_back(l10n_util::GetStringUTF16(
-          IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE));
-  }
-  return messages;
-}
-
-std::u16string SigninGlobalError::GetBubbleViewAcceptButtonLabel() {
-  // If the auth service is unavailable, don't give the user the option to try
-  // signing in again.
-  if (error_controller_->auth_error().state() ==
-      GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
-    return l10n_util::GetStringUTF16(
-        IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_ACCEPT);
-  } else {
-    return l10n_util::GetStringUTF16(IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT);
-  }
-}
-
-std::u16string SigninGlobalError::GetBubbleViewCancelButtonLabel() {
-  return std::u16string();
-}
-
-void SigninGlobalError::OnBubbleViewDidClose(Browser* browser) {
-}
-
-void SigninGlobalError::BubbleViewAcceptButtonPressed(Browser* browser) {
-  ExecuteMenuItem(browser);
-}
-
-void SigninGlobalError::BubbleViewCancelButtonPressed(Browser* browser) {
-  NOTREACHED();
-}
-
-void SigninGlobalError::OnErrorChanged() {
-  GlobalErrorServiceFactory::GetForProfile(profile_)->NotifyErrorsChanged();
-}
diff --git a/chrome/browser/signin/signin_global_error.h b/chrome/browser/signin/signin_global_error.h
deleted file mode 100644
index 50e110e..0000000
--- a/chrome/browser/signin/signin_global_error.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SIGNIN_SIGNIN_GLOBAL_ERROR_H_
-#define CHROME_BROWSER_SIGNIN_SIGNIN_GLOBAL_ERROR_H_
-
-#include <set>
-#include "base/gtest_prod_util.h"
-#include "base/memory/raw_ptr.h"
-#include "chrome/browser/ui/global_error/global_error.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/browser/signin_error_controller.h"
-
-class Profile;
-
-// Shows auth errors on the wrench menu using a bubble view and a menu item.
-class SigninGlobalError : public GlobalErrorWithStandardBubble,
-                          public SigninErrorController::Observer,
-                          public KeyedService {
- public:
-  SigninGlobalError(SigninErrorController* error_controller,
-                    Profile* profile);
-
-  SigninGlobalError(const SigninGlobalError&) = delete;
-  SigninGlobalError& operator=(const SigninGlobalError&) = delete;
-
-  ~SigninGlobalError() override;
-
-  // Returns true if there is an authentication error.
-  bool HasError();
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(SigninGlobalErrorTest, Basic);
-  FRIEND_TEST_ALL_PREFIXES(SigninGlobalErrorTest, AuthStatusEnumerateAllErrors);
-
-  // KeyedService:
-  void Shutdown() override;
-
-  // GlobalErrorWithStandardBubble:
-  bool HasMenuItem() override;
-  int MenuItemCommandID() override;
-  std::u16string MenuItemLabel() override;
-  void ExecuteMenuItem(Browser* browser) override;
-  bool HasBubbleView() override;
-  std::u16string GetBubbleViewTitle() override;
-  std::vector<std::u16string> GetBubbleViewMessages() override;
-  std::u16string GetBubbleViewAcceptButtonLabel() override;
-  std::u16string GetBubbleViewCancelButtonLabel() override;
-  void OnBubbleViewDidClose(Browser* browser) override;
-  void BubbleViewAcceptButtonPressed(Browser* browser) override;
-  void BubbleViewCancelButtonPressed(Browser* browser) override;
-
-  // SigninErrorController::Observer:
-  void OnErrorChanged() override;
-
-  // The Profile this service belongs to.
-  raw_ptr<Profile> profile_;
-
-  // The SigninErrorController that provides auth status.
-  raw_ptr<SigninErrorController> error_controller_;
-};
-
-#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_GLOBAL_ERROR_H_
diff --git a/chrome/browser/signin/signin_global_error_factory.cc b/chrome/browser/signin/signin_global_error_factory.cc
deleted file mode 100644
index 304d6a5..0000000
--- a/chrome/browser/signin/signin_global_error_factory.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/signin/signin_global_error_factory.h"
-
-#include "build/chromeos_buildflags.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/signin_error_controller_factory.h"
-#include "chrome/browser/signin/signin_global_error.h"
-#include "chrome/browser/ui/global_error/global_error_service_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-
-SigninGlobalErrorFactory::SigninGlobalErrorFactory()
-    : BrowserContextKeyedServiceFactory(
-        "SigninGlobalError",
-        BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(SigninErrorControllerFactory::GetInstance());
-  DependsOn(GlobalErrorServiceFactory::GetInstance());
-}
-
-SigninGlobalErrorFactory::~SigninGlobalErrorFactory() {}
-
-// static
-SigninGlobalError* SigninGlobalErrorFactory::GetForProfile(
-    Profile* profile) {
-  return static_cast<SigninGlobalError*>(
-      GetInstance()->GetServiceForBrowserContext(profile, true));
-}
-
-// static
-SigninGlobalErrorFactory* SigninGlobalErrorFactory::GetInstance() {
-  return base::Singleton<SigninGlobalErrorFactory>::get();
-}
-
-KeyedService* SigninGlobalErrorFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  return nullptr;
-#endif
-
-  Profile* profile = static_cast<Profile*>(context);
-  return new SigninGlobalError(
-      SigninErrorControllerFactory::GetForProfile(profile), profile);
-}
diff --git a/chrome/browser/signin/signin_global_error_factory.h b/chrome/browser/signin/signin_global_error_factory.h
deleted file mode 100644
index d13b4f6d..0000000
--- a/chrome/browser/signin/signin_global_error_factory.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SIGNIN_SIGNIN_GLOBAL_ERROR_FACTORY_H_
-#define CHROME_BROWSER_SIGNIN_SIGNIN_GLOBAL_ERROR_FACTORY_H_
-
-#include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-class SigninGlobalError;
-class Profile;
-
-// Singleton that owns all SigninGlobalErrors and associates them with
-// Profiles. Listens for the Profile's destruction notification and cleans up
-// the associated SigninGlobalError.
-class SigninGlobalErrorFactory : public BrowserContextKeyedServiceFactory {
- public:
-  // Returns the instance of SigninGlobalError associated with this
-  // profile, creating one if none exists. In Ash, this will return NULL.
-  static SigninGlobalError* GetForProfile(Profile* profile);
-
-  // Returns an instance of the SigninGlobalErrorFactory singleton.
-  static SigninGlobalErrorFactory* GetInstance();
-
-  SigninGlobalErrorFactory(const SigninGlobalErrorFactory&) = delete;
-  SigninGlobalErrorFactory& operator=(const SigninGlobalErrorFactory&) = delete;
-
- private:
-  friend struct base::DefaultSingletonTraits<SigninGlobalErrorFactory>;
-
-  SigninGlobalErrorFactory();
-  ~SigninGlobalErrorFactory() override;
-
-  // BrowserContextKeyedServiceFactory:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
-};
-
-#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_GLOBAL_ERROR_FACTORY_H_
diff --git a/chrome/browser/signin/signin_global_error_unittest.cc b/chrome/browser/signin/signin_global_error_unittest.cc
deleted file mode 100644
index 73428ef7..0000000
--- a/chrome/browser/signin/signin_global_error_unittest.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/signin/signin_global_error.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <string>
-
-#include "base/bind.h"
-#include "base/memory/raw_ptr.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "chrome/browser/profiles/profile_attributes_entry.h"
-#include "chrome/browser/profiles/profile_attributes_storage.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/profiles/profile_metrics.h"
-#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
-#include "chrome/browser/signin/signin_error_controller_factory.h"
-#include "chrome/browser/signin/signin_global_error_factory.h"
-#include "chrome/browser/ui/global_error/global_error_service.h"
-#include "chrome/browser/ui/global_error/global_error_service_factory.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "chrome/test/base/testing_profile.h"
-#include "chrome/test/base/testing_profile_manager.h"
-#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/signin_error_controller.h"
-#include "components/signin/public/identity_manager/identity_test_environment.h"
-#include "components/signin/public/identity_manager/identity_test_utils.h"
-#include "components/sync_preferences/pref_service_syncable.h"
-#include "content/public/test/browser_task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-static const char kTestEmail[] = "testuser@test.com";
-static const char16_t kTestEmail16[] = u"testuser@test.com";
-
-class SigninGlobalErrorTest : public testing::Test {
- public:
-  SigninGlobalErrorTest() :
-      profile_manager_(TestingBrowserProcess::GetGlobal()) {}
-
-  void SetUp() override {
-    ASSERT_TRUE(profile_manager_.SetUp());
-
-    // Create a signed-in profile.
-    TestingProfile::TestingFactories testing_factories =
-        IdentityTestEnvironmentProfileAdaptor::
-            GetIdentityTestEnvironmentFactories();
-
-    profile_ = profile_manager_.CreateTestingProfile(
-        "Person 1", std::unique_ptr<sync_preferences::PrefServiceSyncable>(),
-        u"Person 1", 0, std::move(testing_factories));
-
-    identity_test_env_profile_adaptor_ =
-        std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile());
-
-    AccountInfo account_info =
-        identity_test_env_profile_adaptor_->identity_test_env()
-            ->MakePrimaryAccountAvailable(kTestEmail,
-                                          signin::ConsentLevel::kSync);
-    ProfileAttributesEntry* entry =
-        profile_manager_.profile_attributes_storage()
-            ->GetProfileAttributesWithPath(profile()->GetPath());
-    ASSERT_NE(entry, nullptr);
-
-    entry->SetAuthInfo(account_info.gaia, kTestEmail16,
-                       /*is_consented_primary_account=*/true);
-
-    global_error_ = SigninGlobalErrorFactory::GetForProfile(profile());
-    error_controller_ = SigninErrorControllerFactory::GetForProfile(profile());
-  }
-
-  TestingProfile* profile() { return profile_; }
-  TestingProfileManager* testing_profile_manager() {
-    return &profile_manager_;
-  }
-
-  SigninGlobalError* global_error() { return global_error_; }
-  SigninErrorController* error_controller() { return error_controller_; }
-
-  void SetAuthError(GoogleServiceAuthError::State state) {
-    signin::IdentityTestEnvironment* identity_test_env =
-        identity_test_env_profile_adaptor_->identity_test_env();
-    CoreAccountId primary_account_id =
-        identity_test_env->identity_manager()->GetPrimaryAccountId(
-            signin::ConsentLevel::kSync);
-
-    signin::UpdatePersistentErrorOfRefreshTokenForAccount(
-        identity_test_env->identity_manager(), primary_account_id,
-        GoogleServiceAuthError(state));
-  }
-
- private:
-  content::BrowserTaskEnvironment task_environment_;
-  TestingProfileManager profile_manager_;
-  raw_ptr<TestingProfile> profile_;
-
-  std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
-      identity_test_env_profile_adaptor_;
-
-  raw_ptr<SigninGlobalError> global_error_;
-  raw_ptr<SigninErrorController> error_controller_;
-};
-
-TEST_F(SigninGlobalErrorTest, Basic) {
-  ASSERT_FALSE(global_error()->HasMenuItem());
-
-  SetAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-  EXPECT_TRUE(global_error()->HasMenuItem());
-
-  SetAuthError(GoogleServiceAuthError::NONE);
-  EXPECT_FALSE(global_error()->HasMenuItem());
-}
-
-// Verify that SigninGlobalError ignores certain errors.
-TEST_F(SigninGlobalErrorTest, AuthStatusEnumerateAllErrors) {
-  typedef struct {
-    GoogleServiceAuthError::State error_state;
-    bool is_error;
-  } ErrorTableEntry;
-
-  ErrorTableEntry table[] = {
-      {GoogleServiceAuthError::NONE, false},
-      {GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, true},
-      {GoogleServiceAuthError::USER_NOT_SIGNED_UP, true},
-      {GoogleServiceAuthError::CONNECTION_FAILED, false},
-      {GoogleServiceAuthError::SERVICE_UNAVAILABLE, false},
-      {GoogleServiceAuthError::REQUEST_CANCELED, false},
-      {GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE, true},
-      {GoogleServiceAuthError::SERVICE_ERROR, true},
-  };
-  static_assert(
-      std::size(table) == GoogleServiceAuthError::NUM_STATES -
-                              GoogleServiceAuthError::kDeprecatedStateCount,
-      "table size should match number of auth error types");
-
-  // Mark the profile with an active timestamp so profile_metrics logs it.
-  testing_profile_manager()->UpdateLastUser(profile());
-
-  for (ErrorTableEntry entry : table) {
-    SetAuthError(GoogleServiceAuthError::NONE);
-
-    base::HistogramTester histogram_tester;
-    SetAuthError(entry.error_state);
-
-    EXPECT_EQ(global_error()->HasMenuItem(), entry.is_error);
-    EXPECT_EQ(global_error()->MenuItemLabel().empty(), !entry.is_error);
-    EXPECT_EQ(global_error()->GetBubbleViewMessages().empty(), !entry.is_error);
-    EXPECT_FALSE(global_error()->GetBubbleViewTitle().empty());
-    EXPECT_FALSE(global_error()->GetBubbleViewAcceptButtonLabel().empty());
-    EXPECT_TRUE(global_error()->GetBubbleViewCancelButtonLabel().empty());
-
-    ProfileMetrics::LogNumberOfProfiles(&testing_profile_manager()
-                                             ->profile_manager()
-                                             ->GetProfileAttributesStorage());
-
-    if (entry.is_error) {
-      histogram_tester.ExpectBucketCount("Signin.AuthError", entry.error_state,
-                                         1);
-    }
-  }
-}
diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc
index b6f43ea..53895f9 100644
--- a/chrome/browser/sync/test/integration/enable_disable_test.cc
+++ b/chrome/browser/sync/test/integration/enable_disable_test.cc
@@ -95,13 +95,10 @@
  protected:
   void SetupTest(bool all_types_enabled) {
     ASSERT_TRUE(SetupClients());
-    if (all_types_enabled) {
-      ASSERT_TRUE(GetClient(0)->SetupSync());
-    } else {
-      ASSERT_TRUE(
-          GetClient(0)->SetupSyncNoWaitForCompletion(UserSelectableTypeSet()));
-      ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
-    }
+    ASSERT_TRUE(GetClient(0)->SetupSync(base::BindLambdaForTesting(
+        [all_types_enabled](syncer::SyncUserSettings* user_settings) {
+          user_settings->SetSelectedTypes(all_types_enabled, {});
+        })));
 
     registered_data_types_ = GetSyncService(0)->GetRegisteredDataTypesForTest();
     multi_grouped_types_ = MultiGroupTypes(registered_data_types_);
diff --git a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
index 8a2745c..ff4fc676 100644
--- a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
@@ -5,6 +5,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/bind.h"
 #include "base/guid.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/metrics/statistics_recorder.h"
@@ -227,12 +228,14 @@
   void SetupBookmarksSync() {
     // Only enable bookmarks so that sync is not nudged by another data type
     // (with a shorter delay).
+    ASSERT_TRUE(GetClient(0)->SetupSync(
+        base::BindOnce([](syncer::SyncUserSettings* user_settings) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-    GetSyncService(0)->GetUserSettings()->SetSelectedOsTypes(false, {});
+          user_settings->SetSelectedOsTypes(false, {});
 #endif
-    ASSERT_TRUE(GetClient(0)->SetupSyncNoWaitForCompletion(
-        {syncer::UserSelectableType::kBookmarks}));
-    ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
+          user_settings->SetSelectedTypes(
+              false, {syncer::UserSelectableType::kBookmarks});
+        })));
   }
 
  private:
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 0b4b4c5..70f9606 100644
--- a/chrome/browser/sync/test/integration/sync_service_impl_harness.cc
+++ b/chrome/browser/sync/test/integration/sync_service_impl_harness.cc
@@ -261,10 +261,10 @@
   AwaitSyncSetupCompletion();
 }
 
-bool SyncServiceImplHarness::SetupSync() {
+bool SyncServiceImplHarness::SetupSync(
+    SetUserSettingsCallback user_settings_callback) {
   bool result =
-      SetupSyncNoWaitForCompletion(
-          service()->GetUserSettings()->GetRegisteredSelectableTypes()) &&
+      SetupSyncNoWaitForCompletion(std::move(user_settings_callback)) &&
       AwaitSyncSetupCompletion();
   if (!result) {
     LOG(ERROR) << profile_debug_name_ << ": SetupSync failed. Syncer status:\n"
@@ -276,31 +276,28 @@
 }
 
 bool SyncServiceImplHarness::SetupSyncNoWaitForCompletion(
-    syncer::UserSelectableTypeSet selected_types) {
-  return SetupSyncImpl(selected_types, EncryptionSetupMode::kNoEncryption,
-                       /*encryption_passphrase=*/absl::nullopt);
+    SetUserSettingsCallback user_settings_callback) {
+  return SetupSyncImpl(EncryptionSetupMode::kNoEncryption,
+                       /*encryption_passphrase=*/absl::nullopt,
+                       std::move(user_settings_callback));
 }
 
 bool SyncServiceImplHarness::
     SetupSyncWithEncryptionPassphraseNoWaitForCompletion(
-        syncer::UserSelectableTypeSet selected_types,
         const std::string& passphrase) {
-  return SetupSyncImpl(selected_types, EncryptionSetupMode::kEncryption,
-                       passphrase);
+  return SetupSyncImpl(EncryptionSetupMode::kEncryption, passphrase);
 }
 
 bool SyncServiceImplHarness::
     SetupSyncWithDecryptionPassphraseNoWaitForCompletion(
-        syncer::UserSelectableTypeSet selected_types,
         const std::string& passphrase) {
-  return SetupSyncImpl(selected_types, EncryptionSetupMode::kDecryption,
-                       passphrase);
+  return SetupSyncImpl(EncryptionSetupMode::kDecryption, passphrase);
 }
 
 bool SyncServiceImplHarness::SetupSyncImpl(
-    syncer::UserSelectableTypeSet selected_types,
     EncryptionSetupMode encryption_mode,
-    const absl::optional<std::string>& passphrase) {
+    const absl::optional<std::string>& passphrase,
+    SetUserSettingsCallback user_settings_callback) {
   DCHECK(encryption_mode == EncryptionSetupMode::kNoEncryption ||
          passphrase.has_value());
 
@@ -323,13 +320,12 @@
   if (!AwaitEngineInitialization()) {
     return false;
   }
-  // Choose the datatypes to be synced. If all registered datatypes are to be
-  // synced, set sync_everything to true; otherwise, set it to false.
-  bool sync_everything =
-      (selected_types ==
-       service()->GetUserSettings()->GetRegisteredSelectableTypes());
-  service()->GetUserSettings()->SetSelectedTypes(sync_everything,
-                                                 selected_types);
+
+  // Now give the caller a chance to configure settings (in particular, the
+  // selected data types) before actually starting to sync.
+  if (user_settings_callback) {
+    std::move(user_settings_callback).Run(service()->GetUserSettings());
+  }
 
   if (encryption_mode == EncryptionSetupMode::kEncryption) {
     service()->GetUserSettings()->SetEncryptionPassphrase(passphrase.value());
@@ -481,8 +477,10 @@
       std::string(syncer::GetUserSelectableTypeName(type)) + ")");
 
   if (!IsSyncEnabledByUser()) {
-    bool result =
-        SetupSyncNoWaitForCompletion({type}) && AwaitSyncSetupCompletion();
+    bool result = SetupSync(base::BindLambdaForTesting(
+        [type](syncer::SyncUserSettings* user_settings) {
+          user_settings->SetSelectedTypes(false, {type});
+        }));
     // If SetupSync() succeeded, then Sync must now be enabled.
     DCHECK(!result || IsSyncEnabledByUser());
     return result;
diff --git a/chrome/browser/sync/test/integration/sync_service_impl_harness.h b/chrome/browser/sync/test/integration/sync_service_impl_harness.h
index 3910392..cc31d63b4 100644
--- a/chrome/browser/sync/test/integration/sync_service_impl_harness.h
+++ b/chrome/browser/sync/test/integration/sync_service_impl_harness.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/callback_forward.h"
 #include "base/memory/raw_ptr.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -21,6 +22,7 @@
 
 namespace syncer {
 class SyncSetupInProgressHandle;
+class SyncUserSettings;
 }  // namespace syncer
 
 class SyncSigninDelegate;
@@ -40,6 +42,9 @@
     UI_SIGNIN
   };
 
+  using SetUserSettingsCallback =
+      base::OnceCallback<void(syncer::SyncUserSettings*)>;
+
   static std::unique_ptr<SyncServiceImplHarness> Create(
       Profile* profile,
       const std::string& username,
@@ -70,26 +75,32 @@
   // Enables and configures sync for all available datatypes. Returns true only
   // after sync has been fully initialized and authenticated, and we are ready
   // to process changes.
-  bool SetupSync();
+  // |user_settings_callback| will be called once the engine is initialized, but
+  // before actually starting sync, to give the caller a chance to modify sync
+  // settings (mostly the selected data types).
+  bool SetupSync(SetUserSettingsCallback user_settings_callback =
+                     SetUserSettingsCallback());
 
-  // Enables and configures sync only for the given |selected_types|.
+  // Enables and configures sync.
   // Does not wait for sync to be ready to process changes -- callers need to
   // ensure this by calling AwaitSyncSetupCompletion() or
   // AwaitSyncTransportActive().
+  // |user_settings_callback| will be called once the engine is initialized, but
+  // before actually starting sync, to give the caller a chance to modify sync
+  // settings (mostly the selected data types).
   // Returns true on success.
   bool SetupSyncNoWaitForCompletion(
-      syncer::UserSelectableTypeSet selected_types);
+      SetUserSettingsCallback user_settings_callback =
+          SetUserSettingsCallback());
 
   // Same as SetupSyncNoWaitForCompletion(), but also sets the given encryption
   // passphrase during setup.
   bool SetupSyncWithEncryptionPassphraseNoWaitForCompletion(
-      syncer::UserSelectableTypeSet selected_types,
       const std::string& passphrase);
 
   // Same as SetupSyncNoWaitForCompletion(), but also sets the given decryption
   // passphrase during setup.
   bool SetupSyncWithDecryptionPassphraseNoWaitForCompletion(
-      syncer::UserSelectableTypeSet selected_types,
       const std::string& passphrase);
 
   // Signals that sync setup is complete, and that PSS may begin syncing.
@@ -188,9 +199,13 @@
   // |encryption_mode|.
   // If |encryption_mode| is kDecryption or kEncryption, |encryption_passphrase|
   // has to have a value which will be used to properly setup sync.
-  bool SetupSyncImpl(syncer::UserSelectableTypeSet selected_types,
-                     EncryptionSetupMode encryption_mode,
-                     const absl::optional<std::string>& encryption_passphrase);
+  // |user_settings_callback| will be called once the engine is initialized, but
+  // before actually starting sync, to give the caller a chance to modify sync
+  // settings (mostly the selected data types).
+  bool SetupSyncImpl(EncryptionSetupMode encryption_mode,
+                     const absl::optional<std::string>& encryption_passphrase,
+                     SetUserSettingsCallback user_settings_callback =
+                         SetUserSettingsCallback());
 
   // Gets detailed status from |service_| in pretty-printable form.
   std::string GetServiceStatus();
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index f7ce36d..7a26e0e 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -868,18 +868,15 @@
     }
 
     if (encryption_passphrase_provided) {
-      CHECK(client->SetupSyncWithEncryptionPassphraseNoWaitForCompletion(
-          GetRegisteredSelectableTypes(client_index),
+      ASSERT_TRUE(client->SetupSyncWithEncryptionPassphraseNoWaitForCompletion(
           encryption_passphrase_it->second))
           << "SetupSync() failed.";
     } else if (decryption_passphrase_provided) {
-      CHECK(client->SetupSyncWithDecryptionPassphraseNoWaitForCompletion(
-          GetRegisteredSelectableTypes(client_index),
+      ASSERT_TRUE(client->SetupSyncWithDecryptionPassphraseNoWaitForCompletion(
           decryption_passphrase_it->second))
           << "SetupSync() failed.";
     } else {
-      CHECK(client->SetupSyncNoWaitForCompletion(
-          GetRegisteredSelectableTypes(client_index)))
+      ASSERT_TRUE(client->SetupSyncNoWaitForCompletion())
           << "SetupSync() failed.";
     }
 
diff --git a/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc b/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
index 878a223..369c15b 100644
--- a/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
@@ -111,9 +111,7 @@
       UpdatedProgressMarkerChecker(GetSyncService(kEncryptingClientId)).Wait());
 
   // Set up a new sync client.
-  ASSERT_TRUE(GetClient(kDecryptingClientId)
-                  ->SetupSyncNoWaitForCompletion(
-                      GetRegisteredSelectableTypes(kDecryptingClientId)));
+  ASSERT_TRUE(GetClient(kDecryptingClientId)->SetupSyncNoWaitForCompletion());
   ASSERT_TRUE(
       PassphraseRequiredChecker(GetSyncService(kDecryptingClientId)).Wait());
 
diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
index aee01d2..3b744f0 100644
--- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
@@ -236,8 +236,7 @@
 
   // When client 1 hits a passphrase required state, we can infer that
   // client 0's passphrase has been committed. to the server.
-  ASSERT_TRUE(GetClient(1)->SetupSyncNoWaitForCompletion(
-      GetRegisteredSelectableTypes(1)));
+  ASSERT_TRUE(GetClient(1)->SetupSyncNoWaitForCompletion());
   ASSERT_TRUE(PassphraseRequiredChecker(GetSyncService(1)).Wait());
 
   // Get client 1 out of the passphrase required state.
diff --git a/chrome/browser/sync/test/integration/two_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/two_client_user_events_sync_test.cc
index 0f44152d..24790fd6 100644
--- a/chrome/browser/sync/test/integration/two_client_user_events_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_user_events_sync_test.cc
@@ -76,9 +76,7 @@
       base::Time() + base::Microseconds(1)));
 
   // Set up sync on the second client.
-  ASSERT_TRUE(GetClient(kDecryptingClientId)
-                  ->SetupSyncNoWaitForCompletion(
-                      GetRegisteredSelectableTypes(kDecryptingClientId)));
+  ASSERT_TRUE(GetClient(kDecryptingClientId)->SetupSyncNoWaitForCompletion());
   // The second client asks the user to provide a password for decryption.
   ASSERT_TRUE(
       PassphraseRequiredChecker(GetSyncService(kDecryptingClientId)).Wait());
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 2276683..4bc29c2d 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
@@ -15,6 +15,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
+#include "chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut_manager.h"
 #include "chrome/browser/web_applications/test/fake_os_integration_manager.h"
@@ -23,6 +24,7 @@
 #include "chrome/browser/web_applications/test/web_app_test_utils.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
 #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_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
@@ -111,18 +113,20 @@
 
     AppId app_id;
     base::RunLoop run_loop;
-    WebAppProvider::GetForTest(profile)
-        ->install_manager()
-        .InstallWebAppFromManifestWithFallback(
-            browser->tab_strip_model()->GetActiveWebContents(),
-            WebAppInstallFlow::kInstallSite, source,
+    auto* provider = WebAppProvider::GetForTest(profile);
+    provider->command_manager().ScheduleCommand(
+        std::make_unique<FetchManifestAndInstallCommand>(
+            &provider->install_finalizer(), &provider->registrar(), source,
+            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();
-            }));
+            }),
+            /*use_fallback=*/true, WebAppInstallFlow::kInstallSite));
     run_loop.Run();
     return app_id;
   }
@@ -496,7 +500,7 @@
       GetProfile(0), webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
       GetUserInitiatedAppURL2());
   ASSERT_NE(app_id1, app_id2);
-  
+
   // Wait for both of the webapps to be installed on profile 1.
   ASSERT_TRUE(AwaitQuiescence());
   apps_helper::AwaitWebAppQuiescence({GetProfile(0), GetProfile(1)});
diff --git a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java
index 54c172f..ddf258f 100644
--- a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java
+++ b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java
@@ -141,6 +141,26 @@
 
     @Test
     @MediumTest
+    public void testClickingManagePasswordsTriggersCallback() {
+        runOnUiThreadBlocking(() -> {
+            mTouchToFill.showCredentials(sExampleUrl, true, Collections.singletonList(sAna), false);
+        });
+        BottomSheetTestSupport.waitForOpen(mBottomSheetController);
+
+        BottomSheetTestSupport sheetSupport = new BottomSheetTestSupport(mBottomSheetController);
+
+        // Swipe the sheet up to it's full state in order to see the 'Manage Passwords' button.
+        runOnUiThreadBlocking(() -> { sheetSupport.setSheetState(SheetState.FULL, false); });
+
+        pollUiThread(() -> getManagePasswordsButton() != null);
+        TouchCommon.singleClickView(getManagePasswordsButton());
+        waitForEvent(mMockBridge).onManagePasswordsSelected();
+        verify(mMockBridge, never()).onDismissed();
+        verify(mMockBridge, never()).onCredentialSelected(any());
+    }
+
+    @Test
+    @MediumTest
     @SuppressLint("SetTextI18n")
     public void testDismissedIfUnableToShow() throws Exception {
         BottomSheetContent otherBottomSheetContent = runOnUiThreadBlocking(() -> {
@@ -220,6 +240,11 @@
         return mActivityTestRule.getActivity().findViewById(R.id.sheet_item_list);
     }
 
+    private TextView getManagePasswordsButton() {
+        return mActivityTestRule.getActivity().findViewById(
+                R.id.touch_to_fill_sheet_manage_passwords);
+    }
+
     public static <T> T waitForEvent(T mock) {
         return verify(mock,
                 timeout(ScalableTimeout.scaleTimeout(CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL)));
diff --git a/chrome/browser/ui/android/signin/BUILD.gn b/chrome/browser/ui/android/signin/BUILD.gn
index 3918471..acd9852 100644
--- a/chrome/browser/ui/android/signin/BUILD.gn
+++ b/chrome/browser/ui/android/signin/BUILD.gn
@@ -31,7 +31,6 @@
     "//components/sync/android:sync_java",
     "//components/user_prefs/android:java",
     "//content/public/android:content_java",
-    "//third_party/android_deps:guava_android_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
     "//third_party/androidx:androidx_appcompat_appcompat_resources_java",
@@ -165,7 +164,6 @@
     "//components/signin/public/android:signin_java_test_support",
     "//components/user_prefs/android:java",
     "//content/public/android:content_java",
-    "//third_party/android_deps:guava_android_java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
     "//third_party/androidx:androidx_fragment_fragment_java",
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java
index 96a9f73..efb1555 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java
@@ -18,6 +18,7 @@
 import androidx.annotation.StringRes;
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.base.Promise;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -34,7 +35,10 @@
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.AccountUtils;
+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.AccountInfoServiceProvider;
 import org.chromium.components.signin.identitymanager.ConsentLevel;
 import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
@@ -210,10 +214,16 @@
             return false;
         }
         final @Nullable Account visibleAccount = getVisibleAccount();
-        final AccountManagerFacade accountManagerFacade =
-                AccountManagerFacadeProvider.getInstance();
-        return visibleAccount == null
-                || accountManagerFacade.canOfferExtendedSyncPromos(visibleAccount).or(false);
+        if (visibleAccount == null) {
+            return true;
+        }
+        final Promise<AccountInfo> visibleAccountPromise =
+                AccountInfoServiceProvider.get().getAccountInfoByEmail(visibleAccount.name);
+        return visibleAccountPromise.isFulfilled()
+                && visibleAccountPromise.getResult()
+                           .getAccountCapabilities()
+                           .canOfferExtendedSyncPromos()
+                == Tribool.TRUE;
     }
 
     private static boolean canShowSettingsPromo() {
diff --git a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java
index 0e0ac30e..22139ec 100644
--- a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java
+++ b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java
@@ -4,18 +4,12 @@
 
 package org.chromium.chrome.browser.ui.signin;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
-import android.accounts.Account;
 import android.text.format.DateUtils;
 
-import com.google.common.base.Optional;
-
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -35,13 +29,13 @@
 import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
-import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
+import org.chromium.components.signin.test.util.AccountCapabilitiesBuilder;
 import org.chromium.components.signin.test.util.FakeAccountManagerFacade;
 
 /**
- * Tests for {@link SigninPromoController}..
+ * Tests for {@link SigninPromoController}.
  */
 @RunWith(BaseRobolectricTestRunner.class)
 @Features.DisableFeatures({ChromeFeatureList.FORCE_DISABLE_EXTENDED_SYNC_PROMOS})
@@ -71,6 +65,8 @@
 
     private final SharedPreferencesManager mSharedPreferencesManager =
             SharedPreferencesManager.getInstance();
+    private final AccountCapabilitiesBuilder mAccountCapabilitiesBuilder =
+            new AccountCapabilitiesBuilder();
 
     @Before
     public void setUp() {
@@ -95,12 +91,10 @@
 
     @Test
     public void shouldHideSyncPromoForNTPWhenDefaultAccountCannotOfferSyncPromos() {
-        final CoreAccountInfo accountInfo =
-                mAccountManagerTestRule.addAccount("test.account.default@gmail.com");
-        mAccountManagerTestRule.addAccount("test.account.secondary@gmail.com");
-        doReturn(Optional.of(false))
-                .when(mFakeAccountManagerFacade)
-                .canOfferExtendedSyncPromos(CoreAccountInfo.getAndroidAccountFrom(accountInfo));
+        mAccountManagerTestRule.addAccount("test1@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(false).build());
+        mAccountManagerTestRule.addAccount("test2@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(true).build());
 
         Assert.assertFalse(
                 SigninPromoController.canShowSyncPromo(SigninAccessPoint.NTP_CONTENT_SUGGESTIONS));
@@ -117,16 +111,10 @@
 
     @Test
     public void shouldShowSyncPromoForNTPWhenSecondaryAccountCannotOfferSyncPromos() {
-        mAccountManagerTestRule.addAccount("test.account.default@gmail.com");
-        final CoreAccountInfo secondAccountInfo =
-                mAccountManagerTestRule.addAccount("test.account.secondary@gmail.com");
-        final Account secondAccount = CoreAccountInfo.getAndroidAccountFrom(secondAccountInfo);
-        doAnswer(invocation -> {
-            final Account account0 = invocation.getArgument(0);
-            return Optional.of(!account0.equals(secondAccount));
-        })
-                .when(mFakeAccountManagerFacade)
-                .canOfferExtendedSyncPromos(any());
+        mAccountManagerTestRule.addAccount("test1@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(true).build());
+        mAccountManagerTestRule.addAccount("test2@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(false).build());
 
         Assert.assertTrue(
                 SigninPromoController.canShowSyncPromo(SigninAccessPoint.NTP_CONTENT_SUGGESTIONS));
diff --git a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtilLaunchSigninPromoTest.java b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtilLaunchSigninPromoTest.java
index e80de01a..a7f9a32b 100644
--- a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtilLaunchSigninPromoTest.java
+++ b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoUtilLaunchSigninPromoTest.java
@@ -36,17 +36,15 @@
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
 import org.chromium.components.prefs.PrefService;
-import org.chromium.components.signin.AccountCapabilitiesConstants;
-import org.chromium.components.signin.base.AccountCapabilities;
 import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.identitymanager.ConsentLevel;
 import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
+import org.chromium.components.signin.test.util.AccountCapabilitiesBuilder;
 import org.chromium.components.signin.test.util.FakeAccountManagerFacade;
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.components.user_prefs.UserPrefsJni;
 
-import java.util.HashMap;
 import java.util.Set;
 
 /**
@@ -87,6 +85,8 @@
 
     private final Context mContext = RuntimeEnvironment.systemContext;
     private final SigninPreferencesManager mPrefManager = SigninPreferencesManager.getInstance();
+    private final AccountCapabilitiesBuilder mAccountCapabilitiesBuilder =
+            new AccountCapabilitiesBuilder();
 
     @Before
     public void setUp() {
@@ -180,8 +180,8 @@
 
     @Test
     public void whenNoAccountListStoredShouldReturnTrue() {
-        final CoreAccountInfo accountInfo = addAccountWithCanOfferExtendedSyncPromosCapability(
-                "test", /*canOfferExtendedSyncPromos=*/true);
+        final CoreAccountInfo accountInfo = mAccountManagerTestRule.addAccount("test@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(true).build());
         mPrefManager.setSigninPromoLastShownVersion(40);
         // Old implementation hasn't been storing account list
         Assert.assertTrue(SigninPromoUtil.launchSigninPromoIfNeeded(
@@ -204,8 +204,8 @@
 
     @Test
     public void whenHasNewAccountShouldReturnTrue() {
-        addAccountWithCanOfferExtendedSyncPromosCapability(
-                "test1", /*canOfferExtendedSyncPromos=*/true);
+        mAccountManagerTestRule.addAccount("test1@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(true).build());
         mAccountManagerTestRule.addAccount("test2@gmail.com");
         mPrefManager.setSigninPromoLastShownVersion(40);
         mPrefManager.setSigninPromoLastAccountNames(
@@ -248,8 +248,8 @@
 
     @Test
     public void promoHiddenWhenDefaultAccountCanNotOfferExtendedSyncPromos() {
-        addAccountWithCanOfferExtendedSyncPromosCapability(
-                "test1", /*canOfferExtendedSyncPromos=*/false);
+        mAccountManagerTestRule.addAccount("test1@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(false).build());
         mAccountManagerTestRule.addAccount("test2@gmail.com");
         mPrefManager.setSigninPromoLastShownVersion(38);
 
@@ -261,25 +261,14 @@
 
     @Test
     public void promoVisibleWhenTheSecondaryAccountCanNotOfferExtendedSyncPromos() {
-        addAccountWithCanOfferExtendedSyncPromosCapability(
-                "test1", /*canOfferExtendedSyncPromos=*/true);
-        addAccountWithCanOfferExtendedSyncPromosCapability(
-                "test2", /*canOfferExtendedSyncPromos=*/false);
+        mAccountManagerTestRule.addAccount("test1@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(true).build());
+        mAccountManagerTestRule.addAccount("test2@gmail.com",
+                mAccountCapabilitiesBuilder.setCanOfferExtendedSyncPromos(false).build());
         mPrefManager.setSigninPromoLastShownVersion(38);
         Assert.assertTrue(SigninPromoUtil.launchSigninPromoIfNeeded(
                 mContext, mLauncherMock, CURRENT_MAJOR_VERSION));
 
         verify(mLauncherMock).launchActivityIfAllowed(mContext, SigninAccessPoint.SIGNIN_PROMO);
     }
-
-    private CoreAccountInfo addAccountWithCanOfferExtendedSyncPromosCapability(
-            String baseName, boolean canOfferExtendedSyncPromos) {
-        final HashMap<String, Boolean> capabilities = new HashMap<>();
-        capabilities.put(
-                AccountCapabilitiesConstants.CAN_OFFER_EXTENDED_CHROME_SYNC_PROMOS_CAPABILITY_NAME,
-                canOfferExtendedSyncPromos);
-        return mAccountManagerTestRule.addAccount(baseName + "@gmail.com", baseName + ".fullName",
-                baseName + ".giveName",
-                /*avatar=*/null, new AccountCapabilities(capabilities));
-    }
 }
diff --git a/chrome/browser/ui/global_error/global_error_browsertest.cc b/chrome/browser/ui/global_error/global_error_browsertest.cc
index 354a9bc..76803a2 100644
--- a/chrome/browser/ui/global_error/global_error_browsertest.cc
+++ b/chrome/browser/ui/global_error/global_error_browsertest.cc
@@ -45,11 +45,6 @@
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/feature_switch.h"
 
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/signin/signin_global_error.h"
-#include "chrome/browser/signin/signin_global_error_factory.h"
-#endif
-
 namespace {
 
 // Shows the first GlobalError with associated UI associated with |browser|.
@@ -206,10 +201,6 @@
         prefs::kRecoveryComponentNeedsElevation, true);
     waiter.Wait();
     ShowPendingError(browser());
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
-  } else if (name == "SigninGlobalError") {
-    SigninGlobalErrorFactory::GetForProfile(profile)->ShowBubbleView(browser());
-#endif
   } else {
     ADD_FAILURE();
   }
@@ -249,10 +240,3 @@
   ShowAndVerifyUi();
 }
 #endif
-
-// Signin global errors never happon on ChromeOS.
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
-IN_PROC_BROWSER_TEST_F(GlobalErrorBubbleTest, InvokeUi_SigninGlobalError) {
-  ShowAndVerifyUi();
-}
-#endif
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc
index 992d9ec..c1740c7 100644
--- a/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc
+++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper.h b/chrome/browser/ui/sync/profile_signin_confirmation_helper.h
index d3139177..7fefd8e3 100644
--- a/chrome/browser/ui/sync/profile_signin_confirmation_helper.h
+++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_SYNC_PROFILE_SIGNIN_CONFIRMATION_HELPER_H_
 #define CHROME_BROWSER_UI_SYNC_PROFILE_SIGNIN_CONFIRMATION_HELPER_H_
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 
 class Profile;
 
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 4c954dd..49b077f 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -1029,10 +1029,6 @@
       SetIcon(GetIndexOfCommandId(error->MenuItemCommandID()),
               error->MenuItemIcon());
       menu_items_added = true;
-      if (IDC_SHOW_SIGNIN_ERROR == error->MenuItemCommandID()) {
-        signin_metrics::RecordSigninImpressionUserActionForAccessPoint(
-            signin_metrics::AccessPoint::ACCESS_POINT_MENU);
-      }
     }
   }
   return menu_items_added;
diff --git a/chrome/browser/ui/views/bubble_anchor_util_views.cc b/chrome/browser/ui/views/bubble_anchor_util_views.cc
index 9106aa5..b36d53e 100644
--- a/chrome/browser/ui/views/bubble_anchor_util_views.cc
+++ b/chrome/browser/ui/views/bubble_anchor_util_views.cc
@@ -59,6 +59,10 @@
   return GetPageInfoAnchorConfiguration(browser);
 }
 
+AnchorConfiguration GetAppMenuAnchorConfiguration(Browser* browser) {
+  return GetPageInfoAnchorConfiguration(browser, kAppMenuButton);
+}
+
 gfx::Rect GetPageInfoAnchorRect(Browser* browser) {
   // GetPageInfoAnchorConfiguration()'s anchor_view should be preferred if
   // available.
diff --git a/chrome/browser/ui/views/bubble_anchor_util_views.h b/chrome/browser/ui/views/bubble_anchor_util_views.h
index b64a7d4..43f90769 100644
--- a/chrome/browser/ui/views/bubble_anchor_util_views.h
+++ b/chrome/browser/ui/views/bubble_anchor_util_views.h
@@ -38,6 +38,10 @@
 AnchorConfiguration GetPermissionPromptBubbleAnchorConfiguration(
     Browser* browser);
 
+// Returns the anchor configuration for bubbles that are aligned to the app menu
+// button.
+AnchorConfiguration GetAppMenuAnchorConfiguration(Browser* browser);
+
 }  // namespace bubble_anchor_util
 
 #endif  // CHROME_BROWSER_UI_VIEWS_BUBBLE_ANCHOR_UTIL_VIEWS_H_
diff --git a/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_notice_bubble_view.cc b/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_notice_bubble_view.cc
index 78cc227d..c216a36d 100644
--- a/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_notice_bubble_view.cc
+++ b/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_notice_bubble_view.cc
@@ -5,12 +5,39 @@
 #include "chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_notice_bubble_view.h"
 
 #include "chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt.h"
+#include "chrome/browser/ui/views/bubble_anchor_util_views.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/layout/fill_layout.h"
 
 // static
 void ShowPrivacySandboxNoticeBubble(Browser* browser) {
-  // TODO(crbug.com/1321587): Create BubbleDialogDelegate and show bubble.
+  bubble_anchor_util::AnchorConfiguration configuration =
+      bubble_anchor_util::GetAppMenuAnchorConfiguration(browser);
+  auto bubble_delegate = std::make_unique<views::BubbleDialogDelegate>(
+      configuration.anchor_view, configuration.bubble_arrow);
+  bubble_delegate->SetShowTitle(false);
+  bubble_delegate->SetShowCloseButton(false);
+  bubble_delegate->set_close_on_deactivate(false);
+  bubble_delegate->set_fixed_width(
+      ChromeLayoutProvider::Get()->GetDistanceMetric(
+          views::DISTANCE_BUBBLE_PREFERRED_WIDTH));
+
+  bubble_delegate->SetButtonLabel(
+      ui::DIALOG_BUTTON_OK,
+      l10n_util::GetStringUTF16(
+          IDS_PRIVACY_SANDBOX_DIALOG_NOTICE_ACKNOWLEDGE_BUTTON));
+  bubble_delegate->SetButtonLabel(
+      ui::DIALOG_BUTTON_CANCEL,
+      l10n_util::GetStringUTF16(
+          IDS_PRIVACY_SANDBOX_DIALOG_NOTICE_OPEN_SETTINGS_BUTTON));
+
+  bubble_delegate->SetContentsView(
+      std::make_unique<PrivacySandboxNoticeBubbleView>(browser));
+  views::BubbleDialogDelegate::CreateBubble(std::move(bubble_delegate))->Show();
 }
 
 PrivacySandboxNoticeBubbleView::PrivacySandboxNoticeBubbleView(Browser* browser)
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 1ab19d8..8d603ff 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -116,7 +116,6 @@
 #endif
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/signin/signin_global_error_factory.h"
 #include "chrome/browser/ui/bookmarks/bookmark_bubble_sign_in_delegate.h"
 #include "chrome/browser/ui/dialogs/outdated_upgrade_bubble.h"
 #endif
@@ -387,12 +386,9 @@
   LoadImages();
 
   // Start global error services now so we set the icon on the menu correctly.
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
-  SigninGlobalErrorFactory::GetForProfile(browser_->profile());
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
   RecoveryInstallGlobalErrorFactory::GetForProfile(browser_->profile());
-#endif
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
 
   // Set the button icon based on the system state. Do this after
   // |app_menu_button_| has been added as a bubble may be shown that needs
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 ad770e0b3..800f344 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
@@ -18,11 +18,12 @@
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
+#include "chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
+#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_install_info.h"
-#include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -147,27 +148,28 @@
     auto* provider = WebAppProvider::GetForTest(browser()->profile());
     DCHECK(provider);
     test::WaitUntilReady(provider);
-    provider->install_manager().InstallWebAppFromManifestWithFallback(
-        browser()->tab_strip_model()->GetActiveWebContents(),
-        WebAppInstallFlow::kInstallSite,
-        webapps::WebappInstallSource::MENU_BROWSER_TAB,
-        /*dialog_callback=*/
-        base::BindLambdaForTesting(
-            [](content::WebContents*,
-               std::unique_ptr<WebAppInstallInfo> web_app_info,
-               WebAppInstallationAcceptanceCallback acceptance_callback) {
-              web_app_info->user_display_mode = UserDisplayMode::kTabbed;
-              std::move(acceptance_callback)
-                  .Run(/*user_accepted=*/true, std::move(web_app_info));
-            }),
-        /*callback=*/
-        base::BindLambdaForTesting(
-            [&run_loop, &app_id](const AppId& installed_app_id,
-                                 webapps::InstallResultCode code) {
+    provider->command_manager().ScheduleCommand(
+        std::make_unique<FetchManifestAndInstallCommand>(
+            &provider->install_finalizer(), &provider->registrar(),
+            webapps::WebappInstallSource::MENU_BROWSER_TAB,
+            browser()->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
+            /*bypass_service_worker_check=*/false,
+            base::BindLambdaForTesting(
+                [](content::WebContents*,
+                   std::unique_ptr<WebAppInstallInfo> web_app_info,
+                   WebAppInstallationAcceptanceCallback acceptance_callback) {
+                  web_app_info->user_display_mode = UserDisplayMode::kTabbed;
+                  std::move(acceptance_callback)
+                      .Run(/*user_accepted=*/true, std::move(web_app_info));
+                }),
+            base::BindLambdaForTesting([&run_loop, &app_id](
+                                           const AppId& installed_app_id,
+                                           webapps::InstallResultCode code) {
               DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
               app_id = installed_app_id;
               run_loop.Quit();
-            }));
+            }),
+            /*use_fallback=*/true, WebAppInstallFlow::kInstallSite));
     run_loop.Run();
   }
 
diff --git a/chrome/browser/ui/web_applications/create_shortcut_browsertest.cc b/chrome/browser/ui/web_applications/create_shortcut_browsertest.cc
index 487b490..3df4d99f 100644
--- a/chrome/browser/ui/web_applications/create_shortcut_browsertest.cc
+++ b/chrome/browser/ui/web_applications/create_shortcut_browsertest.cc
@@ -19,9 +19,9 @@
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
+#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_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_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
@@ -259,7 +259,7 @@
   ASSERT_TRUE(chrome::ExecuteCommand(browser(), IDC_CREATE_SHORTCUT));
   ASSERT_TRUE(chrome::ExecuteCommand(browser(), IDC_CREATE_SHORTCUT));
 
-  EXPECT_EQ(1u, provider().install_manager().GetInstallTaskCountForTesting());
+  EXPECT_EQ(1u, provider().command_manager().GetCommandCountForTesting());
 }
 
 }  // namespace web_app
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 a3e1a589..1dfa0dc 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
@@ -30,10 +30,12 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/toolbar/app_menu_model.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
+#include "chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h"
 #include "chrome/browser/web_applications/external_install_options.h"
 #include "chrome/browser/web_applications/test/service_worker_registration_waiter.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
+#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_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
@@ -135,18 +137,21 @@
   auto* provider = WebAppProvider::GetForTest(browser->profile());
   DCHECK(provider);
   test::WaitUntilReady(provider);
-  provider->install_manager().InstallWebAppFromManifestWithFallback(
-      browser->tab_strip_model()->GetActiveWebContents(),
-      WebAppInstallFlow::kInstallSite,
-      webapps::WebappInstallSource::MENU_BROWSER_TAB,
-      base::BindOnce(&AutoAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&run_loop, &app_id](const AppId& installed_app_id,
-                               webapps::InstallResultCode code) {
-            DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
-            app_id = installed_app_id;
-            run_loop.Quit();
-          }));
+  provider->command_manager().ScheduleCommand(
+      std::make_unique<FetchManifestAndInstallCommand>(
+          &provider->install_finalizer(), &provider->registrar(),
+          webapps::WebappInstallSource::MENU_BROWSER_TAB,
+          browser->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
+          /*bypass_service_worker_check=*/false,
+          base::BindOnce(&AutoAcceptDialogCallback),
+          base::BindLambdaForTesting(
+              [&run_loop, &app_id](const AppId& installed_app_id,
+                                   webapps::InstallResultCode code) {
+                DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
+                app_id = installed_app_id;
+                run_loop.Quit();
+              }),
+          /*use_fallback=*/true, WebAppInstallFlow::kInstallSite));
 
   run_loop.Run();
   return app_id;
@@ -164,18 +169,21 @@
   auto* provider = WebAppProvider::GetForTest(browser->profile());
   DCHECK(provider);
   test::WaitUntilReady(provider);
-  provider->install_manager().InstallWebAppFromManifestWithFallback(
-      browser->tab_strip_model()->GetActiveWebContents(),
-      WebAppInstallFlow::kInstallSite,
-      webapps::WebappInstallSource::MENU_BROWSER_TAB,
-      base::BindOnce(&AutoAcceptDialogCallback),
-      base::BindLambdaForTesting(
-          [&run_loop, &app_id](const AppId& installed_app_id,
-                               webapps::InstallResultCode code) {
-            DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
-            app_id = installed_app_id;
-            run_loop.Quit();
-          }));
+  provider->command_manager().ScheduleCommand(
+      std::make_unique<FetchManifestAndInstallCommand>(
+          &provider->install_finalizer(), &provider->registrar(),
+          webapps::WebappInstallSource::MENU_BROWSER_TAB,
+          browser->tab_strip_model()->GetActiveWebContents()->GetWeakPtr(),
+          /*bypass_service_worker_check=*/false,
+          base::BindOnce(&AutoAcceptDialogCallback),
+          base::BindLambdaForTesting(
+              [&run_loop, &app_id](const AppId& installed_app_id,
+                                   webapps::InstallResultCode code) {
+                DCHECK_EQ(code, webapps::InstallResultCode::kSuccessNewInstall);
+                app_id = installed_app_id;
+                run_loop.Quit();
+              }),
+          /*use_fallback=*/true, WebAppInstallFlow::kInstallSite));
 
   run_loop.Run();
   return app_id;
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 8de74ee1..9cdc5010 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
@@ -112,8 +112,10 @@
   auto* provider = WebAppProvider::GetForWebContents(web_contents);
   DCHECK(provider);
 
-  if (provider->install_manager().IsInstallingForWebContents(web_contents))
+  if (provider->install_manager().IsInstallingForWebContents(web_contents) ||
+      provider->command_manager().IsInstallingForWebContents(web_contents)) {
     return;
+  }
 
   webapps::WebappInstallSource install_source =
       webapps::InstallableMetrics::GetInstallSource(
@@ -123,11 +125,15 @@
 
   WebAppInstalledCallback callback = base::DoNothing();
 
-  provider->install_manager().InstallWebAppFromManifestWithFallback(
-      web_contents, flow, install_source,
-      base::BindOnce(OnWebAppInstallShowInstallDialog, flow, install_source,
-                     chrome::PwaInProductHelpState::kNotShown),
-      base::BindOnce(OnWebAppInstalled, std::move(callback)));
+  provider->command_manager().ScheduleCommand(
+      std::make_unique<FetchManifestAndInstallCommand>(
+          &provider->install_finalizer(), &provider->registrar(),
+          install_source, web_contents->GetWeakPtr(),
+          /*bypass_service_worker_check=*/false,
+          base::BindOnce(OnWebAppInstallShowInstallDialog, flow, install_source,
+                         chrome::PwaInProductHelpState::kNotShown),
+          base::BindOnce(OnWebAppInstalled, std::move(callback)),
+          /*use_fallback=*/true, flow));
 }
 
 bool CreateWebAppFromManifest(content::WebContents* web_contents,
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
index 6e5f325e..d5e595a3 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -57,9 +57,7 @@
 
 namespace chromeos {
 
-// Note that show_oobe_ui_ defaults to false because WizardController assumes
-// OOBE UI is not visible by default.
-CoreOobeHandler::CoreOobeHandler() {
+CoreOobeHandler::CoreOobeHandler(const std::string& display_type) {
   ash::TabletMode::Get()->AddObserver(this);
 
   OobeConfiguration::Get()->AddAndFireObserver(this);
@@ -68,6 +66,30 @@
 
   OnKeyboardVisibilityChanged(
       ChromeKeyboardControllerClient::Get()->is_keyboard_visible());
+
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+  version_info_updater_.StartUpdate(true);
+#else
+  version_info_updater_.StartUpdate(false);
+#endif
+  UpdateClientAreaSize(
+      display::Screen::GetScreen()->GetPrimaryDisplay().size());
+
+  bool has_api_keys_configured = google_apis::HasAPIKeyConfigured() &&
+                                 google_apis::HasOAuthClientConfigured();
+  CallJS("cr.ui.Oobe.showAPIKeysNotice",
+         !has_api_keys_configured && (display_type == OobeUI::kOobeDisplay ||
+                                      display_type == OobeUI::kLoginDisplay));
+
+  // Don't show version label on the stable and beta channels by default.
+  version_info::Channel channel = chrome::GetChannel();
+  if (channel != version_info::Channel::STABLE &&
+      channel != version_info::Channel::BETA) {
+    ToggleSystemInfo();
+  }
+
+  if (system::InputDeviceSettings::Get()->ForceKeyboardDrivenUINavigation())
+    CallJS("cr.ui.Oobe.enableKeyboardFlow", true);
 }
 
 CoreOobeHandler::~CoreOobeHandler() {
@@ -101,17 +123,6 @@
   builder->Add("next", IDS_EULA_NEXT_BUTTON);
 }
 
-void CoreOobeHandler::InitializeDeprecated() {
-  UpdateOobeUIVisibility();
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  version_info_updater_.StartUpdate(true);
-#else
-  version_info_updater_.StartUpdate(false);
-#endif
-  UpdateClientAreaSize(
-      display::Screen::GetScreen()->GetPrimaryDisplay().size());
-}
-
 void CoreOobeHandler::GetAdditionalParameters(base::Value::Dict* dict) {
   dict->Set("isInTabletMode",
             base::Value(ash::TabletMode::Get()->InTabletMode()));
@@ -183,13 +194,7 @@
 }
 
 void CoreOobeHandler::ShowOobeUI(bool show) {
-  if (show == show_oobe_ui_)
-    return;
-
-  show_oobe_ui_ = show;
-
-  if (IsJavascriptAllowed())
-    UpdateOobeUIVisibility();
+  CallJS("cr.ui.Oobe.showOobeUI", show);
 }
 
 void CoreOobeHandler::SetLoginUserCount(int user_count) {
@@ -200,27 +205,6 @@
   CallJS("cr.ui.Oobe.handleAccelerator", accelerator_name);
 }
 
-void CoreOobeHandler::UpdateOobeUIVisibility() {
-  const std::string& display = GetOobeUI()->display_type();
-  bool has_api_keys_configured = google_apis::HasAPIKeyConfigured() &&
-                                 google_apis::HasOAuthClientConfigured();
-  CallJS("cr.ui.Oobe.showAPIKeysNotice",
-         !has_api_keys_configured && (display == OobeUI::kOobeDisplay ||
-                                      display == OobeUI::kLoginDisplay));
-
-  // Don't show version label on the stable channel by default.
-  bool should_show_version = true;
-  version_info::Channel channel = chrome::GetChannel();
-  if (channel == version_info::Channel::STABLE ||
-      channel == version_info::Channel::BETA) {
-    should_show_version = false;
-  }
-  CallJS("cr.ui.Oobe.showVersion", should_show_version);
-  CallJS("cr.ui.Oobe.showOobeUI", show_oobe_ui_);
-  if (system::InputDeviceSettings::Get()->ForceKeyboardDrivenUINavigation())
-    CallJS("cr.ui.Oobe.enableKeyboardFlow", true);
-}
-
 void CoreOobeHandler::OnOSVersionLabelTextUpdated(
     const std::string& os_version_label_text) {
   UpdateLabel("version", os_version_label_text);
@@ -265,6 +249,10 @@
   CallJS("cr.ui.Oobe.setDialogSize", dialog_size.width(), dialog_size.height());
 }
 
+void CoreOobeHandler::ToggleSystemInfo() {
+  CallJS("cr.ui.Oobe.toggleSystemInfo");
+}
+
 void CoreOobeHandler::OnOobeConfigurationChanged() {
   base::Value configuration(base::Value::Type::DICTIONARY);
   configuration::FilterConfiguration(
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
index 1bb0d31..cf906fe 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -38,6 +38,7 @@
   virtual void ReloadContent(base::Value::Dict dictionary) = 0;
   virtual void FocusReturned(bool reverse) = 0;
   virtual void UpdateClientAreaSize(const gfx::Size& size) = 0;
+  virtual void ToggleSystemInfo() = 0;
 };
 
 // The core handler for Javascript messages related to the "oobe" view.
@@ -49,7 +50,7 @@
                         public OobeConfiguration::Observer,
                         public ChromeKeyboardControllerClient::Observer {
  public:
-  CoreOobeHandler();
+  explicit CoreOobeHandler(const std::string& display_type);
 
   CoreOobeHandler(const CoreOobeHandler&) = delete;
   CoreOobeHandler& operator=(const CoreOobeHandler&) = delete;
@@ -59,7 +60,6 @@
   // BaseScreenHandler implementation:
   void DeclareLocalizedValues(
       ::login::LocalizedValuesBuilder* builder) override;
-  void InitializeDeprecated() override;
 
   // BaseScreenHandler implementation:
   void GetAdditionalParameters(base::Value::Dict* dict) override;
@@ -95,6 +95,7 @@
   void FocusReturned(bool reverse) override;
   // Updates client area size based on the primary screen size.
   void UpdateClientAreaSize(const gfx::Size& size) override;
+  void ToggleSystemInfo() override;
 
   // ash::TabletModeObserver:
   void OnTabletModeStarted() override;
@@ -121,15 +122,9 @@
   // to tab/shift-tab event.
   void HandleRaiseTabKeyEvent(bool reverse);
 
-  // Calls javascript to sync OOBE UI visibility with show_oobe_ui_.
-  void UpdateOobeUIVisibility();
-
   // Updates label with specified id with specified text.
   void UpdateLabel(const std::string& id, const std::string& text);
 
-  // True if we should show OOBE instead of login.
-  bool show_oobe_ui_ = false;
-
   // Updates when version info is changed.
   VersionInfoUpdater version_info_updater_{this};
 
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 96cf9ae..227bb8e 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -604,7 +604,7 @@
   LOG(WARNING) << "OobeUI created";
   display_type_ = GetDisplayType(url);
 
-  auto core_handler = std::make_unique<CoreOobeHandler>();
+  auto core_handler = std::make_unique<CoreOobeHandler>(display_type_);
   core_handler_ = core_handler.get();
 
   AddWebUIHandler(std::move(core_handler));
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 cb609f8..250305f 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
@@ -91,6 +91,11 @@
   Abort(webapps::InstallResultCode::kCancelledOnWebAppProviderShuttingDown);
 }
 
+content::WebContents*
+FetchManifestAndInstallCommand::GetInstallingWebContents() {
+  return web_contents_.get();
+}
+
 base::Value FetchManifestAndInstallCommand::ToDebugValue() const {
   auto debug_value = debug_log_.Clone();
   debug_value.Set("command_name", "FetchManifestAndInstallCommand");
@@ -165,8 +170,13 @@
   auto start_url = install_info_->start_url;
 
   if (opt_manifest) {
-    UpdateWebAppInfoFromManifest(*opt_manifest, manifest_url,
-                                 install_info_.get());
+    if (opt_manifest->start_url.is_valid())
+      install_info_->start_url = opt_manifest->start_url;
+
+    if (opt_manifest->id.has_value()) {
+      install_info_->manifest_id = absl::optional<std::string>(
+          base::UTF16ToUTF8(opt_manifest->id.value()));
+    }
     LogInstallInfo();
   }
 
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 a172c93..b5519938 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
@@ -55,6 +55,8 @@
   void OnBeforeForcedUninstallFromSync() override;
   void OnShutdown() override;
 
+  content::WebContents* GetInstallingWebContents() override;
+
   base::Value ToDebugValue() const override;
 
  private:
diff --git a/chrome/browser/web_applications/commands/web_app_command.cc b/chrome/browser/web_applications/commands/web_app_command.cc
index 1dfd208..8922f3d2 100644
--- a/chrome/browser/web_applications/commands/web_app_command.cc
+++ b/chrome/browser/web_applications/commands/web_app_command.cc
@@ -147,6 +147,10 @@
 }
 WebAppCommand::~WebAppCommand() = default;
 
+content::WebContents* WebAppCommand::GetInstallingWebContents() {
+  return nullptr;
+}
+
 void WebAppCommand::SignalCompletionAndSelfDestruct(
     CommandResult result,
     base::OnceClosure completion_callback) {
diff --git a/chrome/browser/web_applications/commands/web_app_command.h b/chrome/browser/web_applications/commands/web_app_command.h
index 2790af1..404f45ff 100644
--- a/chrome/browser/web_applications/commands/web_app_command.h
+++ b/chrome/browser/web_applications/commands/web_app_command.h
@@ -132,6 +132,11 @@
   // Returns if the command has been started yet.
   bool IsStarted() const { return command_manager_ != nullptr; }
 
+  // Returns the pre-existing web contents the installation was
+  // initiated with. Only implements this when the command is used for
+  // installation and uses a pre-existing web contents.
+  virtual content::WebContents* GetInstallingWebContents();
+
   // Returns a debug value to log the state of the command. Used in
   // chrome://web-app-internals.
   virtual base::Value ToDebugValue() const = 0;
@@ -194,7 +199,7 @@
   WebAppCommandManager* command_manager_ = nullptr;
   // Because this is owned by the command manager, it will always outlive this
   // object. Thus a raw pointer is save.
-  base::raw_ptr<content::WebContents> shared_web_contents_;
+  raw_ptr<content::WebContents> shared_web_contents_;
 
   base::WeakPtrFactory<WebAppCommand> weak_factory_{this};
 };
diff --git a/chrome/browser/web_applications/commands/web_app_install_command.cc b/chrome/browser/web_applications/commands/web_app_install_command.cc
index d9bc9e2..bbdaf33 100644
--- a/chrome/browser/web_applications/commands/web_app_install_command.cc
+++ b/chrome/browser/web_applications/commands/web_app_install_command.cc
@@ -7,8 +7,12 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/web_applications/web_app_command_manager.h"
 #include "chrome/browser/web_applications/web_app_data_retriever.h"
+#include "chrome/browser/web_applications/web_app_install_manager.h"
+#include "chrome/common/chrome_features.h"
 #include "content/public/browser/web_contents.h"
 
 namespace web_app {
@@ -61,17 +65,24 @@
   if (!install_callback_)
     return;
   webapps::InstallableMetrics::TrackInstallResult(false);
-  std::move(install_callback_).Run(app_id_, code);
-  SignalCompletionAndSelfDestruct(CommandResult::kFailure, base::DoNothing());
+  SignalCompletionAndSelfDestruct(
+      CommandResult::kFailure,
+      base::BindOnce(std::move(install_callback_), app_id_, code));
 }
 
 void WebAppInstallCommand::OnInstallCompleted(const AppId& app_id,
                                               webapps::InstallResultCode code) {
-  std::move(install_callback_).Run(app_id, code);
-  SignalCompletionAndSelfDestruct(webapps::IsSuccess(code)
-                                      ? CommandResult::kSuccess
-                                      : CommandResult::kFailure,
-                                  base::DoNothing());
+  if (base::FeatureList::IsEnabled(features::kRecordWebAppDebugInfo)) {
+    base::Value task_error_dict = install_task_.TakeErrorDict();
+    if (!task_error_dict.DictEmpty())
+      command_manager()->LogToInstallManager(std::move(task_error_dict));
+  }
+
+  webapps::InstallableMetrics::TrackInstallResult(webapps::IsSuccess(code));
+  SignalCompletionAndSelfDestruct(
+      webapps::IsSuccess(code) ? CommandResult::kSuccess
+                               : CommandResult::kFailure,
+      base::BindOnce(std::move(install_callback_), app_id, code));
 }
 
 void WebAppInstallCommand::OnBeforeForcedUninstallFromSync() {
@@ -85,6 +96,10 @@
   return;
 }
 
+content::WebContents* WebAppInstallCommand::GetInstallingWebContents() {
+  return web_contents_.get();
+}
+
 base::Value WebAppInstallCommand::ToDebugValue() const {
   return base::Value(base::StringPrintf("WebAppInstallCommand %d, app_id: %s",
                                         id(), app_id_.c_str()));
diff --git a/chrome/browser/web_applications/commands/web_app_install_command.h b/chrome/browser/web_applications/commands/web_app_install_command.h
index ba33002..779496b 100644
--- a/chrome/browser/web_applications/commands/web_app_install_command.h
+++ b/chrome/browser/web_applications/commands/web_app_install_command.h
@@ -49,6 +49,8 @@
   void OnBeforeForcedUninstallFromSync() override;
   void OnShutdown() override;
 
+  content::WebContents* GetInstallingWebContents() override;
+
   base::Value ToDebugValue() const override;
 
  private:
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
index 9571e1b8..c12c5c9 100644
--- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
+#include "chrome/browser/web_applications/commands/fetch_manifest_and_install_command.h"
 #include "chrome/browser/web_applications/externally_managed_app_manager.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/os_integration/web_app_file_handler_registration.h"
@@ -40,6 +41,7 @@
 #include "chrome/browser/web_applications/test/web_app_test_utils.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
 #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_helpers.h"
 #include "chrome/browser/web_applications/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
@@ -400,17 +402,21 @@
 
     AppId app_id;
     base::RunLoop run_loop;
-    GetProvider().install_manager().InstallWebAppFromManifestWithFallback(
-        browser()->tab_strip_model()->GetActiveWebContents(),
-        WebAppInstallFlow::kInstallSite,
-        webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
-        base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting(
-            [&](const AppId& new_app_id, webapps::InstallResultCode code) {
+    GetProvider().command_manager().ScheduleCommand(
+        std::make_unique<FetchManifestAndInstallCommand>(
+            &GetProvider().install_finalizer(), &GetProvider().registrar(),
+            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();
-            }));
+            }),
+            /*use_fallback=*/true, WebAppInstallFlow::kInstallSite));
+
     run_loop.Run();
     return app_id;
   }
diff --git a/chrome/browser/web_applications/web_app_command_manager.cc b/chrome/browser/web_applications/web_app_command_manager.cc
index dd54b4c..378fb60a 100644
--- a/chrome/browser/web_applications/web_app_command_manager.cc
+++ b/chrome/browser/web_applications/web_app_command_manager.cc
@@ -182,6 +182,25 @@
   return base::Value(std::move(state));
 }
 
+void WebAppCommandManager::SetSubsystems(
+    WebAppInstallManager* install_manager) {
+  install_manager_ = install_manager;
+}
+
+void WebAppCommandManager::LogToInstallManager(base::Value log) {
+  install_manager_->TakeCommandErrorLog(PassKey(), std::move(log));
+}
+
+bool WebAppCommandManager::IsInstallingForWebContents(
+    const content::WebContents* web_contents) const {
+  for (const auto& [id, command_state] : commands_) {
+    if (command_state.command->GetInstallingWebContents() == web_contents) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void WebAppCommandManager::OnCommandComplete(
     WebAppCommand* running_command,
     CommandResult result,
diff --git a/chrome/browser/web_applications/web_app_command_manager.h b/chrome/browser/web_applications/web_app_command_manager.h
index 4a627a2..bc052d4 100644
--- a/chrome/browser/web_applications/web_app_command_manager.h
+++ b/chrome/browser/web_applications/web_app_command_manager.h
@@ -11,8 +11,10 @@
 
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
+#include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
+#include "base/types/pass_key.h"
 #include "base/values.h"
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
@@ -29,6 +31,8 @@
 
 namespace web_app {
 
+class WebAppInstallManager;
+
 // The command manager is used to schedule commands or callbacks to write & read
 // from the WebAppProvider system. To use, simply call `ScheduleCommand` to
 // schedule the given command or a CallbackCommand with given callback.
@@ -39,6 +43,8 @@
 // until `SignalCompletionAndSelfDestruct()` was called by the last command.
 class WebAppCommandManager {
  public:
+  using PassKey = base::PassKey<WebAppCommandManager>;
+
   explicit WebAppCommandManager(Profile* profile);
   ~WebAppCommandManager();
 
@@ -59,6 +65,16 @@
   // running and queued commands.
   base::Value ToDebugValue();
 
+  void SetSubsystems(WebAppInstallManager* install_manager);
+  void LogToInstallManager(base::Value);
+
+  // Returns whether an installation is already scheduled with the same web
+  // contents.
+  bool IsInstallingForWebContents(
+      const content::WebContents* web_contents) const;
+
+  std::size_t GetCommandCountForTesting() { return commands_.size(); }
+
  protected:
   friend class WebAppCommand;
 
@@ -95,6 +111,8 @@
   content::DisjointRangeLockManager lock_manager_{
       static_cast<int>(WebAppCommandLock::LockLevel::kMaxValue) + 1};
 
+  raw_ptr<WebAppInstallManager> install_manager_;
+
   base::WeakPtrFactory<WebAppCommandManager> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc
index f7f9542..d0af3a6 100644
--- a/chrome/browser/web_applications/web_app_install_manager.cc
+++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -479,6 +479,13 @@
   }
 }
 
+void WebAppInstallManager::TakeCommandErrorLog(
+    base::PassKey<WebAppCommandManager>,
+    base::Value log) {
+  if (error_log_)
+    LogErrorObject(std::move(log));
+}
+
 void WebAppInstallManager::DeleteTask(WebAppInstallTask* task) {
   TakeTaskErrorLog(task);
   // If this happens after/during the call to Shutdown(), then ignore deletion
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h
index e1bb661..2cf2674d 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/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/types/pass_key.h"
 #include "base/values.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
@@ -38,6 +39,7 @@
 
 class WebAppInstallFinalizer;
 class OsIntegrationManager;
+class WebAppCommandManager;
 class WebAppDataRetriever;
 class WebAppInstallTask;
 class WebAppRegistrar;
@@ -153,6 +155,11 @@
   bool has_web_contents_for_testing() const { return web_contents_ != nullptr; }
   std::set<AppId> GetEnqueuedInstallAppIdsForTesting();
 
+  // TODO(crbug.com/1322974): migrate loggign to WebAppCommandManager after all
+  // tasks are migrated to the command system.
+  void TakeCommandErrorLog(base::PassKey<WebAppCommandManager>,
+                           base::Value log);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(WebAppInstallManagerTest,
                            TaskQueueWebContentsReadyRace);
diff --git a/chrome/browser/web_applications/web_app_internals_browsertest.cc b/chrome/browser/web_applications/web_app_internals_browsertest.cc
index 8848655..247626e 100644
--- a/chrome/browser/web_applications/web_app_internals_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_internals_browsertest.cc
@@ -11,10 +11,12 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
+#include "chrome/browser/web_applications/commands/fetch_manifest_and_install_command.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/test/web_app_test_utils.h"
 #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_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_params.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -89,17 +91,21 @@
 
     AppId app_id;
     base::RunLoop run_loop;
-    GetProvider().install_manager().InstallWebAppFromManifestWithFallback(
-        browser()->tab_strip_model()->GetActiveWebContents(),
-        WebAppInstallFlow::kInstallSite,
-        webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
-        base::BindOnce(test::TestAcceptDialogCallback),
-        base::BindLambdaForTesting(
-            [&](const AppId& new_app_id, webapps::InstallResultCode code) {
+    GetProvider().command_manager().ScheduleCommand(
+        std::make_unique<FetchManifestAndInstallCommand>(
+            &GetProvider().install_finalizer(), &GetProvider().registrar(),
+            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();
-            }));
+            }),
+            /*use_fallback=*/true, WebAppInstallFlow::kInstallSite));
+
     run_loop.Run();
     return app_id;
   }
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc
index 87cf14e5..d2dc1b0 100644
--- a/chrome/browser/web_applications/web_app_provider.cc
+++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -334,6 +334,7 @@
                                          ui_manager_.get(),
                                          icon_manager_.get());
 
+  command_manager_->SetSubsystems(install_manager_.get());
   connected_ = true;
 }
 
diff --git a/chrome/browser/web_applications/web_app_tab_helper.cc b/chrome/browser/web_applications/web_app_tab_helper.cc
index aea1b69..1d96e9d 100644
--- a/chrome/browser/web_applications/web_app_tab_helper.cc
+++ b/chrome/browser/web_applications/web_app_tab_helper.cc
@@ -53,10 +53,6 @@
   return audio_focus_group_id_;
 }
 
-bool WebAppTabHelper::HasLoadedNonAboutBlankPage() const {
-  return has_loaded_non_about_blank_page_;
-}
-
 WebAppLaunchQueue& WebAppTabHelper::EnsureLaunchQueue() {
   if (!launch_queue_) {
     launch_queue_ = std::make_unique<WebAppLaunchQueue>(web_contents(),
@@ -93,21 +89,32 @@
   }
 }
 
-void WebAppTabHelper::DidFinishNavigation(
-    content::NavigationHandle* navigation_handle) {
-  if (!navigation_handle->IsInPrimaryMainFrame() ||
-      !navigation_handle->HasCommitted())
-    return;
+void WebAppTabHelper::PrimaryPageChanged(content::Page& page) {
+  // This method is invoked whenever primary page of a WebContents
+  // (WebContents::GetPrimaryPage()) changes to `page`. This happens in one of
+  // the following cases:
+  // 1) when the current RenderFrameHost in the primary main frame changes after
+  //    a navigation.
+  // 2) when the current RenderFrameHost in the primary main frame is
+  //    reinitialized after a crash.
+  // 3) when a cross-document navigation commits in the current RenderFrameHost
+  //    of the primary main frame.
+  //
+  // The new primary page might either be a brand new one (if the committed
+  // navigation created a new document in the primary main frame) or an existing
+  // one (back-forward cache restore or prerendering activation).
+  //
+  // This notification is not dispatched for changes of pages in the non-primary
+  // frame trees (prerendering, fenced frames) and when the primary page is
+  // destroyed (e.g., when closing a tab).
+  //
+  // See the declaration of WebContentsObserver::PrimaryPageChanged for more
+  // information.
+  provider_->manifest_update_manager().MaybeUpdate(
+      page.GetMainDocument().GetLastCommittedURL(), GetAppId(), web_contents());
 
-  if (!navigation_handle->GetURL().IsAboutBlank())
-    has_loaded_non_about_blank_page_ = true;
-
-  is_error_page_ = navigation_handle->IsErrorPage();
-
-  provider_->manifest_update_manager().MaybeUpdate(navigation_handle->GetURL(),
-                                                   GetAppId(), web_contents());
-
-  ReinstallPlaceholderAppIfNecessary(navigation_handle->GetURL());
+  ReinstallPlaceholderAppIfNecessary(
+      page.GetMainDocument().GetLastCommittedURL());
 }
 
 void WebAppTabHelper::DidCloneToNewWebContents(
diff --git a/chrome/browser/web_applications/web_app_tab_helper.h b/chrome/browser/web_applications/web_app_tab_helper.h
index 61a363dc..63a15d6 100644
--- a/chrome/browser/web_applications/web_app_tab_helper.h
+++ b/chrome/browser/web_applications/web_app_tab_helper.h
@@ -40,7 +40,6 @@
   const AppId& GetAppId() const;
   void SetAppId(const AppId& app_id);
   const base::UnguessableToken& GetAudioFocusGroupIdForTesting() const;
-  bool HasLoadedNonAboutBlankPage() const;
 
   bool acting_as_app() const { return acting_as_app_; }
   void set_acting_as_app(bool acting_as_app) { acting_as_app_ = acting_as_app; }
@@ -50,8 +49,7 @@
   // content::WebContentsObserver:
   void ReadyToCommitNavigation(
       content::NavigationHandle* navigation_handle) override;
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override;
+  void PrimaryPageChanged(content::Page& page) override;
   void DidCloneToNewWebContents(
       content::WebContents* old_web_contents,
       content::WebContents* new_web_contents) override;
@@ -92,17 +90,10 @@
   // be false if a user types the app's URL into a normal browser window.
   bool acting_as_app_ = false;
 
-  // Indicates if the current page is an error page (e.g. the page failed to
-  // load). We store this because it isn't accessible off a |WebContents| or a
-  // |RenderFrameHost|.
-  bool is_error_page_ = false;
-
   // The audio focus group id is used to group media sessions together for apps.
   // We store the applied group id locally on the helper for testing.
   base::UnguessableToken audio_focus_group_id_ = base::UnguessableToken::Null();
 
-  bool has_loaded_non_about_blank_page_ = false;
-
   // Use unique_ptr for lazy instantiation as most browser tabs have no need to
   // incur this memory overhead.
   std::unique_ptr<WebAppLaunchQueue> launch_queue_;
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 0253cf73..e7ef495 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1651773593-a88faa6390c0d9aa66503690a46a6f0b98e3892e.profdata
+chrome-linux-main-1651816596-692ba9813b405a6ee7f50f63737bbbba963ed05a.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index e10f62a..8e43e0e 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1651795087-5c9b2dcc112ff39989d013ca045af82dba78c90b.profdata
+chrome-mac-arm-main-1651816596-085e006d36e9890184616ffe25d329b5528a265f.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 15884d61..1a63ef0 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1651795087-8aebf0ef58a841fc4df6307c36629d3b59f52cb1.profdata
+chrome-mac-main-1651816596-32b849179f5731586347ab1e3e60b44af56ec0e2.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 84605ce..ee34051 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1651697635-bf6862dd7ebeb6d97ff8dcb3555314c4670c634d.profdata
+chrome-win32-main-1651827472-b1fa1c1a3b88b9af5a90d2888a2c86dcb13cbea6.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index a3d6bbc..b82c3c6 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1651784399-ab51a2305f81007ee024530893e0d91ec68880c5.profdata
+chrome-win64-main-1651827472-925c7b569946e16b585806727bc67573580a81fc.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 329bae9..0b67f068 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -8188,7 +8188,6 @@
       "../browser/policy/client_data_delegate_desktop_unittest.cc",
       "../browser/profiles/profile_activity_metrics_recorder_unittest.cc",
       "../browser/signin/force_signin_verifier_unittest.cc",
-      "../browser/signin/signin_global_error_unittest.cc",
       "../browser/signin/signin_manager_unittest.cc",
       "../browser/signin/signin_ui_util_unittest.cc",
       "../browser/signin/signin_util_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java
index a7e6f89..5a0b317 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java
@@ -126,9 +126,19 @@
      * @return The CoreAccountInfo for the account added.
      */
     public CoreAccountInfo addAccount(String accountName) {
+        return addAccount(accountName, new AccountCapabilities(new HashMap<>()));
+    }
+
+    /**
+     * Adds an account of the given accountName and capabilities to the fake AccountManagerFacade.
+     * @return The CoreAccountInfo for the account added.
+     */
+    public CoreAccountInfo addAccount(
+            String accountName, @NonNull AccountCapabilities capabilities) {
         assert mFakeAccountInfoService != null;
-        final String baseEmail = accountName.split("@", 2)[0];
-        return addAccount(accountName, baseEmail + ".full", baseEmail + ".given", createAvatar());
+        final String baseName = accountName.split("@", 2)[0];
+        return addAccount(
+                accountName, baseName + ".full", baseName + ".given", createAvatar(), capabilities);
     }
 
     /**
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_enter_rsu_wp_disable_code_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_enter_rsu_wp_disable_code_page_test.js
index f751e68..b4927973c 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/onboarding_enter_rsu_wp_disable_code_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/onboarding_enter_rsu_wp_disable_code_page_test.js
@@ -102,14 +102,14 @@
       async () => {
         const resolver = new PromiseResolver();
         await initializeEnterRsuWpDisableCodePage('', '');
-        const expectedCode = 'rsu code';
+        const expectedCode = 'RSU CODE';
         let savedCode = '';
         service.setRsuDisableWriteProtectCode = (code) => {
           savedCode = code;
           return resolver.promise;
         };
         const rsuCodeComponent = component.shadowRoot.querySelector('#rsuCode');
-        rsuCodeComponent.value = expectedCode;
+        rsuCodeComponent.value = expectedCode.toLowerCase();
 
         const expectedResult = {foo: 'bar'};
         let savedResult;
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 660f86b..4d5bd4ab 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -6,6 +6,7 @@
 import("//build/config/ui.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//testing/test.gni")
+import("./features.gni")
 import("./tast_control.gni")
 
 if (is_chromeos_device) {
@@ -19,6 +20,11 @@
   defines = [ "CHROMEOS_IMPLEMENTATION" ]
 }
 
+buildflag_header("features") {
+  header = "features.h"
+  flags = [ "USE_REAL_CHROMEOS_SERVICES=$use_real_chromeos_services" ]
+}
+
 component("chromeos") {
   deps = [ "//chromeos/dbus/constants" ]
   sources = []
diff --git a/chromeos/ash/components/dbus/rmad/OWNERS b/chromeos/ash/components/dbus/rmad/OWNERS
index 583bca73..a8b4697 100644
--- a/chromeos/ash/components/dbus/rmad/OWNERS
+++ b/chromeos/ash/components/dbus/rmad/OWNERS
@@ -1,5 +1,5 @@
 # Primary Owners
-gavindodd@chromium.org
+gavinwill@chromium.org
 
 # Backup OWNERS
 jimmyxgong@chromium.org
diff --git a/chromeos/components/mojo_service_manager/DIR_METADATA b/chromeos/components/mojo_service_manager/DIR_METADATA
new file mode 100644
index 0000000..adf352d
--- /dev/null
+++ b/chromeos/components/mojo_service_manager/DIR_METADATA
@@ -0,0 +1,3 @@
+buganizer: {
+  component_id: 1188058
+}
diff --git a/chromeos/components/mojo_service_manager/OWNERS b/chromeos/components/mojo_service_manager/OWNERS
new file mode 100644
index 0000000..7bd7ce6c3
--- /dev/null
+++ b/chromeos/components/mojo_service_manager/OWNERS
@@ -0,0 +1,2 @@
+chungsheng@chromium.org
+hashimoto@chromium.org
diff --git a/chromeos/components/mojo_service_manager/mojom/BUILD.gn b/chromeos/components/mojo_service_manager/mojom/BUILD.gn
new file mode 100644
index 0000000..9c038a0
--- /dev/null
+++ b/chromeos/components/mojo_service_manager/mojom/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2022 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+  sources = [ "mojo_service_manager.mojom" ]
+  public_deps = [ "//mojo/public/mojom/base" ]
+
+  component_output_prefix = "chromeos_mojo_service_manager"
+  component_macro_prefix = "CHROMEOS_MOJO_SERVICE_MANAGER"
+}
diff --git a/fuchsia/mojom/OWNERS b/chromeos/components/mojo_service_manager/mojom/OWNERS
similarity index 60%
copy from fuchsia/mojom/OWNERS
copy to chromeos/components/mojo_service_manager/mojom/OWNERS
index 1feb514..c4a2530 100644
--- a/fuchsia/mojom/OWNERS
+++ b/chromeos/components/mojo_service_manager/mojom/OWNERS
@@ -1,4 +1,6 @@
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
+per-file *.mojom=file://chromeos/SECURITY_OWNERS
 per-file *_mojom_traits*.*=set noparent
 per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file://chromeos/SECURITY_OWNERS
diff --git a/chromeos/components/mojo_service_manager/mojom/mojo_service_manager.mojom b/chromeos/components/mojo_service_manager/mojom/mojo_service_manager.mojom
new file mode 100644
index 0000000..0bf932d
--- /dev/null
+++ b/chromeos/components/mojo_service_manager/mojom/mojo_service_manager.mojom
@@ -0,0 +1,163 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// API exposed by the ChromeOS mojo service manager.
+
+// NOTE: This mojom should be kept in sync with the copy in ChromeOS's repo in
+// src/platform2/mojo_service_manager/lib/mojom/service_manager.mojom
+
+module chromeos.mojo_service_manager.mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+
+// Manages services provided by processes running on the system.
+// The argument |service_name| should match the regex ([a-zA-Z0-9._\-]+).
+//
+// Next MinVersion: 1
+// Next Method ID: 4
+interface ServiceManager {
+  // Registers a service to the service manager. Callers should set disconnect
+  // handler on another end of |service_provider| to handle errors.
+  Register@0(string service_name,
+             pending_remote<ServiceProvider> service_provider);
+
+  // Requests a service from the service manager. The |receiver| will be bound
+  // to the service. In the case that the service is not registered, if
+  // |timeout| is null, the |receiver| will be bound after the service is
+  // available. If |timeout| is not null and the |receiver| cannot be bound
+  // after |timeout|, it will be reset. Callers should set disconnect handler on
+  // another end of |receiver| to handle errors.
+  Request@1(string service_name, mojo_base.mojom.TimeDelta? timeout,
+            handle<message_pipe> receiver);
+
+  // Queries the state of a service.
+  Query@2(string service_name) => (ErrorOrServiceState result);
+
+  // Registers an observer to observe the state of services. The observer can
+  // only receive the events related to the services which the callers are
+  // allowed to request. Callers should set disconnect handler on another end of
+  // |observer| to handle errors.
+  AddServiceObserver@3(pending_remote<ServiceObserver> observer);
+};
+
+// Provides services to other processes. Provider processes implement this and
+// register it to the service manager.
+//
+// Next MinVersion: 1
+// Next Method ID: 1
+interface ServiceProvider {
+  // Requests to bind the |receiver| to the corresponding mojo interface. The
+  // |client_identity| can be used to identify the requester processes.
+  // Note: the implementations can reset |receiver| to return errors. They
+  // should use the error codes defined in |ErrorCode| enum when returning
+  // errors.
+  Request@0(ProcessIdentity client_identity,
+            handle<message_pipe> receiver);
+};
+
+// Observes the service events. Requester processes implement this and register
+// it to the service manager.
+//
+// Next MinVersion: 1
+// Next Method ID: 1
+interface ServiceObserver {
+  // Is called when service events occur.
+  OnServiceEvent@0(ServiceEvent event);
+};
+
+// The identity information about a process.
+//
+// Next MinVersion: 1
+// Next Field ID: 4
+struct ProcessIdentity {
+  // The SELinux security context.
+  string security_context@0;
+  // The process id.
+  uint32 pid@1;
+  // The user / group id.
+  uint32 uid@2;
+  uint32 gid@3;
+};
+
+// The result of ServiceManager::Query.
+//
+// Next MinVersion: 1
+union ErrorOrServiceState {
+  // The result if succeeds.
+  ServiceState state;
+  // The error if fails.
+  Error error;
+};
+
+// The state of a service.
+//
+// Next MinVersion: 1
+// Next Field ID: 2
+struct ServiceState {
+  // The service is registered or not.
+  bool is_registered@0;
+  // The identity of the owner of the service. This is omitted if the service
+  // is not registered.
+  ProcessIdentity? owner@1;
+};
+
+// The event about a service.
+//
+// Next MinVersion: 1
+// Next Field ID: 3
+struct ServiceEvent {
+  [Extensible]
+  enum Type {
+    // The default value for forward compatibility. All the unknown value will
+    // be mapped to this.
+    [Default] kUnknown,
+    // The service is registered.
+    kRegistered,
+    // The service is not registered.
+    kUnRegistered,
+  };
+
+  Type type@0;
+  // The name of the service which triggers the event.
+  string service_name@1;
+  // The dispatcher of the event. It is the process which registered or
+  // unregistered the service.
+  ProcessIdentity dispatcher@2;
+};
+
+// A generic error type for functions to return error.
+//
+// Next MinVersion: 1
+// Next Field ID: 2
+struct Error {
+  ErrorCode code@0;
+  string message@1;
+};
+
+// The error code for |struct Error| and the disconnect handlers. This is used
+// in the disconnect reason of all the mojo handles (namely, message pipe,
+// receiver and remote) which are sent to |ServiceManager|.
+// Note that in the disconnect handlers, this is casted to |uint32| and has no
+// guarantee that the value can be casted back to this. Always check if the
+// value is between 1 and |ErrorCode::kMaxValue| before casting it.
+//
+// NextMinVersion: 1
+[Extensible]
+enum ErrorCode {
+  // The default value for forward compatibility. In struct |Error|, all the
+  // unknown value will be mapped to this.
+  // In disconnect handlers, if the handle is reset without a reason, the error
+  // code is 0. So this enum starts from 1 to be distinguish from that.
+  [Default] kUnknown = 1,
+  // Timeout is reached.
+  kTimeout,
+  // The caller is not permit to perform the operation.
+  kPermissionDenied,
+  // The service has already been registered.
+  kServiceHasBeenRegistered,
+  // The service cannot be found.
+  kServiceNotFound,
+  // Unexpected os error.
+  kUnexpectedOsError,
+};
diff --git a/chromeos/dbus/debug_daemon/debug_daemon_client.cc b/chromeos/dbus/debug_daemon/debug_daemon_client.cc
index 6a9dd22..8075a0eb 100644
--- a/chromeos/dbus/debug_daemon/debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon/debug_daemon_client.cc
@@ -211,16 +211,16 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void GetPerfOutput(const std::vector<std::string>& quipper_args,
-                     bool disable_cpu_idle,
+  void GetPerfOutput(base::TimeDelta duration,
+                     const std::vector<std::string>& perf_args,
                      int file_descriptor,
                      DBusMethodCallback<uint64_t> callback) override {
     DCHECK(file_descriptor);
     dbus::MethodCall method_call(debugd::kDebugdInterface,
-                                 debugd::kGetPerfOutputV2);
+                                 debugd::kGetPerfOutputFd);
     dbus::MessageWriter writer(&method_call);
-    writer.AppendArrayOfStrings(quipper_args);
-    writer.AppendBool(disable_cpu_idle);
+    writer.AppendUint32(duration.InSeconds());
+    writer.AppendArrayOfStrings(perf_args);
     writer.AppendFileDescriptor(file_descriptor);
 
     debugdaemon_proxy_->CallMethod(
diff --git a/chromeos/dbus/debug_daemon/debug_daemon_client.h b/chromeos/dbus/debug_daemon/debug_daemon_client.h
index 569a590..8b73c92 100644
--- a/chromeos/dbus/debug_daemon/debug_daemon_client.h
+++ b/chromeos/dbus/debug_daemon/debug_daemon_client.h
@@ -91,16 +91,16 @@
   virtual void GetNetworkInterfaces(
       DBusMethodCallback<std::string> callback) = 0;
 
-  // Runs perf (via quipper) with |quipper_args| and returns data collected
-  // over the passed |file_descriptor|.
+  // Runs perf (via quipper) with arguments for |duration| (converted to
+  // seconds) and returns data collected over the passed |file_descriptor|.
   // |callback| is called on the completion of the D-Bus call.
   // Note that quipper failures may occur after successfully running the D-Bus
   // method. Such errors can be detected by |file_descriptor| and all its
   // duplicates being closed with no data written.
   // This method duplicates |file_descriptor| so it's OK to close the FD without
   // waiting for the result.
-  virtual void GetPerfOutput(const std::vector<std::string>& quipper_args,
-                             bool disable_cpu_idle,
+  virtual void GetPerfOutput(base::TimeDelta duration,
+                             const std::vector<std::string>& perf_args,
                              int file_descriptor,
                              DBusMethodCallback<uint64_t> callback) = 0;
 
diff --git a/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc
index 3eab7f1..84032bc 100644
--- a/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc
@@ -110,8 +110,8 @@
 }
 
 void FakeDebugDaemonClient::GetPerfOutput(
-    const std::vector<std::string>& quipper_args,
-    bool disable_cpu_idle,
+    base::TimeDelta duration,
+    const std::vector<std::string>& perf_args,
     int file_descriptor,
     DBusMethodCallback<uint64_t> error_callback) {}
 
diff --git a/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h
index 50b083d..ea8c181 100644
--- a/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h
+++ b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h
@@ -55,8 +55,8 @@
   void SetKstaledRatio(uint8_t val, KstaledRatioCallback callback) override;
   void GetNetworkStatus(DBusMethodCallback<std::string> callback) override;
   void GetNetworkInterfaces(DBusMethodCallback<std::string> callback) override;
-  void GetPerfOutput(const std::vector<std::string>& quipper_args,
-                     bool disable_cpu_idle,
+  void GetPerfOutput(base::TimeDelta duration,
+                     const std::vector<std::string>& perf_args,
                      int file_descriptor,
                      DBusMethodCallback<uint64_t> callback) override;
   void StopPerf(uint64_t session_id, VoidDBusMethodCallback callback) override;
diff --git a/chromeos/features.gni b/chromeos/features.gni
new file mode 100644
index 0000000..02d342d
--- /dev/null
+++ b/chromeos/features.gni
@@ -0,0 +1,10 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chromeos/dbus/config/use_real_dbus_clients.gni")
+
+declare_args() {
+  # TODO(crbug/1321052): Replace use_real_dbus_clients with this.
+  use_real_chromeos_services = use_real_dbus_clients
+}
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc
index fee63d40..7c9c66696 100644
--- a/components/autofill/core/browser/form_data_importer.cc
+++ b/components/autofill/core/browser/form_data_importer.cc
@@ -120,9 +120,8 @@
 
   // Check the |ADDRESS_HOME_LINE1| requirement.
   bool is_line1_missing = false;
-  if (country.requires_line1() &&
-      profile.GetRawInfo(ADDRESS_HOME_LINE1).empty() &&
-      profile.GetRawInfo(ADDRESS_HOME_STREET_NAME).empty()) {
+  if (country.requires_line1() && !profile.HasRawInfo(ADDRESS_HOME_LINE1) &&
+      !profile.HasRawInfo(ADDRESS_HOME_STREET_NAME)) {
     if (import_log_buffer) {
       *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
                          << "Missing required ADDRESS_HOME_LINE1." << CTag{};
@@ -132,8 +131,7 @@
 
   // Check the |ADDRESS_HOME_CITY| requirement.
   bool is_city_missing = false;
-  if (country.requires_city() &&
-      profile.GetRawInfo(ADDRESS_HOME_CITY).empty()) {
+  if (country.requires_city() && !profile.HasRawInfo(ADDRESS_HOME_CITY)) {
     if (import_log_buffer) {
       *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
                          << "Missing required ADDRESS_HOME_CITY." << CTag{};
@@ -143,8 +141,7 @@
 
   // Check the |ADDRESS_HOME_STATE| requirement.
   bool is_state_missing = false;
-  if (country.requires_state() &&
-      profile.GetRawInfo(ADDRESS_HOME_STATE).empty()) {
+  if (country.requires_state() && !profile.HasRawInfo(ADDRESS_HOME_STATE)) {
     if (import_log_buffer) {
       *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
                          << "Missing required ADDRESS_HOME_STATE." << CTag{};
@@ -154,7 +151,7 @@
 
   // Check the |ADDRESS_HOME_ZIP| requirement.
   bool is_zip_missing = false;
-  if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty()) {
+  if (country.requires_zip() && !profile.HasRawInfo(ADDRESS_HOME_ZIP)) {
     if (import_log_buffer) {
       *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
                          << "Missing required ADDRESS_HOME_ZIP." << CTag{};
@@ -164,8 +161,8 @@
 
   bool is_zip_or_state_requirement_violated = false;
   if (country.requires_zip_or_state() &&
-      profile.GetRawInfo(ADDRESS_HOME_ZIP).empty() &&
-      profile.GetRawInfo(ADDRESS_HOME_STATE).empty()) {
+      !profile.HasRawInfo(ADDRESS_HOME_ZIP) &&
+      !profile.HasRawInfo(ADDRESS_HOME_STATE)) {
     if (import_log_buffer) {
       *import_log_buffer
           << LogMessage::kImportAddressProfileFromFormFailed
@@ -177,8 +174,8 @@
 
   bool is_line1_or_house_number_violated = false;
   if (country.requires_line1_or_house_number() &&
-      profile.GetRawInfo(ADDRESS_HOME_LINE1).empty() &&
-      profile.GetRawInfo(ADDRESS_HOME_HOUSE_NUMBER).empty()) {
+      !profile.HasRawInfo(ADDRESS_HOME_LINE1) &&
+      !profile.HasRawInfo(ADDRESS_HOME_HOUSE_NUMBER)) {
     if (import_log_buffer) {
       *import_log_buffer
           << LogMessage::kImportAddressProfileFromFormFailed
@@ -404,7 +401,7 @@
   // TODO(crbug.com/1297032): Cleanup `kAutofillComplementCountryCodeOnImport`
   // check when launched.
   bool should_complement_country =
-      profile.GetRawInfo(ADDRESS_HOME_COUNTRY).empty() &&
+      !profile.HasRawInfo(ADDRESS_HOME_COUNTRY) &&
       base::FeatureList::IsEnabled(
           features::kAutofillAddressProfileSavePrompt) &&
       base::FeatureList::IsEnabled(
@@ -706,7 +703,7 @@
 
     // Reject profiles with invalid country information.
     if (server_field_type == ADDRESS_HOME_COUNTRY &&
-        candidate_profile.GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
+        !candidate_profile.HasRawInfo(ADDRESS_HOME_COUNTRY)) {
       // The country code was not successfully determined from the value in
       // the country field. This can be caused by a localization that does not
       // match the |app_locale|. Try setting the value again using the
@@ -723,7 +720,7 @@
             field_type, value, page_language, VerificationStatus::kObserved);
       }
       // Check if the country code was still not determined correctly.
-      if (candidate_profile.GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
+      if (!candidate_profile.HasRawInfo(ADDRESS_HOME_COUNTRY)) {
         if (import_log_buffer) {
           *import_log_buffer << LogMessage::kImportAddressProfileFromFormFailed
                              << "Missing country." << CTag{};
diff --git a/components/autofill/core/browser/form_parsing/regex_patterns.h b/components/autofill/core/browser/form_parsing/regex_patterns.h
index a20658ab..1385b369 100644
--- a/components/autofill/core/browser/form_parsing/regex_patterns.h
+++ b/components/autofill/core/browser/form_parsing/regex_patterns.h
@@ -71,9 +71,14 @@
 // The pattern  source identifies the JSON file providing the set of parsing
 // patterns.
 enum class PatternSource {
+  // The patterns applied for most users.
   kDefault,
+  // Patterns that are being verified experimentally.
   kExperimental,
+  // One step before `kExperimental`. These patterns are used only for
+  // non-user-visible metrics.
   kNextGen,
+  // Patterns whose stability is above suspicion.
   kLegacy,
   kMaxValue = kLegacy
 };
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataBinder.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
index 07e6355f..99ba7d9 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
@@ -111,12 +111,11 @@
             AssistantCollectUserDataModel model, ViewHolder view, PropertyKey propertyKey) {
         boolean handled = updateEditors(model, propertyKey, view);
         handled = updateRootVisibility(model, propertyKey, view) || handled;
-        handled = updateSectionVisibility(model, propertyKey, view) || handled;
         handled = updateSectionTitles(model, propertyKey, view) || handled;
         handled = updateSectionContents(model, propertyKey, view) || handled;
         handled = updateSectionSelectedItem(model, propertyKey, view) || handled;
-        /* Update section paddings *after* updating section visibility. */
-        handled = updateSectionPaddings(model, propertyKey, view) || handled;
+        // Update section visibility/padding *after* updating editors and content.
+        handled = updateVisibilityAndPaddings(model, propertyKey, view) || handled;
 
         if (propertyKey == AssistantCollectUserDataModel.DELEGATE) {
             AssistantCollectUserDataDelegate collectUserDataDelegate =
@@ -358,45 +357,6 @@
     }
 
     /**
-     * Updates visibility of PR sections.
-     * @return whether the property key was handled.
-     */
-    private boolean updateSectionVisibility(
-            AssistantCollectUserDataModel model, PropertyKey propertyKey, ViewHolder view) {
-        if (propertyKey == AssistantCollectUserDataModel.REQUEST_NAME
-                || propertyKey == AssistantCollectUserDataModel.REQUEST_EMAIL
-                || propertyKey == AssistantCollectUserDataModel.REQUEST_PHONE) {
-            view.mContactDetailsSection.setVisible(shouldShowContactDetails(model));
-            return true;
-        } else if (propertyKey == AssistantCollectUserDataModel.REQUEST_PHONE_NUMBER_SEPARATELY) {
-            view.mPhoneNumberSection.setVisible(
-                    model.get(AssistantCollectUserDataModel.REQUEST_PHONE_NUMBER_SEPARATELY));
-            return true;
-        } else if (propertyKey == AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS) {
-            view.mShippingAddressSection.setVisible(
-                    model.get(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS));
-            return true;
-        } else if (propertyKey == AssistantCollectUserDataModel.REQUEST_PAYMENT) {
-            view.mPaymentMethodSection.setVisible(shouldShowPaymentInstruments(model));
-            return true;
-        } else if (propertyKey == AssistantCollectUserDataModel.SHOW_TERMS_AS_CHECKBOX) {
-            if (model.get(AssistantCollectUserDataModel.SHOW_TERMS_AS_CHECKBOX)) {
-                view.mTermsSection.getView().setVisibility(View.GONE);
-                view.mTermsAsCheckboxSection.getView().setVisibility(View.VISIBLE);
-            } else {
-                view.mTermsSection.getView().setVisibility(View.VISIBLE);
-                view.mTermsAsCheckboxSection.getView().setVisibility(View.GONE);
-            }
-            return true;
-        } else if (propertyKey == AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE) {
-            view.mLoginSection.setVisible(
-                    model.get(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE));
-            return true;
-        }
-        return false;
-    }
-
-    /**
      * Updates visibility of the root widget.
      * @return whether the property key was handled.
      */
@@ -490,25 +450,58 @@
         return false;
     }
 
+    private boolean updateVisibilityAndPaddings(
+            AssistantCollectUserDataModel model, PropertyKey propertyKey, ViewHolder view) {
+        updateSectionVisibility(model, view);
+        updateSectionPaddings(model, view);
+
+        return propertyKey == AssistantCollectUserDataModel.REQUEST_NAME
+                || propertyKey == AssistantCollectUserDataModel.REQUEST_EMAIL
+                || propertyKey == AssistantCollectUserDataModel.REQUEST_PHONE
+                || propertyKey == AssistantCollectUserDataModel.REQUEST_PHONE_NUMBER_SEPARATELY
+                || propertyKey == AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS
+                || propertyKey == AssistantCollectUserDataModel.REQUEST_PAYMENT
+                || propertyKey == AssistantCollectUserDataModel.SHOW_TERMS_AS_CHECKBOX
+                || propertyKey == AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE
+                || propertyKey == AssistantCollectUserDataModel.EXPANDED_SECTION
+                || propertyKey == AssistantCollectUserDataModel.PREPENDED_SECTIONS
+                || propertyKey == AssistantCollectUserDataModel.APPENDED_SECTIONS
+                || propertyKey == AssistantCollectUserDataModel.WEB_CONTENTS
+                || propertyKey == AssistantCollectUserDataModel.USE_GMS_CORE_EDIT_DIALOGS
+                || propertyKey == AssistantCollectUserDataModel.ADD_PAYMENT_INSTRUMENT_ACTION_TOKEN
+                || propertyKey == AssistantCollectUserDataModel.INITIALIZE_ADDRESS_COLLECTION_PARAMS
+                || propertyKey == AssistantCollectUserDataModel.AVAILABLE_CONTACTS
+                || propertyKey == AssistantCollectUserDataModel.AVAILABLE_PHONE_NUMBERS
+                || propertyKey == AssistantCollectUserDataModel.AVAILABLE_PAYMENT_INSTRUMENTS
+                || propertyKey == AssistantCollectUserDataModel.AVAILABLE_SHIPPING_ADDRESSES
+                || propertyKey == AssistantCollectUserDataModel.AVAILABLE_LOGINS;
+    }
+
+    /**
+     * Updates visibility of user data sections.
+     */
+    private void updateSectionVisibility(AssistantCollectUserDataModel model, ViewHolder view) {
+        view.mContactDetailsSection.setVisible(shouldShowContactDetails(model));
+        view.mPhoneNumberSection.setVisible(
+                model.get(AssistantCollectUserDataModel.REQUEST_PHONE_NUMBER_SEPARATELY));
+        view.mShippingAddressSection.setVisible(
+                model.get(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS));
+        view.mPaymentMethodSection.setVisible(shouldShowPaymentInstruments(model));
+        if (model.get(AssistantCollectUserDataModel.SHOW_TERMS_AS_CHECKBOX)) {
+            view.mTermsSection.setVisible(false);
+            view.mTermsAsCheckboxSection.setVisible(true);
+        } else {
+            view.mTermsSection.setVisible(true);
+            view.mTermsAsCheckboxSection.setVisible(false);
+        }
+        view.mLoginSection.setVisible(
+                model.get(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE));
+    }
+
     /**
      * Updates the paddings between sections and section dividers.
-     * @return whether the property key was handled.
      */
-    private boolean updateSectionPaddings(
-            AssistantCollectUserDataModel model, PropertyKey propertyKey, ViewHolder view) {
-        if ((propertyKey != AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS)
-                && (propertyKey != AssistantCollectUserDataModel.REQUEST_NAME)
-                && (propertyKey != AssistantCollectUserDataModel.REQUEST_EMAIL)
-                && (propertyKey != AssistantCollectUserDataModel.REQUEST_PHONE)
-                && (propertyKey != AssistantCollectUserDataModel.REQUEST_PHONE_NUMBER_SEPARATELY)
-                && (propertyKey != AssistantCollectUserDataModel.REQUEST_PAYMENT)
-                && (propertyKey != AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE)
-                && (propertyKey != AssistantCollectUserDataModel.EXPANDED_SECTION)
-                && (propertyKey != AssistantCollectUserDataModel.PREPENDED_SECTIONS)
-                && (propertyKey != AssistantCollectUserDataModel.APPENDED_SECTIONS)) {
-            return false;
-        }
-
+    private void updateSectionPaddings(AssistantCollectUserDataModel model, ViewHolder view) {
         // Update section paddings such that the first and last section are flush to the top/bottom,
         // and all other sections have the same amount of padding in-between them.
 
@@ -590,7 +583,6 @@
                 prevSectionIsExpandedOrInvisible = false;
             }
         }
-        return true;
     }
 
     /**
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataSection.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataSection.java
index d5c385a7..a2d1f784 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataSection.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantCollectUserDataSection.java
@@ -132,8 +132,14 @@
         return mSectionExpander;
     }
 
+    /**
+     * Set the view itself visible, if allowed. This can be overruled by the view deciding that
+     * it has no reason to be visible, by being empty (no items) and not having an editor.
+     *
+     * @param visible The flag to decide the visibility.
+     */
     void setVisible(boolean visible) {
-        mSectionExpander.setVisibility(visible ? View.VISIBLE : View.GONE);
+        mSectionExpander.setVisibility(visible && canBeVisible() ? View.VISIBLE : View.GONE);
     }
 
     void setDelegate(@Nullable Delegate<T> delegate) {
@@ -454,4 +460,8 @@
         view.setPadding(
                 view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), padding);
     }
+
+    private boolean canBeVisible() {
+        return !isEmpty() || getEditor() != null;
+    }
 }
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantTermsSection.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantTermsSection.java
index 530b2365f..2fd9561 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantTermsSection.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/user_data/AssistantTermsSection.java
@@ -151,4 +151,8 @@
     View getView() {
         return mView;
     }
+
+    void setVisible(boolean visible) {
+        mView.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
 }
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn
index aa6e25e..c833fb4 100644
--- a/components/autofill_assistant/browser/BUILD.gn
+++ b/components/autofill_assistant/browser/BUILD.gn
@@ -412,6 +412,8 @@
     "mock_autofill_assistant_tts_controller.h",
     "mock_client.cc",
     "mock_client.h",
+    "mock_common_dependencies.cc",
+    "mock_common_dependencies.h",
     "mock_controller_observer.cc",
     "mock_controller_observer.h",
     "mock_execution_delegate.cc",
diff --git a/components/autofill_assistant/browser/actions/collect_user_data_action.cc b/components/autofill_assistant/browser/actions/collect_user_data_action.cc
index d64a7cf..0f1e241 100644
--- a/components/autofill_assistant/browser/actions/collect_user_data_action.cc
+++ b/components/autofill_assistant/browser/actions/collect_user_data_action.cc
@@ -1432,8 +1432,9 @@
     if (proto_data.has_selected_contact_identifier()) {
       const auto& it = base::ranges::find_if(
           user_data->available_contacts_, [&](const auto& contact) {
-            return proto_data.selected_contact_identifier() ==
-                   contact->identifier.value_or(std::string());
+            return contact->identifier &&
+                   proto_data.selected_contact_identifier() ==
+                       contact->identifier;
           });
       if (it == user_data->available_contacts_.end()) {
         NOTREACHED();
diff --git a/components/autofill_assistant/browser/autofill_assistant_factory.cc b/components/autofill_assistant/browser/autofill_assistant_factory.cc
index 425214f..c3161c8 100644
--- a/components/autofill_assistant/browser/autofill_assistant_factory.cc
+++ b/components/autofill_assistant/browser/autofill_assistant_factory.cc
@@ -4,8 +4,10 @@
 
 #include "components/autofill_assistant/browser/public/autofill_assistant_factory.h"
 
+#include <memory>
+
 #include "components/autofill_assistant/browser/autofill_assistant_impl.h"
-#include "components/version_info/channel.h"
+#include "components/autofill_assistant/browser/common_dependencies.h"
 
 namespace autofill_assistant {
 
@@ -13,11 +15,9 @@
 std::unique_ptr<AutofillAssistant>
 AutofillAssistantFactory::CreateForBrowserContext(
     content::BrowserContext* browser_context,
-    version_info::Channel channel,
-    const std::string& country_code,
-    const std::string& locale) {
-  return AutofillAssistantImpl::Create(browser_context, channel, country_code,
-                                       locale);
+    std::unique_ptr<CommonDependencies> dependencies) {
+  return AutofillAssistantImpl::Create(browser_context,
+                                       std::move(dependencies));
 }
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/autofill_assistant_impl.cc b/components/autofill_assistant/browser/autofill_assistant_impl.cc
index 02732b9..ee7fa70 100644
--- a/components/autofill_assistant/browser/autofill_assistant_impl.cc
+++ b/components/autofill_assistant/browser/autofill_assistant_impl.cc
@@ -4,8 +4,10 @@
 
 #include "components/autofill_assistant/browser/autofill_assistant_impl.h"
 
+#include <memory>
 #include <vector>
 
+#include "components/autofill_assistant/browser/common_dependencies.h"
 #include "components/autofill_assistant/browser/desktop/starter_delegate_desktop.h"
 #include "components/autofill_assistant/browser/headless/external_script_controller_impl.h"
 #include "components/autofill_assistant/browser/protocol_utils.h"
@@ -16,7 +18,6 @@
 #include "components/autofill_assistant/browser/service/service_request_sender.h"
 #include "components/autofill_assistant/browser/service/service_request_sender_impl.h"
 #include "components/autofill_assistant/browser/service/simple_url_loader_factory.h"
-#include "components/version_info/channel.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_context.h"
 #include "net/http/http_status_code.h"
@@ -68,31 +69,28 @@
 // static
 std::unique_ptr<AutofillAssistantImpl> AutofillAssistantImpl::Create(
     content::BrowserContext* browser_context,
-    version_info::Channel channel,
-    const std::string& country_code,
-    const std::string& locale) {
+    std::unique_ptr<CommonDependencies> dependencies) {
   auto request_sender = std::make_unique<ServiceRequestSenderImpl>(
       browser_context,
       /* access_token_fetcher = */ nullptr,
       std::make_unique<cup::CUPImplFactory>(),
       std::make_unique<NativeURLLoaderFactory>(),
-      ApiKeyFetcher().GetAPIKey(channel));
+      ApiKeyFetcher().GetAPIKey(dependencies->GetChannel()));
   const ServerUrlFetcher& url_fetcher =
       ServerUrlFetcher(ServerUrlFetcher::GetDefaultServerUrl());
+
   return std::make_unique<AutofillAssistantImpl>(
-      std::move(request_sender), url_fetcher.GetCapabilitiesByHashEndpoint(),
-      country_code, locale);
+      std::move(request_sender), std::move(dependencies),
+      url_fetcher.GetCapabilitiesByHashEndpoint());
 }
 
 AutofillAssistantImpl::AutofillAssistantImpl(
     std::unique_ptr<ServiceRequestSender> request_sender,
-    const GURL& script_server_url,
-    const std::string& country_code,
-    const std::string& locale)
+    std::unique_ptr<CommonDependencies> dependencies,
+    const GURL& script_server_url)
     : request_sender_(std::move(request_sender)),
       script_server_url_(script_server_url),
-      country_code_(country_code),
-      locale_(locale) {}
+      dependencies_(std::move(dependencies)) {}
 
 AutofillAssistantImpl::~AutofillAssistantImpl() = default;
 
@@ -106,10 +104,11 @@
           {kIntentScriptParameterKey, intent}}};
 
   ClientContextProto client_context;
-  client_context.set_country(country_code_);
-  client_context.set_locale(locale_);
+  client_context.set_country(dependencies_->GetCountryCode());
+  client_context.set_locale(dependencies_->GetLocale());
   client_context.mutable_chrome()->set_chrome_version(
       version_info::GetProductNameAndVersionForUserAgent());
+
 #if BUILDFLAG(IS_ANDROID)
   client_context.set_platform_type(ClientContextProto::PLATFORM_TYPE_ANDROID);
 #endif
diff --git a/components/autofill_assistant/browser/autofill_assistant_impl.h b/components/autofill_assistant/browser/autofill_assistant_impl.h
index 4f12715..3f71057 100644
--- a/components/autofill_assistant/browser/autofill_assistant_impl.h
+++ b/components/autofill_assistant/browser/autofill_assistant_impl.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_AUTOFILL_ASSISTANT_IMPL_H_
 #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_AUTOFILL_ASSISTANT_IMPL_H_
 
+#include <memory>
 #include <vector>
 
 #include "components/autofill_assistant/browser/public/autofill_assistant.h"
@@ -15,21 +16,21 @@
 
 namespace autofill_assistant {
 
+class CommonDependencies;
+
 class AutofillAssistantImpl : public autofill_assistant::AutofillAssistant {
  public:
   static std::unique_ptr<AutofillAssistantImpl> Create(
       content::BrowserContext* browser_context,
-      version_info::Channel channel,
-      const std::string& country_code,
-      const std::string& locale);
+      std::unique_ptr<CommonDependencies> dependencies);
 
   AutofillAssistantImpl(std::unique_ptr<ServiceRequestSender> request_sender,
-                        const GURL& script_server_url,
-                        const std::string& country_code,
-                        const std::string& locale);
+                        std::unique_ptr<CommonDependencies> dependencies,
+                        const GURL& script_server_url);
+  ~AutofillAssistantImpl() override;
+
   AutofillAssistantImpl(const AutofillAssistantImpl&) = delete;
   AutofillAssistantImpl& operator=(const AutofillAssistantImpl&) = delete;
-  ~AutofillAssistantImpl() override;
 
   void GetCapabilitiesByHashPrefix(
       uint32_t hash_prefix_length,
@@ -44,12 +45,12 @@
  private:
   // The request sender responsible for communicating with a remote endpoint.
   std::unique_ptr<ServiceRequestSender> request_sender_;
+
   // The RPC endpoint to send requests to.
   GURL script_server_url_;
-  // The client's country code.
-  std::string country_code_;
-  // The client's locale.
-  std::string locale_;
+
+  // Dependencies on client code such as country code or locale.
+  std::unique_ptr<CommonDependencies> dependencies_;
 };
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/autofill_assistant_impl_unittest.cc b/components/autofill_assistant/browser/autofill_assistant_impl_unittest.cc
index 65d49dd..477cf87d 100644
--- a/components/autofill_assistant/browser/autofill_assistant_impl_unittest.cc
+++ b/components/autofill_assistant/browser/autofill_assistant_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/test/gmock_callback_support.h"
 #include "base/test/mock_callback.h"
+#include "components/autofill_assistant/browser/mock_common_dependencies.h"
 #include "components/autofill_assistant/browser/service.pb.h"
 #include "components/autofill_assistant/browser/service/mock_service_request_sender.h"
 #include "components/version_info/version_info.h"
@@ -32,8 +33,14 @@
         std::make_unique<NiceMock<MockServiceRequestSender>>();
     mock_request_sender_ = mock_request_sender.get();
 
+    auto mock_common_dependencies = std::make_unique<MockCommonDependencies>();
+    mock_dependencies_ = mock_common_dependencies.get();
+    ON_CALL(*mock_dependencies_, GetCountryCode).WillByDefault(Return("US"));
+    ON_CALL(*mock_dependencies_, GetLocale).WillByDefault(Return("en-US"));
+
     service_ = std::make_unique<AutofillAssistantImpl>(
-        std::move(mock_request_sender), GURL(kScriptServerUrl), "US", "en-US");
+        std::move(mock_request_sender), std::move(mock_common_dependencies),
+        GURL(kScriptServerUrl));
   }
   ~AutofillAssistantImpTest() override = default;
 
@@ -41,6 +48,7 @@
   base::MockCallback<AutofillAssistant::GetCapabilitiesResponseCallback>
       mock_response_callback_;
   raw_ptr<NiceMock<MockServiceRequestSender>> mock_request_sender_;
+  raw_ptr<MockCommonDependencies> mock_dependencies_;
   std::unique_ptr<AutofillAssistantImpl> service_;
 };
 
diff --git a/components/autofill_assistant/browser/mock_common_dependencies.cc b/components/autofill_assistant/browser/mock_common_dependencies.cc
new file mode 100644
index 0000000..2ac0434
--- /dev/null
+++ b/components/autofill_assistant/browser/mock_common_dependencies.cc
@@ -0,0 +1,13 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/mock_common_dependencies.h"
+
+namespace autofill_assistant {
+
+MockCommonDependencies::MockCommonDependencies() = default;
+
+MockCommonDependencies::~MockCommonDependencies() = default;
+
+}  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/mock_common_dependencies.h b/components/autofill_assistant/browser/mock_common_dependencies.h
new file mode 100644
index 0000000..e0c59d58
--- /dev/null
+++ b/components/autofill_assistant/browser/mock_common_dependencies.h
@@ -0,0 +1,51 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_COMMON_DEPENDENCIES_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_COMMON_DEPENDENCIES_H_
+
+#include "components/autofill_assistant/browser/assistant_field_trial_util.h"
+#include "components/autofill_assistant/browser/common_dependencies.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+
+class MockCommonDependencies : public CommonDependencies {
+ public:
+  MockCommonDependencies();
+  ~MockCommonDependencies() override;
+
+  MOCK_METHOD(std::unique_ptr<AssistantFieldTrialUtil>,
+              CreateFieldTrialUtil,
+              (),
+              (const override));
+  MOCK_METHOD(std::string, GetLocale, (), (const override));
+  MOCK_METHOD(std::string, GetCountryCode, (), (const override));
+  MOCK_METHOD(autofill::PersonalDataManager*,
+              GetPersonalDataManager,
+              (),
+              (const override));
+  MOCK_METHOD(password_manager::PasswordManagerClient*,
+              GetPasswordManagerClient,
+              (content::WebContents*),
+              (const override));
+  MOCK_METHOD(std::string,
+              GetSignedInEmail,
+              (content::WebContents*),
+              (const override));
+  MOCK_METHOD(AnnotateDomModelService*,
+              GetOrCreateAnnotateDomModelService,
+              (content::BrowserContext*),
+              (const override));
+  MOCK_METHOD(bool, IsWebLayer, (), (const override));
+  MOCK_METHOD(signin::IdentityManager*,
+              GetIdentityManager,
+              (content::BrowserContext*),
+              (const override));
+  MOCK_METHOD(version_info::Channel, GetChannel, (), (const override));
+};
+
+}  // namespace autofill_assistant
+
+#endif  // #COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_COMMON_DEPENDENCIES_H_
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc
index cd8baab..46a68cdf 100644
--- a/components/autofill_assistant/browser/protocol_utils.cc
+++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -958,15 +958,23 @@
     bool request_email,
     bool request_phone,
     bool request_shipping,
+    const std::vector<std::string>& preexisting_address_ids,
     bool request_payment_methods,
     const std::vector<std::string>& supported_card_networks,
+    const std::vector<std::string>& preexisting_payment_instrument_ids,
     const std::string& client_token) {
   GetUserDataRequestProto request_proto;
   request_proto.set_run_id(run_id);
   request_proto.set_request_name(request_name);
   request_proto.set_request_email(request_email);
   request_proto.set_request_phone(request_phone);
-  request_proto.set_request_addresses(request_shipping);
+
+  if (request_shipping) {
+    auto* address_request = request_proto.mutable_request_shipping_addresses();
+    for (const std::string& id : preexisting_address_ids) {
+      address_request->add_preexisting_ids(id);
+    }
+  }
 
   if (request_payment_methods) {
     auto* payment_methods_request =
@@ -976,6 +984,9 @@
       payment_methods_request->add_supported_card_networks(
           supported_card_network);
     }
+    for (const std::string& id : preexisting_payment_instrument_ids) {
+      payment_methods_request->add_preexisting_ids(id);
+    }
   }
 
   std::string serialized_request_proto;
diff --git a/components/autofill_assistant/browser/protocol_utils.h b/components/autofill_assistant/browser/protocol_utils.h
index f3f885f..ab906e3 100644
--- a/components/autofill_assistant/browser/protocol_utils.h
+++ b/components/autofill_assistant/browser/protocol_utils.h
@@ -81,8 +81,10 @@
       bool request_email,
       bool request_phone,
       bool request_shipping,
+      const std::vector<std::string>& preexisting_address_ids,
       bool request_payment_methods,
       const std::vector<std::string>& supported_card_networks,
+      const std::vector<std::string>& preexisting_payment_instrument_ids,
       const std::string& client_token);
 
   // Create an action from the |action|.
diff --git a/components/autofill_assistant/browser/protocol_utils_unittest.cc b/components/autofill_assistant/browser/protocol_utils_unittest.cc
index 7ce0b5d..4438fd4 100644
--- a/components/autofill_assistant/browser/protocol_utils_unittest.cc
+++ b/components/autofill_assistant/browser/protocol_utils_unittest.cc
@@ -604,28 +604,39 @@
   GetUserDataRequestProto request;
   EXPECT_TRUE(request.ParseFromString(ProtocolUtils::CreateGetUserDataRequest(
       /* run_id= */ 1, /* request_name= */ true, /* request_email= */ true,
-      /* request_phone= */ true, /* request_shipping= */ true,
+      /* request_phone= */ true, /* request_shipping= */ false,
+      /* preexisting_address_ids= */ std::vector<std::string>(),
       /* request_payment_methods= */ false,
       /* supported_card_networks= */ std::vector<std::string>(),
+      /* preexisting_payment_instrument_ids= */ std::vector<std::string>(),
       /* client_token= */ std::string())));
   EXPECT_EQ(request.run_id(), 1u);
   EXPECT_TRUE(request.request_name());
   EXPECT_TRUE(request.request_email());
   EXPECT_TRUE(request.request_phone());
-  EXPECT_TRUE(request.request_addresses());
+  EXPECT_FALSE(request.has_request_shipping_addresses());
   EXPECT_FALSE(request.has_request_payment_methods());
 
   EXPECT_TRUE(request.ParseFromString(ProtocolUtils::CreateGetUserDataRequest(
       /* run_id= */ 1, /* request_name= */ true, /* request_email= */ true,
       /* request_phone= */ true, /* request_shipping= */ true,
+      /* preexisting_address_ids= */
+      std::vector<std::string>({"address-1", "address-2"}),
       /* request_payment_methods= */ true,
       /* supported_card_networks= */
       std::vector<std::string>({"VISA", "MASTERCARD"}),
+      /* preexisting_payment_instrument_ids= */
+      std::vector<std::string>({"instrument-1", "instrument-2"}),
       /* client_token= */ "token")));
+  EXPECT_TRUE(request.has_request_shipping_addresses());
+  EXPECT_THAT(request.request_shipping_addresses().preexisting_ids(),
+              ElementsAre("address-1", "address-2"));
   EXPECT_TRUE(request.has_request_payment_methods());
   EXPECT_EQ(request.request_payment_methods().client_token(), "token");
   EXPECT_THAT(request.request_payment_methods().supported_card_networks(),
               ElementsAre("VISA", "MASTERCARD"));
+  EXPECT_THAT(request.request_payment_methods().preexisting_ids(),
+              ElementsAre("instrument-1", "instrument-2"));
 }
 
 TEST_F(ProtocolUtilsTest, ComputeNetworkStats) {
diff --git a/components/autofill_assistant/browser/public/autofill_assistant_factory.h b/components/autofill_assistant/browser/public/autofill_assistant_factory.h
index b7befe6f..3ab5853 100644
--- a/components/autofill_assistant/browser/public/autofill_assistant_factory.h
+++ b/components/autofill_assistant/browser/public/autofill_assistant_factory.h
@@ -5,12 +5,17 @@
 #ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_PUBLIC_AUTOFILL_ASSISTANT_FACTORY_H_
 #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_PUBLIC_AUTOFILL_ASSISTANT_FACTORY_H_
 
+#include <memory>
+
 #include "components/autofill_assistant/browser/public/autofill_assistant.h"
 #include "components/version_info/channel.h"
 #include "content/public/browser/browser_context.h"
 
 namespace autofill_assistant {
-// Creates an instance of |AutofillAssistant|.
+
+class CommonDependencies;
+
+// Factory class for creating |AutofillAssistant|.
 class AutofillAssistantFactory {
  public:
   // TODO(b/201964911) The |AutofillAssistant::CreateExternalScriptController|
@@ -20,9 +25,7 @@
   // |AutofillAssistant::GetCapabilitiesByHashPrefix| as well.
   static std::unique_ptr<AutofillAssistant> CreateForBrowserContext(
       content::BrowserContext* browser_context,
-      version_info::Channel channel,
-      const std::string& country_code,
-      const std::string& locale);
+      std::unique_ptr<CommonDependencies> dependencies);
 };
 }  // namespace autofill_assistant
 
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 37480b2f..0acb37d 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -1085,7 +1085,7 @@
 
   delegate_->EnterState(AutofillAssistantState::RUNNING);
   service->GetUserData(
-      options, run_id_,
+      options, run_id_, user_data_,
       base::BindOnce(&ScriptExecutor::OnRequestUserData,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc
index 21a67bb..8d6c072d 100644
--- a/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -2252,7 +2252,7 @@
 
 TEST_F(ScriptExecutorTest, RequestUserData) {
   EXPECT_CALL(mock_service_, GetUserData)
-      .WillOnce(RunOnceCallback<2>(net::HTTP_OK, "",
+      .WillOnce(RunOnceCallback<3>(net::HTTP_OK, std::string(),
                                    ServiceRequestSender::ResponseInfo{}));
 
   base::MockCallback<
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index 361e7e11..fc4375e 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -241,6 +241,12 @@
     optional bytes client_token = 1;
     // The list of supported card networks.
     repeated string supported_card_networks = 2;
+    // The list of known payment instruments from a previous call.
+    repeated string preexisting_ids = 3;
+  }
+  message AddressRequest {
+    // The list of known addresses from a previous call.
+    repeated string preexisting_ids = 1;
   }
 
   // For logging, to know which run this request has originated from.
@@ -249,10 +255,10 @@
   optional bool request_name = 2;
   optional bool request_email = 3;
   optional bool request_phone = 4;
-  optional bool request_addresses = 5;
+  optional AddressRequest request_shipping_addresses = 8;
   optional PaymentMethodRequest request_payment_methods = 7;
 
-  reserved 6;
+  reserved 5, 6;
 }
 
 // Response with user data.
diff --git a/components/autofill_assistant/browser/service/java_service.cc b/components/autofill_assistant/browser/service/java_service.cc
index 754cd68e..46eb329 100644
--- a/components/autofill_assistant/browser/service/java_service.cc
+++ b/components/autofill_assistant/browser/service/java_service.cc
@@ -94,6 +94,7 @@
 
 void JavaService::GetUserData(const CollectUserDataOptions& options,
                               uint64_t run_id,
+                              const UserData* user_data,
                               ServiceRequestSender::ResponseCallback callback) {
   JNIEnv* env = base::android::AttachCurrentThread();
   auto jresponse =
diff --git a/components/autofill_assistant/browser/service/java_service.h b/components/autofill_assistant/browser/service/java_service.h
index 471859f4..3828fba1 100644
--- a/components/autofill_assistant/browser/service/java_service.h
+++ b/components/autofill_assistant/browser/service/java_service.h
@@ -60,6 +60,7 @@
   // Get user data.
   void GetUserData(const CollectUserDataOptions& options,
                    uint64_t run_id,
+                   const UserData* user_data,
                    ServiceRequestSender::ResponseCallback callback) override;
 
  private:
diff --git a/components/autofill_assistant/browser/service/java_test_endpoint_service.cc b/components/autofill_assistant/browser/service/java_test_endpoint_service.cc
index b4020f97..7d04fca 100644
--- a/components/autofill_assistant/browser/service/java_test_endpoint_service.cc
+++ b/components/autofill_assistant/browser/service/java_test_endpoint_service.cc
@@ -125,8 +125,9 @@
 void JavaTestEndpointService::GetUserData(
     const CollectUserDataOptions& options,
     uint64_t run_id,
+    const UserData* user_data,
     ServiceRequestSender::ResponseCallback callback) {
-  service_impl_->GetUserData(options, run_id, std::move(callback));
+  service_impl_->GetUserData(options, run_id, user_data, std::move(callback));
 }
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/service/java_test_endpoint_service.h b/components/autofill_assistant/browser/service/java_test_endpoint_service.h
index 3e05aa34..7ec5da03 100644
--- a/components/autofill_assistant/browser/service/java_test_endpoint_service.h
+++ b/components/autofill_assistant/browser/service/java_test_endpoint_service.h
@@ -49,6 +49,7 @@
 
   void GetUserData(const CollectUserDataOptions& options,
                    uint64_t run_id,
+                   const UserData* user_data,
                    ServiceRequestSender::ResponseCallback callback) override;
 
  private:
diff --git a/components/autofill_assistant/browser/service/mock_service.h b/components/autofill_assistant/browser/service/mock_service.h
index cf6deed..361505e7 100644
--- a/components/autofill_assistant/browser/service/mock_service.h
+++ b/components/autofill_assistant/browser/service/mock_service.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "components/autofill_assistant/browser/service/service.h"
+#include "components/autofill_assistant/browser/user_data.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace autofill_assistant {
@@ -51,6 +52,7 @@
               GetUserData,
               (const CollectUserDataOptions& options,
                uint64_t run_id,
+               const UserData* user_data,
                ServiceRequestSender::ResponseCallback callback),
               (override));
 };
diff --git a/components/autofill_assistant/browser/service/service.h b/components/autofill_assistant/browser/service/service.h
index d2bf64ee..b7bb5572 100644
--- a/components/autofill_assistant/browser/service/service.h
+++ b/components/autofill_assistant/browser/service/service.h
@@ -55,6 +55,7 @@
   // Get user data.
   virtual void GetUserData(const CollectUserDataOptions& options,
                            uint64_t run_id,
+                           const UserData* user_data,
                            ServiceRequestSender::ResponseCallback callback) = 0;
 
  protected:
diff --git a/components/autofill_assistant/browser/service/service_impl.cc b/components/autofill_assistant/browser/service/service_impl.cc
index 323405d..44d6dd5 100644
--- a/components/autofill_assistant/browser/service/service_impl.cc
+++ b/components/autofill_assistant/browser/service/service_impl.cc
@@ -144,7 +144,24 @@
 
 void ServiceImpl::GetUserData(const CollectUserDataOptions& options,
                               uint64_t run_id,
+                              const UserData* user_data,
                               ServiceRequestSender::ResponseCallback callback) {
+  std::vector<std::string> preexisting_address_ids;
+  std::vector<std::string> preexisting_payment_instrument_ids;
+  if (user_data) {
+    for (const auto& address : user_data->available_addresses_) {
+      if (address->identifier.has_value()) {
+        preexisting_address_ids.emplace_back(*address->identifier);
+      }
+    }
+    for (const auto& instrument : user_data->available_payment_instruments_) {
+      if (instrument->identifier.has_value()) {
+        preexisting_payment_instrument_ids.emplace_back(
+            *instrument->identifier);
+      }
+    }
+  }
+
   if (options.request_payment_method) {
     // We do not cache the payments client token. It could go stale (in practice
     // it currently doesn't). Getting the token is little overhead.
@@ -152,17 +169,18 @@
         &ServiceImpl::SendUserDataRequest, weak_ptr_factory_.GetWeakPtr(),
         run_id, options.request_payer_name, options.request_payer_email,
         options.request_payer_phone || options.request_phone_number_separately,
-        options.request_shipping, options.request_payment_method,
-        options.supported_basic_card_networks, std::move(callback)));
+        options.request_shipping, preexisting_address_ids,
+        options.request_payment_method, options.supported_basic_card_networks,
+        preexisting_payment_instrument_ids, std::move(callback)));
     return;
   }
 
   SendUserDataRequest(
       run_id, options.request_payer_name, options.request_payer_email,
       options.request_payer_phone || options.request_phone_number_separately,
-      options.request_shipping, options.request_payment_method,
-      options.supported_basic_card_networks, std::move(callback),
-      std::string());
+      options.request_shipping, preexisting_address_ids,
+      options.request_payment_method, options.supported_basic_card_networks,
+      preexisting_payment_instrument_ids, std::move(callback), std::string());
 }
 
 void ServiceImpl::SendUserDataRequest(
@@ -171,15 +189,19 @@
     bool request_email,
     bool request_phone,
     bool request_shipping,
+    const std::vector<std::string>& preexisting_address_ids,
     bool request_payment_methods,
     const std::vector<std::string>& supported_card_networks,
+    const std::vector<std::string>& preexisting_payment_instrument_ids,
     ServiceRequestSender::ResponseCallback callback,
     const std::string& client_token) {
   request_sender_->SendRequest(
       user_data_url_,
       ProtocolUtils::CreateGetUserDataRequest(
           run_id, request_name, request_email, request_phone, request_shipping,
-          request_payment_methods, supported_card_networks, client_token),
+          preexisting_address_ids, request_payment_methods,
+          supported_card_networks, preexisting_payment_instrument_ids,
+          client_token),
       ServiceRequestSender::AuthMode::OAUTH_STRICT, std::move(callback),
       RpcType::GET_USER_DATA);
 }
diff --git a/components/autofill_assistant/browser/service/service_impl.h b/components/autofill_assistant/browser/service/service_impl.h
index 8eab9725..0009835f 100644
--- a/components/autofill_assistant/browser/service/service_impl.h
+++ b/components/autofill_assistant/browser/service/service_impl.h
@@ -18,6 +18,7 @@
 #include "components/autofill_assistant/browser/service/server_url_fetcher.h"
 #include "components/autofill_assistant/browser/service/service.h"
 #include "components/autofill_assistant/browser/service/service_request_sender.h"
+#include "components/autofill_assistant/browser/user_data.h"
 #include "components/signin/public/identity_manager/access_token_fetcher.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "services/network/public/cpp/simple_url_loader.h"
@@ -87,6 +88,7 @@
 
   void GetUserData(const CollectUserDataOptions& options,
                    uint64_t run_id,
+                   const UserData* user_data,
                    ServiceRequestSender::ResponseCallback callback) override;
 
  private:
@@ -96,8 +98,10 @@
       bool request_email,
       bool request_phone,
       bool request_shipping,
+      const std::vector<std::string>& preexisting_address_ids,
       bool request_payment_methods,
       const std::vector<std::string>& supported_card_networks,
+      const std::vector<std::string>& preexisting_payment_instrument_ids,
       ServiceRequestSender::ResponseCallback callback,
       const std::string& client_token);
 
diff --git a/components/autofill_assistant/browser/service/service_impl_unittest.cc b/components/autofill_assistant/browser/service/service_impl_unittest.cc
index b253073..4498656 100644
--- a/components/autofill_assistant/browser/service/service_impl_unittest.cc
+++ b/components/autofill_assistant/browser/service/service_impl_unittest.cc
@@ -40,8 +40,12 @@
   return ProtocolUtils::CreateGetUserDataRequest(
       run_id, /* request_name= */ false, /* request_email= */ false,
       /* request_phone= */ false,
-      /* request_shipping= */ false, request_payment_methods,
-      /* supported_card_networks= */ {}, client_token);
+      /* request_shipping= */ false,
+      /* preexisting_address_ids= */ std::vector<std::string>(),
+      request_payment_methods,
+      /* supported_card_networks= */ std::vector<std::string>(),
+      /* preexisting_payment_instrument_ids= */ std::vector<std::string>(),
+      client_token);
 }
 
 class ServiceImplTest : public testing::Test {
@@ -226,7 +230,8 @@
   EXPECT_CALL(mock_response_callback_,
               Run(net::HTTP_OK, std::string("response"), _));
 
-  service_->GetUserData(options, run_id, mock_response_callback_.Get());
+  service_->GetUserData(options, run_id, /* user_data= */ nullptr,
+                        mock_response_callback_.Get());
 }
 
 TEST_F(ServiceImplTest, GetUserDataWithoutPayments) {
@@ -237,7 +242,7 @@
   EXPECT_CALL(*mock_request_sender_,
               OnSendRequest(GURL(kUserDataServerUrl),
                             ExpectedGetUserDataRequestBody(
-                                run_id, /* client_token= */ "",
+                                run_id, /* client_token= */ std::string(),
                                 options.request_payment_method),
                             _, RpcType::GET_USER_DATA))
       .WillOnce(RunOnceCallback<2>(net::HTTP_OK, std::string("response"),
@@ -245,7 +250,8 @@
   EXPECT_CALL(mock_response_callback_,
               Run(net::HTTP_OK, std::string("response"), _));
 
-  service_->GetUserData(options, run_id, mock_response_callback_.Get());
+  service_->GetUserData(options, run_id, /* user_data= */ nullptr,
+                        mock_response_callback_.Get());
 }
 
 }  // namespace
diff --git a/components/autofill_assistant/content/browser/BUILD.gn b/components/autofill_assistant/content/browser/BUILD.gn
index 592b8eb..17df1b0 100644
--- a/components/autofill_assistant/content/browser/BUILD.gn
+++ b/components/autofill_assistant/content/browser/BUILD.gn
@@ -15,6 +15,7 @@
   deps = [
     "//base",
     "//components/autofill_assistant/content/common:mojo_interfaces",
+    "//components/autofill_assistant/content/common/proto:proto",
     "//components/keyed_service/core",
     "//components/optimization_guide/core",
     "//components/optimization_guide/proto:optimization_guide_proto",
diff --git a/components/autofill_assistant/content/browser/content_autofill_assistant_driver.cc b/components/autofill_assistant/content/browser/content_autofill_assistant_driver.cc
index 79e42a9..8118c59 100644
--- a/components/autofill_assistant/content/browser/content_autofill_assistant_driver.cc
+++ b/components/autofill_assistant/content/browser/content_autofill_assistant_driver.cc
@@ -7,6 +7,7 @@
 #include "base/files/file.h"
 #include "base/guid.h"
 #include "base/location.h"
+#include "components/autofill_assistant/content/common/proto/semantic_feature_overrides.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 
@@ -77,13 +78,15 @@
     GetAnnotateDomModelCallback callback) {
   if (!annotate_dom_model_service_) {
     NOTREACHED() << "No model service";
-    std::move(callback).Run(mojom::ModelStatus::kUnexpectedError, base::File());
+    std::move(callback).Run(mojom::ModelStatus::kUnexpectedError, base::File(),
+                            GetOverridesPolicy());
     return;
   }
 
   absl::optional<base::File> file = annotate_dom_model_service_->GetModelFile();
   if (file) {
-    std::move(callback).Run(mojom::ModelStatus::kSuccess, *std::move(file));
+    std::move(callback).Run(mojom::ModelStatus::kSuccess, *std::move(file),
+                            GetOverridesPolicy());
     return;
   }
 
@@ -129,7 +132,8 @@
   }
 
   DCHECK(it->second->callback_);
-  std::move(it->second->callback_).Run(model_status, std::move(model_file));
+  std::move(it->second->callback_)
+      .Run(model_status, std::move(model_file), GetOverridesPolicy());
   pending_calls_.erase(it);
 }
 
@@ -139,4 +143,15 @@
   annotate_dom_model_service_ = annotate_dom_model_service;
 }
 
+std::string ContentAutofillAssistantDriver::GetOverridesPolicy() const {
+  // TODO(b/228987849): Finish the plumbing by fetching the overrides data from
+  // the service.
+  std::string policy;
+  SemanticSelectorPolicy policy_proto;
+  if (!policy_proto.SerializeToString(&policy)) {
+    return std::string();
+  }
+  return policy;
+}
+
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/content/browser/content_autofill_assistant_driver.h b/components/autofill_assistant/content/browser/content_autofill_assistant_driver.h
index 69b8102..c9bc30a 100644
--- a/components/autofill_assistant/content/browser/content_autofill_assistant_driver.h
+++ b/components/autofill_assistant/content/browser/content_autofill_assistant_driver.h
@@ -68,6 +68,7 @@
   void RunCallback(const std::string& guid,
                    mojom::ModelStatus model_status,
                    base::File model_file);
+  std::string GetOverridesPolicy() const;
 
   raw_ptr<AnnotateDomModelService> annotate_dom_model_service_ = nullptr;
 
diff --git a/components/autofill_assistant/content/browser/content_autofill_assistant_driver_unittest.cc b/components/autofill_assistant/content/browser/content_autofill_assistant_driver_unittest.cc
index d83ac8b1..1fa0bd2 100644
--- a/components/autofill_assistant/content/browser/content_autofill_assistant_driver_unittest.cc
+++ b/components/autofill_assistant/content/browser/content_autofill_assistant_driver_unittest.cc
@@ -67,29 +67,29 @@
   std::unique_ptr<ContentAutofillAssistantDriver> driver_;
   std::unique_ptr<AnnotateDomModelService> annotate_dom_model_service_;
   base::File model_file_;
+
+  base::MockCallback<base::OnceCallback<
+      void(mojom::ModelStatus, base::File, const std::string&)>>
+      callback_;
 };
 
 TEST_F(ContentAutofillAssistantDriverTest, GetLoadedModelFromService) {
   // Model has been loaded before.
   annotate_dom_model_service_->SetModelFileForTest(model_file_.Duplicate());
 
-  base::MockCallback<base::OnceCallback<void(mojom::ModelStatus, base::File)>>
-      callback;
-  EXPECT_CALL(callback, Run(mojom::ModelStatus::kSuccess, _));
+  EXPECT_CALL(callback_, Run(mojom::ModelStatus::kSuccess, _, _));
 
   driver_->GetAnnotateDomModel(/* timeout= */ base::Milliseconds(1000),
-                               callback.Get());
+                               callback_.Get());
 
   EXPECT_FALSE(HasPendingCallbacks());
 }
 
 TEST_F(ContentAutofillAssistantDriverTest, GetModelFromServiceAfterLoading) {
-  base::MockCallback<base::OnceCallback<void(mojom::ModelStatus, base::File)>>
-      callback;
-  EXPECT_CALL(callback, Run(mojom::ModelStatus::kSuccess, _));
+  EXPECT_CALL(callback_, Run(mojom::ModelStatus::kSuccess, _, _));
 
   driver_->GetAnnotateDomModel(/* timeout= */ base::Milliseconds(1000),
-                               callback.Get());
+                               callback_.Get());
 
   // Model loaded after being requested.
   annotate_dom_model_service_->SetModelFileForTest(model_file_.Duplicate());
@@ -98,12 +98,10 @@
 }
 
 TEST_F(ContentAutofillAssistantDriverTest, GetModelTimesOut) {
-  base::MockCallback<base::OnceCallback<void(mojom::ModelStatus, base::File)>>
-      callback;
-  EXPECT_CALL(callback, Run(mojom::ModelStatus::kTimeout, _));
+  EXPECT_CALL(callback_, Run(mojom::ModelStatus::kTimeout, _, _));
 
   driver_->GetAnnotateDomModel(/* timeout= */ base::Milliseconds(1000),
-                               callback.Get());
+                               callback_.Get());
 
   // Model does not get loaded.
   task_environment_.FastForwardBy(base::Seconds(2));
@@ -112,16 +110,14 @@
 }
 
 TEST_F(ContentAutofillAssistantDriverTest, MultipleParallelCalls) {
-  base::MockCallback<base::OnceCallback<void(mojom::ModelStatus, base::File)>>
-      callback;
-  EXPECT_CALL(callback, Run(mojom::ModelStatus::kTimeout, _)).Times(3);
+  EXPECT_CALL(callback_, Run(mojom::ModelStatus::kTimeout, _, _)).Times(3);
 
   driver_->GetAnnotateDomModel(/* timeout= */ base::Milliseconds(1000),
-                               callback.Get());
+                               callback_.Get());
   driver_->GetAnnotateDomModel(/* timeout= */ base::Milliseconds(1000),
-                               callback.Get());
+                               callback_.Get());
   driver_->GetAnnotateDomModel(/* timeout= */ base::Milliseconds(1000),
-                               callback.Get());
+                               callback_.Get());
 
   // Model does not get loaded.
   task_environment_.FastForwardBy(base::Seconds(2));
@@ -129,4 +125,16 @@
   EXPECT_FALSE(HasPendingCallbacks());
 }
 
+TEST_F(ContentAutofillAssistantDriverTest, EmptyOverrides) {
+  EXPECT_CALL(callback_, Run(mojom::ModelStatus::kSuccess, _, std::string()));
+
+  driver_->GetAnnotateDomModel(/* timeout= */ base::Milliseconds(1000),
+                               callback_.Get());
+
+  // Model loaded after being requested.
+  annotate_dom_model_service_->SetModelFileForTest(model_file_.Duplicate());
+
+  EXPECT_FALSE(HasPendingCallbacks());
+}
+
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/content/common/autofill_assistant_driver.mojom b/components/autofill_assistant/content/common/autofill_assistant_driver.mojom
index 703883b..b69d97aa 100644
--- a/components/autofill_assistant/content/common/autofill_assistant_driver.mojom
+++ b/components/autofill_assistant/content/common/autofill_assistant_driver.mojom
@@ -5,6 +5,7 @@
 module autofill_assistant.mojom;
 
 import "components/autofill_assistant/content/common/autofill_assistant_types.mojom";
+import "mojo/public/mojom/base/byte_string.mojom";
 import "mojo/public/mojom/base/read_only_file.mojom";
 import "mojo/public/mojom/base/time.mojom";
 
@@ -14,5 +15,6 @@
   // Request that the annotate DOM model is being loaded and returned for use
   // by the AutofillAssistantAgent.
   GetAnnotateDomModel(mojo_base.mojom.TimeDelta timeout)
-      => (ModelStatus status, mojo_base.mojom.ReadOnlyFile? model_file);
+      => (ModelStatus status, mojo_base.mojom.ReadOnlyFile? model_file,
+          mojo_base.mojom.ByteString overrides_policy);
 };
diff --git a/components/autofill_assistant/content/renderer/BUILD.gn b/components/autofill_assistant/content/renderer/BUILD.gn
index 3138bb95..b2173f11 100644
--- a/components/autofill_assistant/content/renderer/BUILD.gn
+++ b/components/autofill_assistant/content/renderer/BUILD.gn
@@ -20,6 +20,7 @@
     "//base",
     "//components/autofill_assistant/content/common:common",
     "//components/autofill_assistant/content/common:mojo_interfaces",
+    "//components/autofill_assistant/content/common/proto:proto",
     "//components/optimization_guide:machine_learning_tflite_buildflags",
     "//content/public/common:common",
     "//content/public/renderer:renderer",
@@ -73,6 +74,7 @@
     "//base",
     "//base/test:test_support",
     "//components/autofill_assistant/content/common:mojo_interfaces",
+    "//components/autofill_assistant/content/common/proto:proto",
     "//content/public/browser",
     "//content/public/renderer",
     "//content/test:test_support",
diff --git a/components/autofill_assistant/content/renderer/DEPS b/components/autofill_assistant/content/renderer/DEPS
index a28ced16..9218c07 100644
--- a/components/autofill_assistant/content/renderer/DEPS
+++ b/components/autofill_assistant/content/renderer/DEPS
@@ -10,6 +10,7 @@
   "+third_party/blink/public/common",
   "+third_party/blink/public/platform",
   "+third_party/blink/public/web",
+  "+third_party/protobuf/src/google/protobuf/repeated_field.h",
   "+third_party/tflite",
   "+third_party/tflite_support",
 ]
diff --git a/components/autofill_assistant/content/renderer/autofill_assistant_agent.cc b/components/autofill_assistant/content/renderer/autofill_assistant_agent.cc
index 3bc18769..909b7a5 100644
--- a/components/autofill_assistant/content/renderer/autofill_assistant_agent.cc
+++ b/components/autofill_assistant/content/renderer/autofill_assistant_agent.cc
@@ -14,15 +14,21 @@
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/public/web/modules/autofill_assistant/node_signals.h"
 #include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
 
 #if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+#include "components/autofill_assistant/content/common/proto/semantic_feature_overrides.pb.h"
 #include "components/autofill_assistant/content/renderer/autofill_assistant_model_executor.h"
 #endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 
 namespace autofill_assistant {
 namespace {
 
+using OverridesMap = AutofillAssistantModelExecutor::OverridesMap;
+using SparseVector = AutofillAssistantModelExecutor::SparseVector;
+
 #if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+
 std::string NodeSignalsToDebugString(
     const blink::AutofillAssistantNodeSignals& node_signals) {
   std::ostringstream out;
@@ -51,6 +57,42 @@
 
   return out.str();
 }
+
+SparseVector KeyCoordinatesToSparseVector(
+    const ::google::protobuf::RepeatedPtrField<SparseEncoding>&
+        key_coordinates) {
+  SparseVector sparse_vector;
+  for (const auto& coordinate : key_coordinates) {
+    sparse_vector.emplace_back(
+        std::make_pair(std::make_pair(coordinate.feature_concatenation_index(),
+                                      coordinate.vocabulary_index()),
+                       coordinate.number_of_occurrences()));
+  }
+  return sparse_vector;
+}
+
+absl::optional<OverridesMap> ParseOverridesPolicyToMap(
+    std::string overrides_policy) {
+  SemanticSelectorPolicy policy;
+  if (!policy.ParseFromString(
+          std::string(overrides_policy.begin(), overrides_policy.end()))) {
+    return absl::nullopt;
+  }
+  if (!policy.has_bag_of_words()) {
+    return absl::nullopt;
+  }
+  OverridesMap overrides_map;
+  for (const auto& data_point : policy.bag_of_words().data_point_map()) {
+    if (data_point.key_coordinate().empty()) {
+      continue;
+    }
+    const auto& value = data_point.value();
+    overrides_map[KeyCoordinatesToSparseVector(data_point.key_coordinate())] =
+        std::make_pair(value.semantic_role(), value.objective());
+  }
+  return overrides_map;
+}
+
 #endif  // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
 
 }  // namespace
@@ -104,7 +146,8 @@
 
 void AutofillAssistantAgent::GetAnnotateDomModel(
     base::TimeDelta model_timeout,
-    base::OnceCallback<void(mojom::ModelStatus, base::File)> callback) {
+    base::OnceCallback<void(mojom::ModelStatus, base::File, const std::string&)>
+        callback) {
   GetDriver().GetAnnotateDomModel(model_timeout, std::move(callback));
 }
 
@@ -115,14 +158,16 @@
   return *driver_;
 }
 
-void AutofillAssistantAgent::OnGetModelFile(base::Time start_time,
-                                            blink::WebLocalFrame* frame,
-                                            int32_t role,
-                                            int32_t objective,
-                                            bool ignore_objective,
-                                            GetSemanticNodesCallback callback,
-                                            mojom::ModelStatus model_status,
-                                            base::File model) {
+void AutofillAssistantAgent::OnGetModelFile(
+    base::Time start_time,
+    blink::WebLocalFrame* frame,
+    int32_t role,
+    int32_t objective,
+    bool ignore_objective,
+    GetSemanticNodesCallback callback,
+    mojom::ModelStatus model_status,
+    base::File model,
+    const std::string& overrides_policy) {
   std::vector<NodeData> nodes;
   switch (model_status) {
     case mojom::ModelStatus::kSuccess:
@@ -147,7 +192,8 @@
            << (on_node_signals - on_get_model_file).InMilliseconds() << "ms";
 
 #if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
-  AutofillAssistantModelExecutor model_executor;
+  AutofillAssistantModelExecutor model_executor(
+      ParseOverridesPolicyToMap(std::move(overrides_policy)));
   if (!model_executor.InitializeModelFromFile(std::move(model))) {
     std::move(callback).Run(mojom::NodeDataStatus::kInitializationError, nodes);
     return;
diff --git a/components/autofill_assistant/content/renderer/autofill_assistant_agent.h b/components/autofill_assistant/content/renderer/autofill_assistant_agent.h
index b546af6..3d711549 100644
--- a/components/autofill_assistant/content/renderer/autofill_assistant_agent.h
+++ b/components/autofill_assistant/content/renderer/autofill_assistant_agent.h
@@ -54,7 +54,8 @@
 
   void GetAnnotateDomModel(
       base::TimeDelta model_timeout,
-      base::OnceCallback<void(mojom::ModelStatus, base::File)> callback);
+      base::OnceCallback<
+          void(mojom::ModelStatus, base::File, const std::string&)> callback);
 
   mojom::AutofillAssistantDriver& GetDriver();
 
@@ -65,7 +66,8 @@
                       bool ignore_objective,
                       GetSemanticNodesCallback callback,
                       mojom::ModelStatus model_status,
-                      base::File model);
+                      base::File model,
+                      const std::string& overrides_policy);
 
   mojo::AssociatedRemote<mojom::AutofillAssistantDriver> driver_;
 
diff --git a/components/autofill_assistant/content/renderer/autofill_assistant_agent_browsertest.cc b/components/autofill_assistant/content/renderer/autofill_assistant_agent_browsertest.cc
index 36900340..01a3d13 100644
--- a/components/autofill_assistant/content/renderer/autofill_assistant_agent_browsertest.cc
+++ b/components/autofill_assistant/content/renderer/autofill_assistant_agent_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/test/mock_callback.h"
 #include "components/autofill_assistant/content/common/autofill_assistant_agent.mojom.h"
 #include "components/autofill_assistant/content/common/autofill_assistant_driver.mojom.h"
+#include "components/autofill_assistant/content/common/proto/semantic_feature_overrides.pb.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/test/render_view_test.h"
 #include "mojo/public/cpp/bindings/associated_receiver_set.h"
@@ -27,6 +28,9 @@
 using ::testing::_;
 using ::testing::SizeIs;
 
+constexpr int kDummySemanticRole = 9999;
+constexpr int kDummyObjective = 1111;
+
 class MockAutofillAssistantDriver : public mojom::AutofillAssistantDriver {
  public:
   void BindPendingReceiver(mojo::ScopedInterfaceEndpointHandle handle) {
@@ -39,7 +43,8 @@
       void,
       GetAnnotateDomModel,
       (base::TimeDelta timeout,
-       base::OnceCallback<void(mojom::ModelStatus, base::File)> callback),
+       base::OnceCallback<
+           void(mojom::ModelStatus, base::File, const std::string&)> callback),
       (override));
 
  private:
@@ -92,7 +97,7 @@
 TEST_F(AutofillAssistantAgentBrowserTest, GetSemanticNodes) {
   EXPECT_CALL(autofill_assistant_driver_, GetAnnotateDomModel)
       .WillOnce(RunOnceCallback<1>(mojom::ModelStatus::kSuccess,
-                                   model_file_.Duplicate()));
+                                   model_file_.Duplicate(), std::string()));
 
   base::MockCallback<base::OnceCallback<void(mojom::NodeDataStatus,
                                              const std::vector<NodeData>&)>>
@@ -117,7 +122,8 @@
 TEST_F(AutofillAssistantAgentBrowserTest, GetSemanticNodesModelTimeout) {
   // Do not reply to the model call.
   EXPECT_CALL(autofill_assistant_driver_, GetAnnotateDomModel)
-      .WillOnce(RunOnceCallback<1>(mojom::ModelStatus::kTimeout, base::File()));
+      .WillOnce(RunOnceCallback<1>(mojom::ModelStatus::kTimeout, base::File(),
+                                   std::string()));
 
   base::MockCallback<base::OnceCallback<void(mojom::NodeDataStatus,
                                              const std::vector<NodeData>&)>>
@@ -143,7 +149,7 @@
   // Do not reply to the model call.
   EXPECT_CALL(autofill_assistant_driver_, GetAnnotateDomModel)
       .WillOnce(RunOnceCallback<1>(mojom::ModelStatus::kUnexpectedError,
-                                   base::File()));
+                                   base::File(), std::string()));
 
   base::MockCallback<base::OnceCallback<void(mojom::NodeDataStatus,
                                              const std::vector<NodeData>&)>>
@@ -168,7 +174,7 @@
 TEST_F(AutofillAssistantAgentBrowserTest, GetSemanticNodesIgnoreObjective) {
   EXPECT_CALL(autofill_assistant_driver_, GetAnnotateDomModel)
       .WillOnce(RunOnceCallback<1>(mojom::ModelStatus::kSuccess,
-                                   model_file_.Duplicate()));
+                                   model_file_.Duplicate(), std::string()));
 
   LoadHTML(R"(
     <div>
@@ -189,5 +195,50 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(AutofillAssistantAgentBrowserTest, Overrides) {
+  SemanticSelectorPolicy policy_proto;
+  auto* single_override =
+      policy_proto.mutable_bag_of_words()->add_data_point_map();
+
+  auto* coordinate = single_override->add_key_coordinate();
+  coordinate->set_feature_concatenation_index(0);
+  // Vocabulary entry "input"
+  coordinate->set_vocabulary_index(1);
+  coordinate->set_number_of_occurrences(1);
+
+  auto* coordinate2 = single_override->add_key_coordinate();
+  coordinate2->set_feature_concatenation_index(3);
+  // Vocabulary entry "street"
+  coordinate2->set_vocabulary_index(862);
+  coordinate2->set_number_of_occurrences(1);
+
+  auto* value = single_override->mutable_value();
+  value->set_objective(kDummyObjective);
+  value->set_semantic_role(kDummySemanticRole);
+
+  std::string policy;
+  ASSERT_TRUE(policy_proto.SerializeToString(&policy));
+
+  EXPECT_CALL(autofill_assistant_driver_, GetAnnotateDomModel)
+      .WillOnce(RunOnceCallback<1>(mojom::ModelStatus::kSuccess,
+                                   model_file_.Duplicate(), policy));
+
+  LoadHTML(R"(
+    <div>
+      <label for="street">street</label><input id="street">
+    </div>)");
+
+  base::MockCallback<base::OnceCallback<void(mojom::NodeDataStatus,
+                                             const std::vector<NodeData>&)>>
+      callback;
+  EXPECT_CALL(callback, Run(mojom::NodeDataStatus::kSuccess, SizeIs(1)));
+
+  autofill_assistant_agent_->GetSemanticNodes(
+      kDummySemanticRole, kDummyObjective,
+      /* ignore_objective= */ false,
+      /* model_timeout= */ base::Milliseconds(1000), callback.Get());
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/content/renderer/autofill_assistant_model_executor.h b/components/autofill_assistant/content/renderer/autofill_assistant_model_executor.h
index 44b9dd7..e55e66b 100644
--- a/components/autofill_assistant/content/renderer/autofill_assistant_model_executor.h
+++ b/components/autofill_assistant/content/renderer/autofill_assistant_model_executor.h
@@ -113,6 +113,7 @@
   // Data regarding business logic for model execution.
   // Set if there is an override for this model execution.
   // Sparse encoding of a feature vector table.
+  // The format is: overrides_[vector] = (semantic_role, objective)
   absl::optional<OverridesMap> overrides_;
   absl::optional<std::pair<int, int>> overrides_result_;
 };
diff --git a/components/feed/mojom/OWNERS b/components/feed/mojom/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/components/feed/mojom/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/components/neterror/resources/offline.js b/components/neterror/resources/offline.js
index bbe7ac7ec..cf57c22 100644
--- a/components/neterror/resources/offline.js
+++ b/components/neterror/resources/offline.js
@@ -4063,8 +4063,9 @@
    */
   addNewObstacle(currentSpeed) {
     const obstacleCount =
-        Runner.isAltGameModeEnabled() && !this.altGameModeActive ||
-            this.altGameModeActive ?
+        Obstacle.types[Obstacle.types.length - 1].type != 'COLLECTABLE' ||
+            (Runner.isAltGameModeEnabled() && !this.altGameModeActive ||
+             this.altGameModeActive) ?
         Obstacle.types.length - 1 :
         Obstacle.types.length - 2;
     const obstacleTypeIndex =
diff --git a/components/password_manager/core/browser/sync/password_model_type_controller.h b/components/password_manager/core/browser/sync/password_model_type_controller.h
index 91c9677..33bd264 100644
--- a/components/password_manager/core/browser/sync/password_model_type_controller.h
+++ b/components/password_manager/core/browser/sync/password_model_type_controller.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "components/password_manager/core/browser/password_account_storage_settings_watcher.h"
diff --git a/components/reporting/storage/storage.cc b/components/reporting/storage/storage.cc
index f67b76df..0f565d8 100644
--- a/components/reporting/storage/storage.cc
+++ b/components/reporting/storage/storage.cc
@@ -84,8 +84,8 @@
 
 constexpr base::FilePath::CharType kEncryptionKeyFilePrefix[] =
     FILE_PATH_LITERAL("EncryptionKey.");
-const int32_t kEncryptionKeyMaxFileSize = 256;
-const uint64_t kQueueSize = 2 * 1024LL * 1024LL;
+constexpr int32_t kEncryptionKeyMaxFileSize = 256;
+constexpr uint64_t kQueueSize = 2UL * 1024UL * 1024UL;
 
 // Failed upload retry delay: if an upload fails and there are no more incoming
 // events, collected events will not get uploaded for an indefinite time (see
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
index c0152b9..279acb19 100644
--- a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
+++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
@@ -27,6 +27,7 @@
 #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
 #include "components/segmentation_platform/internal/stats.h"
 #include "components/segmentation_platform/public/config.h"
+#include "components/segmentation_platform/public/field_trial_register.h"
 #include "components/segmentation_platform/public/model_provider.h"
 
 using optimization_guide::proto::OptimizationTarget;
@@ -58,6 +59,7 @@
       platform_options_(PlatformOptions::CreateDefault()),
       configs_(std::move(init_params->configs)),
       all_segment_ids_(GetAllSegmentIds(configs_)),
+      field_trial_register_(std::move(init_params->field_trial_register)),
       profile_prefs_(init_params->profile_prefs),
       creation_time_(clock_->Now()) {
   base::UmaHistogramMediumTimes(
@@ -96,8 +98,9 @@
         std::make_unique<SegmentSelectorImpl>(
             storage_service_->segment_info_database(),
             storage_service_->signal_storage_config(),
-            init_params->profile_prefs, config.get(), init_params->clock,
-            platform_options_, storage_service_->default_model_manager());
+            init_params->profile_prefs, config.get(),
+            field_trial_register_.get(), init_params->clock, platform_options_,
+            storage_service_->default_model_manager());
   }
 
   proxy_ = std::make_unique<ServiceProxyImpl>(
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.h b/components/segmentation_platform/internal/segmentation_platform_service_impl.h
index d409394..b30abaf 100644
--- a/components/segmentation_platform/internal/segmentation_platform_service_impl.h
+++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.h
@@ -42,6 +42,7 @@
 namespace segmentation_platform {
 
 struct Config;
+class FieldTrialRegister;
 class ModelProviderFactory;
 class SegmentSelectorImpl;
 class SegmentScoreProvider;
@@ -65,6 +66,7 @@
     std::unique_ptr<ModelProviderFactory> model_provider;
     UkmDataManager* ukm_data_manager = nullptr;
     std::vector<std::unique_ptr<Config>> configs;
+    std::unique_ptr<FieldTrialRegister> field_trial_register;
 
     scoped_refptr<base::SequencedTaskRunner> task_runner;
     base::Clock* clock = nullptr;
@@ -124,6 +126,7 @@
   std::vector<std::unique_ptr<Config>> configs_;
   base::flat_set<optimization_guide::proto::OptimizationTarget>
       all_segment_ids_;
+  std::unique_ptr<FieldTrialRegister> field_trial_register_;
 
   std::unique_ptr<StorageService> storage_service_;
   bool storage_initialized_ = false;
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_test_base.cc b/components/segmentation_platform/internal/segmentation_platform_service_test_base.cc
index 032cd0a..c9fda10 100644
--- a/components/segmentation_platform/internal/segmentation_platform_service_test_base.cc
+++ b/components/segmentation_platform/internal/segmentation_platform_service_test_base.cc
@@ -14,11 +14,19 @@
 #include "components/segmentation_platform/internal/segmentation_platform_service_impl.h"
 #include "components/segmentation_platform/internal/ukm_data_manager.h"
 #include "components/segmentation_platform/public/config.h"
+#include "components/segmentation_platform/public/field_trial_register.h"
 
 namespace segmentation_platform {
 
 namespace {
 
+class MockFieldTrialRegister : public FieldTrialRegister {
+ public:
+  MOCK_METHOD2(RegisterFieldTrial,
+               void(base::StringPiece trial_name,
+                    base::StringPiece group_name));
+};
+
 std::vector<std::unique_ptr<Config>> CreateTestConfigs() {
   std::vector<std::unique_ptr<Config>> configs;
   {
@@ -112,6 +120,7 @@
   params->task_runner = task_runner_;
   params->clock = &test_clock_;
   params->configs = std::move(configs);
+  params->field_trial_register = std::make_unique<MockFieldTrialRegister>();
   segmentation_platform_service_impl_ =
       std::make_unique<SegmentationPlatformServiceImpl>(std::move(params));
 }
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.cc b/components/segmentation_platform/internal/selection/segment_selector_impl.cc
index e52ffc4..c91cf6c 100644
--- a/components/segmentation_platform/internal/selection/segment_selector_impl.cc
+++ b/components/segmentation_platform/internal/selection/segment_selector_impl.cc
@@ -8,6 +8,7 @@
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
 #include "base/logging.h"
+#include "base/strings/strcat.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/clock.h"
 #include "base/time/time.h"
@@ -22,6 +23,7 @@
 #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
 #include "components/segmentation_platform/internal/stats.h"
 #include "components/segmentation_platform/public/config.h"
+#include "components/segmentation_platform/public/field_trial_register.h"
 #include "components/segmentation_platform/public/model_provider.h"
 
 namespace segmentation_platform {
@@ -65,6 +67,7 @@
     SignalStorageConfig* signal_storage_config,
     PrefService* pref_service,
     const Config* config,
+    FieldTrialRegister* field_trial_register,
     base::Clock* clock,
     const PlatformOptions& platform_options,
     DefaultModelManager* default_model_manager)
@@ -73,6 +76,7 @@
           signal_storage_config,
           std::make_unique<SegmentationResultPrefs>(pref_service),
           config,
+          field_trial_register,
           clock,
           platform_options,
           default_model_manager) {}
@@ -82,6 +86,7 @@
     SignalStorageConfig* signal_storage_config,
     std::unique_ptr<SegmentationResultPrefs> prefs,
     const Config* config,
+    FieldTrialRegister* field_trial_register,
     base::Clock* clock,
     const PlatformOptions& platform_options,
     DefaultModelManager* default_model_manager)
@@ -90,21 +95,34 @@
       signal_storage_config_(signal_storage_config),
       default_model_manager_(default_model_manager),
       config_(config),
+      field_trial_register_(field_trial_register),
       clock_(clock),
       platform_options_(platform_options) {
   // Read selected segment from prefs.
   const auto& selected_segment =
       result_prefs_->ReadSegmentationResultFromPref(config_->segmentation_key);
+  std::string trial_name =
+      stats::SegmentationKeyToTrialName(config_->segmentation_key);
+  std::string group_name;
   if (selected_segment.has_value()) {
     selected_segment_last_session_.segment = selected_segment->segment_id;
     selected_segment_last_session_.is_ready = true;
     stats::RecordSegmentSelectionFailure(
         config_->segmentation_key,
         stats::SegmentationSelectionFailureReason::kSelectionAvailableInPrefs);
+
+    group_name = stats::OptimizationTargetToSegmentGroupName(
+        *selected_segment_last_session_.segment);
   } else {
     stats::RecordSegmentSelectionFailure(
         config_->segmentation_key, stats::SegmentationSelectionFailureReason::
                                        kInvalidSelectionResultInPrefs);
+    group_name = "Unselected";
+  }
+
+  // Can be nullptr in tests.
+  if (field_trial_register_) {
+    field_trial_register_->RegisterFieldTrial(trial_name, group_name);
   }
 }
 
@@ -115,7 +133,7 @@
   segment_result_provider_ = SegmentResultProvider::Create(
       segment_database_, signal_storage_config_, default_model_manager_,
       execution_service, clock_, platform_options_.force_refresh_results);
-  if (CanComputeSegmentSelection()) {
+  if (IsPreviousSelectionInvalid()) {
     GetRankForNextSegment(std::make_unique<SegmentRanks>());
   }
 }
@@ -139,13 +157,13 @@
   if (!base::Contains(config_->segment_ids, segment_id))
     return;
 
-  if (!CanComputeSegmentSelection())
+  if (!IsPreviousSelectionInvalid())
     return;
 
   GetRankForNextSegment(std::make_unique<SegmentRanks>());
 }
 
-bool SegmentSelectorImpl::CanComputeSegmentSelection() {
+bool SegmentSelectorImpl::IsPreviousSelectionInvalid() {
   // Don't compute results if segment selection TTL hasn't expired.
   const auto& previous_selection =
       result_prefs_->ReadSegmentationResultFromPref(config_->segmentation_key);
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.h b/components/segmentation_platform/internal/selection/segment_selector_impl.h
index 8aa96ad..f238870 100644
--- a/components/segmentation_platform/internal/selection/segment_selector_impl.h
+++ b/components/segmentation_platform/internal/selection/segment_selector_impl.h
@@ -23,8 +23,9 @@
 namespace segmentation_platform {
 
 struct Config;
-class ExecutionService;
 class DefaultModelManager;
+class ExecutionService;
+class FieldTrialRegister;
 class SegmentationResultPrefs;
 class SignalStorageConfig;
 
@@ -34,6 +35,7 @@
                       SignalStorageConfig* signal_storage_config,
                       PrefService* pref_service,
                       const Config* config,
+                      FieldTrialRegister* field_trial_register,
                       base::Clock* clock,
                       const PlatformOptions& platform_options,
                       DefaultModelManager* default_model_manager);
@@ -42,6 +44,7 @@
                       SignalStorageConfig* signal_storage_config,
                       std::unique_ptr<SegmentationResultPrefs> prefs,
                       const Config* config,
+                      FieldTrialRegister* field_trial_register,
                       base::Clock* clock,
                       const PlatformOptions& platform_options,
                       DefaultModelManager* default_model_manager);
@@ -67,10 +70,9 @@
 
   using SegmentRanks = base::flat_map<OptimizationTarget, int>;
 
-  // Determines whether segment selection can be run based on whether all
-  // segments have met signal collection requirement, have valid results, and
-  // segment selection TTL has expired.
-  bool CanComputeSegmentSelection();
+  // Determines whether segment selection can be run based on whether the
+  // segment selection TTL has expired, or selection is unavailable.
+  bool IsPreviousSelectionInvalid();
 
   // Gets ranks for each segment from SegmentResultProvider, and then computes
   // segment selection.
@@ -104,6 +106,8 @@
   // The config for providing configuration params.
   const raw_ptr<const Config> config_;
 
+  const raw_ptr<FieldTrialRegister> field_trial_register_;
+
   // The time provider.
   const raw_ptr<base::Clock> clock_;
 
diff --git a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
index 5dbdd46..8980aaa0 100644
--- a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
+++ b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
@@ -16,6 +16,7 @@
 #include "components/segmentation_platform/internal/execution/mock_model_provider.h"
 #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
 #include "components/segmentation_platform/public/config.h"
+#include "components/segmentation_platform/public/field_trial_register.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -30,6 +31,13 @@
 
 namespace {
 
+class MockFieldTrialRegister : public FieldTrialRegister {
+ public:
+  MOCK_METHOD2(RegisterFieldTrial,
+               void(base::StringPiece trial_name,
+                    base::StringPiece group_name));
+};
+
 Config CreateTestConfig() {
   Config config;
   config.segmentation_key = "test_key";
@@ -76,7 +84,7 @@
     prefs_ = prefs_moved.get();
     segment_selector_ = std::make_unique<SegmentSelectorImpl>(
         segment_database_.get(), &signal_storage_config_,
-        std::move(prefs_moved), &config_, &clock_,
+        std::move(prefs_moved), &config_, &field_trial_register_, &clock_,
         PlatformOptions::CreateDefault(), default_manager_.get());
     segment_selector_->OnPlatformInitialized(nullptr);
   }
@@ -120,6 +128,7 @@
   TestModelProviderFactory::Data model_providers_;
   TestModelProviderFactory provider_factory_;
   Config config_;
+  MockFieldTrialRegister field_trial_register_;
   base::SimpleTestClock clock_;
   std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_;
   MockSignalStorageConfig signal_storage_config_;
@@ -311,8 +320,8 @@
   // Construct a segment selector. It should read result from last session.
   segment_selector_ = std::make_unique<SegmentSelectorImpl>(
       segment_database_.get(), &signal_storage_config_, std::move(prefs_moved),
-      &config_, &clock_, PlatformOptions::CreateDefault(),
-      default_manager_.get());
+      &config_, &field_trial_register_, &clock_,
+      PlatformOptions::CreateDefault(), default_manager_.get());
   segment_selector_->OnPlatformInitialized(nullptr);
 
   SegmentSelectionResult result;
diff --git a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
index 1eb23b2f..18f3e3d 100644
--- a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
+++ b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
@@ -70,6 +70,7 @@
                             pref_service,
                             config,
                             nullptr,
+                            nullptr,
                             PlatformOptions::CreateDefault(),
                             nullptr) {}
   ~FakeSegmentSelectorImpl() override = default;
diff --git a/components/segmentation_platform/internal/stats.cc b/components/segmentation_platform/internal/stats.cc
index 93d52eae..41f455c 100644
--- a/components/segmentation_platform/internal/stats.cc
+++ b/components/segmentation_platform/internal/stats.cc
@@ -37,8 +37,7 @@
         OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT:
       return "ChromeLowUserEngagement";
     default:
-      NOTREACHED();
-      return "Unknown";
+      return "Other";
   }
 }
 
@@ -266,6 +265,16 @@
 
 }  // namespace
 
+std::string OptimizationTargetToSegmentGroupName(
+    OptimizationTarget segment_id) {
+  return OptimizationTargetToHistogramVariant(segment_id);
+}
+
+std::string SegmentationKeyToTrialName(const std::string& segmentation_key) {
+  return base::StrCat(
+      {"Segmentation_", SegmentationKeyToUmaName(segmentation_key)});
+}
+
 void RecordModelScore(OptimizationTarget segment_id, float score) {
   // Special case adaptive toolbar models since it already has histograms being
   // recorded and updating names will affect current work.
diff --git a/components/segmentation_platform/internal/stats.h b/components/segmentation_platform/internal/stats.h
index b1581a4..5f2ab214 100644
--- a/components/segmentation_platform/internal/stats.h
+++ b/components/segmentation_platform/internal/stats.h
@@ -44,6 +44,14 @@
   kMaxValue = kEnabledToNone,
 };
 
+// Returns a name to be used in UMA dashboard as segment group for the given
+// `segment_id`.
+std::string OptimizationTargetToSegmentGroupName(OptimizationTarget segment_id);
+
+// Returns a name to be used in UMA dashboard as segmentation type for the given
+// `segmentation_key`.
+std::string SegmentationKeyToTrialName(const std::string& segmentation_key);
+
 // Records the score computed for a given segment.
 void RecordModelScore(OptimizationTarget segment_id, float score);
 
diff --git a/components/segmentation_platform/public/BUILD.gn b/components/segmentation_platform/public/BUILD.gn
index 96a6038..000851f 100644
--- a/components/segmentation_platform/public/BUILD.gn
+++ b/components/segmentation_platform/public/BUILD.gn
@@ -13,6 +13,7 @@
     "config.h",
     "features.cc",
     "features.h",
+    "field_trial_register.h",
     "local_state_helper.h",
     "model_provider.cc",
     "model_provider.h",
diff --git a/components/segmentation_platform/public/features.h b/components/segmentation_platform/public/features.h
index c452c7c..e7dc5b0 100644
--- a/components/segmentation_platform/public/features.h
+++ b/components/segmentation_platform/public/features.h
@@ -6,9 +6,9 @@
 #define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_FEATURES_H_
 
 #include "base/feature_list.h"
+#include "base/strings/string_piece.h"
 
-namespace segmentation_platform {
-namespace features {
+namespace segmentation_platform::features {
 
 // Core feature flag for segmentation platform.
 extern const base::Feature kSegmentationPlatformFeature;
@@ -26,7 +26,6 @@
 // Feature flag for enabling low engagement segmentation key.
 extern const base::Feature kSegmentationPlatformLowEngagementFeature;
 
-}  // namespace features
-}  // namespace segmentation_platform
+}  // namespace segmentation_platform::features
 
 #endif  // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_FEATURES_H_
diff --git a/components/segmentation_platform/public/field_trial_register.h b/components/segmentation_platform/public/field_trial_register.h
new file mode 100644
index 0000000..2266427
--- /dev/null
+++ b/components/segmentation_platform/public/field_trial_register.h
@@ -0,0 +1,32 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_FIELD_TRIAL_REGISTER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_FIELD_TRIAL_REGISTER_H_
+
+#include "base/strings/string_piece.h"
+
+namespace segmentation_platform {
+
+// A delegate class that handles recording of the selected segmentation groups
+// to metrics.
+class FieldTrialRegister {
+ public:
+  FieldTrialRegister() = default;
+  virtual ~FieldTrialRegister() = default;
+
+  FieldTrialRegister(FieldTrialRegister&) = delete;
+  FieldTrialRegister& operator=(FieldTrialRegister&) = delete;
+
+  // Records that the current session uses `trial_name` and `group_name` as
+  // segmentation groups. Calling multiple times with same `trial_name`
+  // will replace the existing group with the new one, but note that the
+  // previous logs already closed / staged for upload will not be changed.
+  virtual void RegisterFieldTrial(base::StringPiece trial_name,
+                                  base::StringPiece group_name) = 0;
+};
+
+}  // namespace segmentation_platform
+
+#endif  // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_FIELD_TRIAL_REGISTER_H_
diff --git a/components/services/screen_ai/BUILD.gn b/components/services/screen_ai/BUILD.gn
index 1d12d228..57e9c55 100644
--- a/components/services/screen_ai/BUILD.gn
+++ b/components/services/screen_ai/BUILD.gn
@@ -4,10 +4,6 @@
 
 import("//third_party/protobuf/proto_library.gni")
 
-proto_library("screen_ai_proto") {
-  sources = [ "proto/chrome_screen_ai.proto" ]
-}
-
 source_set("screen_ai") {
   sources = [
     "screen_ai_service_impl.cc",
@@ -15,14 +11,12 @@
   ]
 
   deps = [
-    ":screen_ai_proto",
     "//base",
+    "//components/services/screen_ai/proto:proto_convertors",
     "//components/services/screen_ai/public/cpp:utilities",
-  ]
-
-  public_deps = [
     "//components/services/screen_ai/public/mojom",
     "//mojo/public/cpp/bindings",
+    "//ui/accessibility:ax_base",
   ]
 }
 
diff --git a/components/services/screen_ai/proto/BUILD.gn b/components/services/screen_ai/proto/BUILD.gn
new file mode 100644
index 0000000..754f89b
--- /dev/null
+++ b/components/services/screen_ai/proto/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/protobuf/proto_library.gni")
+
+proto_library("proto") {
+  sources = [
+    "chrome_screen_ai.proto",
+    "dimension.proto",
+    "view_hierarchy.proto",
+  ]
+}
+
+source_set("proto_convertors") {
+  sources = [
+    "proto_convertor.cc",
+    "proto_convertor.h",
+  ]
+
+  deps = [
+    ":proto",
+    "//base",
+    "//components/services/screen_ai/public/mojom",
+    "//ui/accessibility:ax_base",
+  ]
+}
diff --git a/components/services/screen_ai/proto/dimension.proto b/components/services/screen_ai/proto/dimension.proto
new file mode 100644
index 0000000..e436f24
--- /dev/null
+++ b/components/services/screen_ai/proto/dimension.proto
@@ -0,0 +1,29 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This proto is copied from the following proto, do not change.
+// google3/knowledge/cerebra/sense/im2query/screenai/proto/dimensions.proto
+syntax = "proto2";
+
+package screenai;
+
+option optimize_for = LITE_RUNTIME;
+
+// Normalized coordinates [0.0, 1.0] specifying a region of the screen.
+// The coordinate [0.0, 0.0] corresponds to the top left pixel on the screen.
+message BoundingBox {
+  optional float top = 1;
+  optional float left = 2;
+  optional float bottom = 3;
+  optional float right = 4;
+}
+
+// Bounding box specifying a region of the screen in pixel coordinates.
+// The coordinate [0, 0] corresponds to the top left pixel on the screen.
+message BoundingBoxPixels {
+  optional int32 top = 1;
+  optional int32 left = 2;
+  optional int32 bottom = 3;
+  optional int32 right = 4;
+}
diff --git a/components/services/screen_ai/proto/proto_convertor.cc b/components/services/screen_ai/proto/proto_convertor.cc
new file mode 100644
index 0000000..730bbf8
--- /dev/null
+++ b/components/services/screen_ai/proto/proto_convertor.cc
@@ -0,0 +1,177 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/screen_ai/proto/proto_convertor.h"
+
+#include "base/containers/contains.h"
+#include "components/services/screen_ai/proto/chrome_screen_ai.pb.h"
+#include "components/services/screen_ai/proto/dimension.pb.h"
+#include "components/services/screen_ai/proto/view_hierarchy.pb.h"
+#include "components/services/screen_ai/public/mojom/screen_ai_service.mojom.h"
+#include "ui/accessibility/ax_enum_util.h"
+
+namespace {
+
+// The minimum confidence level that a Screen AI annotation should have to be
+// accepted.
+// TODO(https://crbug.com/1278249): Add experiment or heuristics to better
+// adjust this threshold.
+const float kScreenAIMinConfidenceThreshold = 0.1;
+
+}  // namespace
+
+namespace screen_ai {
+
+ui::AXTreeUpdate ScreenAIVisualAnnotationToAXTreeUpdate(
+    const std::string& serialized_proto) {
+  ui::AXTreeUpdate updates;
+
+  chrome_screen_ai::VisualAnnotation results;
+  if (!results.ParseFromString(serialized_proto)) {
+    VLOG(1) << "Could not parse Screen AI library output.";
+    return updates;
+  }
+
+  // TODO(https://crbug.com/1278249): Create an AXTreeSource and create the
+  // update using AXTreeSerializer.
+
+  for (const auto& uic : results.ui_component()) {
+    // Score is only used to prune very low confidence detections and we don't
+    // use it downstream.
+    if (uic.predicted_type().score() < kScreenAIMinConfidenceThreshold)
+      continue;
+
+    ui::AXNodeData node;
+
+    chrome_screen_ai::UIComponent::Type original_type =
+        uic.predicted_type().type();
+    node.relative_bounds.bounds.set_x(uic.bounding_box().x());
+    node.relative_bounds.bounds.set_y(uic.bounding_box().y());
+    node.relative_bounds.bounds.set_width(uic.bounding_box().width());
+    node.relative_bounds.bounds.set_height(uic.bounding_box().height());
+
+    // TODO(https://crbug.com/1278249): Add tests to ensure these two types
+    // match. Add a PRESUBMIT test that compares the proto and enum.
+    node.role = static_cast<ax::mojom::Role>(original_type);
+
+    updates.nodes.push_back(node);
+  }
+
+  // TODO(https://crbug.com/1278249): Add UMA metrics to record the number of
+  // annotations, item types, confidence levels, etc.
+
+  return updates;
+}
+
+std::string Screen2xSnapshotToViewHierarchy(const ui::AXTreeUpdate& snapshot) {
+  screenai::ViewHierarchy view_hierarchy;
+
+  // TODO(https://crbug.com/1278249): Use actual screen resolution.
+  // As root's |relative_bounding_box| is relative to the outside container,
+  // we can assume it as resolution now.
+  float screen_width = -1;
+  float screen_height = -1;
+  for (auto& node : snapshot.nodes) {
+    if (node.id != snapshot.root_id)
+      continue;
+    screen_width = node.relative_bounds.bounds.width();
+    screen_height = node.relative_bounds.bounds.height();
+    break;
+  }
+  VLOG(2) << "Assumed screen size for Screen2x: " << screen_width << " x "
+          << screen_height;
+
+  // TODO(https://crbug.com/1278249): Screen2x requires id 0 for the root, and
+  // -1 as no-parent indicator. Consider just using the type and ignoring the id
+  // value for detecting root.
+  std::map<int, int> chrome_to_screen2x_ids;
+  int last_used_id = 0;
+  // A map for finding parents faster.
+  std::map<int, int> child_to_parent_map;
+  for (auto& node : snapshot.nodes) {
+    int ax_node_id = static_cast<int>(node.id);
+    if (node.id == snapshot.root_id)
+      chrome_to_screen2x_ids[ax_node_id] = 0;
+    else
+      chrome_to_screen2x_ids[ax_node_id] = ++last_used_id;
+
+    for (int32_t child_id : node.child_ids)
+      child_to_parent_map[child_id] = chrome_to_screen2x_ids[ax_node_id];
+  }
+
+  for (auto& node : snapshot.nodes) {
+    screenai::UiElement* uie = view_hierarchy.add_ui_elements();
+    screenai::UiElementAttribute* attrib = nullptr;
+    int ax_node_id = static_cast<int>(node.id);
+
+    // Text.
+    attrib = uie->add_attributes();
+    attrib->set_name("text");
+    attrib->set_string_value(
+        node.GetStringAttribute(ax::mojom::StringAttribute::kName));
+
+    // Class Name.
+    // This is a fixed constant for Chrome requests to Screen2x.
+    attrib = uie->add_attributes();
+    attrib->set_name("class_name");
+    attrib->set_string_value("chrome.unicorn");
+
+    // Role.
+    attrib = uie->add_attributes();
+    attrib->set_name("chrome_role");
+    attrib->set_string_value(ui::ToString(node.role));
+
+    // AxNode ID.
+    attrib = uie->add_attributes();
+    attrib->set_name("/axnode/node_id");
+    attrib->set_int_value(ax_node_id);
+
+    // Child IDs.
+    for (int32_t id : node.child_ids) {
+      attrib = uie->add_attributes();
+      attrib->set_name("/axnode/child_ids");
+      attrib->set_int_value(id);
+      uie->add_child_ids(chrome_to_screen2x_ids[id]);
+    }
+
+    // ID, Type, and parent.
+    uie->set_id(chrome_to_screen2x_ids[ax_node_id]);
+    if (node.id == snapshot.root_id) {
+      uie->set_parent_id(-1);
+      uie->set_type(screenai::UiElementType::ROOT);
+    } else {
+      uie->set_parent_id(child_to_parent_map[ax_node_id]);
+      uie->set_type(screenai::UiElementType::VIEW);
+    }
+
+    // Bounding Box.
+    uie->mutable_bounding_box()->set_top(node.relative_bounds.bounds.y() /
+                                         screen_height);
+    uie->mutable_bounding_box()->set_left(node.relative_bounds.bounds.x() /
+                                          screen_width);
+    uie->mutable_bounding_box()->set_bottom(
+        node.relative_bounds.bounds.bottom() / screen_height);
+    uie->mutable_bounding_box()->set_right(node.relative_bounds.bounds.right() /
+                                           screen_width);
+
+    // Bounding Box Pixels.
+    // TODO(https://crbug.com/1278249): These values are relative to the
+    // container position and not to the actual top-left of the screen. Consider
+    // getting the container position and update based on that.
+    uie->mutable_bounding_box_pixels()->set_top(
+        node.relative_bounds.bounds.y());
+    uie->mutable_bounding_box_pixels()->set_left(
+        node.relative_bounds.bounds.x());
+    uie->mutable_bounding_box_pixels()->set_bottom(
+        node.relative_bounds.bounds.bottom());
+    uie->mutable_bounding_box_pixels()->set_right(
+        node.relative_bounds.bounds.right());
+
+    // TODO(https://crbug.com/1278249): Add non-essential values.
+  }
+
+  return view_hierarchy.SerializeAsString();
+}
+
+}  // namespace screen_ai
diff --git a/components/services/screen_ai/proto/proto_convertor.h b/components/services/screen_ai/proto/proto_convertor.h
new file mode 100644
index 0000000..0d0089e
--- /dev/null
+++ b/components/services/screen_ai/proto/proto_convertor.h
@@ -0,0 +1,23 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_SCREEN_AI_PROTO_PROTO_CONVERTOR_H_
+#define COMPONENTS_SERVICES_SCREEN_AI_PROTO_PROTO_CONVERTOR_H_
+
+#include <string>
+
+#include "ui/accessibility/ax_tree_update.h"
+
+namespace screen_ai {
+
+// Converts serialized VisualAnnotation proto from ScreenAI to AXTreeUpdate.
+ui::AXTreeUpdate ScreenAIVisualAnnotationToAXTreeUpdate(
+    const std::string& serialized_proto);
+
+// Converts an AXTreeUpdate snapshot to serialized ViewHierarchy proto for
+// Screen2X.
+std::string Screen2xSnapshotToViewHierarchy(const ui::AXTreeUpdate& snapshot);
+
+}  // namespace screen_ai
+#endif  // COMPONENTS_SERVICES_SCREEN_AI_PROTO_PROTO_CONVERTOR_H_
diff --git a/components/services/screen_ai/proto/view_hierarchy.proto b/components/services/screen_ai/proto/view_hierarchy.proto
new file mode 100644
index 0000000..acf2ccd8
--- /dev/null
+++ b/components/services/screen_ai/proto/view_hierarchy.proto
@@ -0,0 +1,109 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This proto is copied from the following proto, do not change.
+// google3/knowledge/cerebra/sense/im2query/screenai/proto/view_hierarchy.proto
+syntax = "proto2";
+
+package screenai;
+
+import "dimension.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+// Represents a hierarchical data (e.g. tree structure) in general, in which
+// UiElement represents a node.
+// Next ID: 3.
+message ViewHierarchy {
+  reserved 1;
+  repeated UiElement ui_elements = 2;
+}
+
+// A single UI element. An element is relatively general and includes containers
+// (e.g. LinearLayout) or individual visible elements (e.g. button, text label).
+// Next ID: 10.
+message UiElement {
+  // Unique positive number in the entire view hierarchy.
+  optional int32 id = 1 [default = -1];
+
+  optional UiElementType type = 2;
+
+  optional int32 parent_id = 3 [default = -1];
+
+  // All child elements of this element.
+  // The order of child ids is preserved from original view hierarchy tree.
+  repeated int32 child_ids = 4 [packed = true];
+
+  // Bounding box in screenshot, normalized by the image dimensions. This
+  // dimension is generally the captured screenshot dimension or the dimension
+  // of the root element if it covers the whole visible area.
+  // For example: The viewport of the screen is: 1440x1080. We capture a long
+  // screen that contains scrolled content, which has size 1440x8500.
+  // Then a container with coordinates:
+  //   left: 50, right 1390, top 1300, bottom 2000
+  // would be normalized to:
+  //   left: 50 / 1440, right 1390 / 1440, top 1300 / 8500, bottom 2000 / 8500.
+  optional BoundingBox bounding_box = 6;
+
+  // Bounding box in screenshot. Bounding box in pixels (non-normalized).
+  optional BoundingBoxPixels bounding_box_pixels = 8;
+
+  // A list of attributes for this element. Includes common attributes such as
+  // 'enabled', 'text'.
+  repeated UiElementAttribute attributes = 7;
+
+  // Define the application-specific information below.
+
+  // Information about data extracted from a Chrome-based application.
+  optional ChromeInfo chrome_info = 9;
+}
+
+enum UiElementType {
+  UNKNOWN = 0;
+  ROOT = 1;
+  WINDOW = 2;
+  VIEW = 3;
+}
+
+// An UiElement attribute.
+// Next ID: 9.
+message UiElementAttribute {
+  // The name of the attribute, for example 'text', 'focusable',
+  // 'contentDescription'.
+  optional string name = 1;
+
+  // The value of the attribute.
+  // This format only supports simple types. Some types for example dimension
+  // '123 px' should be stored as string and the application should handle
+  // parsing it. For other types for example reference a custom attribute
+  // message should be defined.
+  oneof value {
+    bool bool_value = 2;
+    int32 int_value = 3;
+    string string_value = 4;
+    float float_value = 5;
+    IntList int_list_value = 6;
+    StringList string_list_value = 7;
+    FloatList float_list_value = 8;
+  }
+}
+
+message IntList {
+  repeated int32 value = 1 [packed = true];
+}
+
+message StringList {
+  repeated string value = 1;
+}
+
+message FloatList {
+  repeated float value = 1;
+}
+
+// Chrome specific information.
+message ChromeInfo {
+  // Backend DOM Node ID from which the UiElement is extracted.
+  // Sample usage: to trace back the original DOM Node of an UiElement.
+  optional int32 dom_node_id = 1 [default = -1];
+}
diff --git a/components/services/screen_ai/public/cpp/utilities.cc b/components/services/screen_ai/public/cpp/utilities.cc
index 89df185..5062f7d 100644
--- a/components/services/screen_ai/public/cpp/utilities.cc
+++ b/components/services/screen_ai/public/cpp/utilities.cc
@@ -36,7 +36,6 @@
   base::FilePath components_dir;
   base::PathService::Get(component_updater::DIR_COMPONENT_USER,
                          &components_dir);
-
   if (components_dir.empty())
     return base::FilePath();
 
diff --git a/components/services/screen_ai/screen_ai_service_impl.cc b/components/services/screen_ai/screen_ai_service_impl.cc
index 1f9f5a7..99e2848 100644
--- a/components/services/screen_ai/screen_ai_service_impl.cc
+++ b/components/services/screen_ai/screen_ai_service_impl.cc
@@ -5,19 +5,12 @@
 #include "components/services/screen_ai/screen_ai_service_impl.h"
 
 #include "base/process/process.h"
-#include "components/services/screen_ai/proto/chrome_screen_ai.pb.h"
+#include "components/services/screen_ai/proto/proto_convertor.h"
 #include "components/services/screen_ai/public/cpp/utilities.h"
-#include "components/services/screen_ai/public/mojom/screen_ai_service.mojom.h"
 #include "ui/accessibility/accessibility_features.h"
 
 namespace {
 
-// The minimum confidence level that a Screen AI annotation should have to be
-// accepted.
-// TODO(https://crbug.com/1278249): Add experiment or heuristics to better
-// adjust this threshold.
-const float kScreenAIMinConfidenceThreshold = 0.1;
-
 enum class InitializationResult {
   kOk = 0,
   kErrorInvalidLibraryFunctions = 1,
@@ -92,7 +85,7 @@
   // TODO(https://crbug.com/1278249): Consider adding a signature that
   // verifies the data integrity and source.
   if (annotate_function_(image, annotation_text)) {
-    updates = DecodeAnnotatorProto(annotation_text);
+    updates = ScreenAIVisualAnnotationToAXTreeUpdate(annotation_text);
   } else {
     VLOG(1) << "Screen AI library could not process snapshot.";
   }
@@ -100,53 +93,19 @@
   std::move(callback).Run(updates);
 }
 
-ui::AXTreeUpdate ScreenAIService::DecodeAnnotatorProto(
-    const std::string& serialized_proto) {
-  ui::AXTreeUpdate updates;
-
-  // TODO(https://crbug.com/1278249): Consider adding version checking.
-  chrome_screen_ai::VisualAnnotation results;
-  if (!results.ParseFromString(serialized_proto)) {
-    VLOG(1) << "Could not parse Screen AI library output.";
-    return updates;
-  }
-
-  // TODO(https://crbug.com/1278249): Create an AXTreeSource and create the
-  // update using AXTreeSerializer.
-
-  for (const auto& uic : results.ui_component()) {
-    // Score is only used to prune very low confidence detections and we don't
-    // use it downstream.
-    if (uic.predicted_type().score() < kScreenAIMinConfidenceThreshold)
-      continue;
-
-    ui::AXNodeData node;
-
-    chrome_screen_ai::UIComponent::Type original_type =
-        uic.predicted_type().type();
-    node.relative_bounds.bounds.set_x(uic.bounding_box().x());
-    node.relative_bounds.bounds.set_y(uic.bounding_box().y());
-    node.relative_bounds.bounds.set_width(uic.bounding_box().width());
-    node.relative_bounds.bounds.set_height(uic.bounding_box().height());
-
-    // TODO(https://crbug.com/1278249): Add tests to ensure these two types
-    // match. Add a PRESUBMIT test that compares the proto and enum.
-    node.role = static_cast<ax::mojom::Role>(original_type);
-
-    updates.nodes.push_back(node);
-  }
-
-  // TODO(https://crbug.com/1278249): Add UMA metrics to record the number of
-  // annotations, item types, confidence levels, etc.
-
-  return updates;
-}
-
 void ScreenAIService::ExtractMainContent(const ui::AXTreeUpdate& snapshot,
                                          ContentExtractionCallback callback) {
-  // TODO(https://crbug.com/1278249): Call |extract_main_content_function_|,
-  // pass |snapshot| to it, receive results, and send them to |callback|.
-  std::move(callback).Run(std::vector<int32_t>());
+  std::string serialized_snapshot = Screen2xSnapshotToViewHierarchy(snapshot);
+  std::vector<int32_t> content_node_ids;
+
+  if (!extract_main_content_function_(serialized_snapshot, content_node_ids)) {
+    VLOG(1) << "Screen2x did not return main content.";
+  } else {
+    VLOG(2) << "Screen2x returned " << content_node_ids.size() << " node ids:";
+    for (int32_t i : content_node_ids)
+      VLOG(2) << i;
+  }
+  std::move(callback).Run(content_node_ids);
 }
 
 }  // namespace screen_ai
diff --git a/components/services/screen_ai/screen_ai_service_impl.h b/components/services/screen_ai/screen_ai_service_impl.h
index d484b8c..00a54a9 100644
--- a/components/services/screen_ai/screen_ai_service_impl.h
+++ b/components/services/screen_ai/screen_ai_service_impl.h
@@ -51,10 +51,6 @@
       mojo::PendingReceiver<mojom::Screen2xMainContentExtractor>
           main_content_extractor) override;
 
-  // Converts the serialized proto from Screen AI library's annotation function
-  // to a vector of screen_ai::mojom::Node.
-  ui::AXTreeUpdate DecodeAnnotatorProto(const std::string& serialized_proto);
-
   typedef bool (*ScreenAIInitFunction)();
   ScreenAIInitFunction screen_ai_init_function_;
 
diff --git a/components/shared_highlighting/core/common/shared_highlighting_features.cc b/components/shared_highlighting/core/common/shared_highlighting_features.cc
index 2eec2ec..a46aced 100644
--- a/components/shared_highlighting/core/common/shared_highlighting_features.cc
+++ b/components/shared_highlighting/core/common/shared_highlighting_features.cc
@@ -14,9 +14,6 @@
 constexpr base::FeatureParam<int> kPreemptiveLinkGenTimeoutLengthMs{
     &kPreemptiveLinkToTextGeneration, "TimeoutLengthMs", 500};
 
-const base::Feature kSharedHighlightingV2{"SharedHighlightingV2",
-                                          base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kSharedHighlightingAmp {
   "SharedHighlightingAmp",
 #if BUILDFLAG(IS_IOS)
diff --git a/components/shared_highlighting/core/common/shared_highlighting_features.h b/components/shared_highlighting/core/common/shared_highlighting_features.h
index d1107dd4..fbaf89be 100644
--- a/components/shared_highlighting/core/common/shared_highlighting_features.h
+++ b/components/shared_highlighting/core/common/shared_highlighting_features.h
@@ -18,9 +18,6 @@
 // Sets the timeout length for pre-emptive link generation.
 extern const base::FeatureParam<int> kPreemptiveLinkGenTimeoutLengthMs;
 
-// Enables the new UI features for highlighted text.
-extern const base::Feature kSharedHighlightingV2;
-
 // Enables shared highlighting for AMP viewers pages.
 extern const base::Feature kSharedHighlightingAmp;
 
diff --git a/components/signin/public/android/BUILD.gn b/components/signin/public/android/BUILD.gn
index 079a7aa..08742f6 100644
--- a/components/signin/public/android/BUILD.gn
+++ b/components/signin/public/android/BUILD.gn
@@ -108,6 +108,7 @@
     "//third_party/mockito:mockito_java",
   ]
   sources = [
+    "java/src/org/chromium/components/signin/test/util/AccountCapabilitiesBuilder.java",
     "java/src/org/chromium/components/signin/test/util/AccountCapabilitiesFetcherTestUtil.java",
     "java/src/org/chromium/components/signin/test/util/AccountHolder.java",
     "java/src/org/chromium/components/signin/test/util/AccountManagerFacadeUtil.java",
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacade.java b/components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
index dcd3815b..f171d62c 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
@@ -113,7 +113,11 @@
     /**
      * Gets the boolean for whether the account can offer extended sync promos.
      * If the result is not yet fetched, the optional will be empty.
+     *
+     * This method will be removed soon. Use {@link
+     * AccountCapabilities#canOfferExtendedSyncPromos()} instead.
      */
+    @Deprecated
     Optional<Boolean> canOfferExtendedSyncPromos(Account account);
 
     /**
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/test/util/AccountCapabilitiesBuilder.java b/components/signin/public/android/java/src/org/chromium/components/signin/test/util/AccountCapabilitiesBuilder.java
new file mode 100644
index 0000000..c75f0cf
--- /dev/null
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/test/util/AccountCapabilitiesBuilder.java
@@ -0,0 +1,36 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.signin.test.util;
+
+import org.chromium.components.signin.AccountCapabilitiesConstants;
+import org.chromium.components.signin.base.AccountCapabilities;
+
+import java.util.HashMap;
+
+/**
+ * This class provides a builder for the class {@link AccountCapabilities}.
+ *
+ * This class is only used in tests.
+ */
+public final class AccountCapabilitiesBuilder {
+    private final HashMap<String, Boolean> mCapabilities = new HashMap<>();
+
+    /**
+     * Sets the canOfferExtendedSyncPromos capability value.
+     */
+    public AccountCapabilitiesBuilder setCanOfferExtendedSyncPromos(boolean value) {
+        mCapabilities.put(
+                AccountCapabilitiesConstants.CAN_OFFER_EXTENDED_CHROME_SYNC_PROMOS_CAPABILITY_NAME,
+                value);
+        return this;
+    }
+
+    /**
+     * @return {@link AccountCapabilities} object with the capabilities set up with the builder.
+     */
+    public AccountCapabilities build() {
+        return new AccountCapabilities((HashMap<String, Boolean>) mCapabilities.clone());
+    }
+}
diff --git a/components/sync/driver/data_type_controller.cc b/components/sync/driver/data_type_controller.cc
index aa619827..eea500f 100644
--- a/components/sync/driver/data_type_controller.cc
+++ b/components/sync/driver/data_type_controller.cc
@@ -4,6 +4,8 @@
 
 #include "components/sync/driver/data_type_controller.h"
 
+#include "base/notreached.h"
+
 namespace syncer {
 
 DataTypeController::DataTypeController(ModelType type) : type_(type) {}
diff --git a/components/sync/driver/data_type_manager.cc b/components/sync/driver/data_type_manager.cc
index a002e65..d963421 100644
--- a/components/sync/driver/data_type_manager.cc
+++ b/components/sync/driver/data_type_manager.cc
@@ -4,6 +4,8 @@
 
 #include "components/sync/driver/data_type_manager.h"
 
+#include "base/notreached.h"
+
 namespace syncer {
 
 DataTypeManager::ConfigureResult::ConfigureResult() : status(UNKNOWN) {}
diff --git a/components/sync/driver/data_type_status_table.cc b/components/sync/driver/data_type_status_table.cc
index d5878e3..ca9155b 100644
--- a/components/sync/driver/data_type_status_table.cc
+++ b/components/sync/driver/data_type_status_table.cc
@@ -5,6 +5,7 @@
 #include "components/sync/driver/data_type_status_table.h"
 
 #include "base/logging.h"
+#include "base/notreached.h"
 #include "components/sync/driver/data_type_manager.h"
 
 namespace syncer {
diff --git a/components/sync/driver/sync_service_impl_bundle.cc b/components/sync/driver/sync_service_impl_bundle.cc
index 8e7abd36..30e35c8 100644
--- a/components/sync/driver/sync_service_impl_bundle.cc
+++ b/components/sync/driver/sync_service_impl_bundle.cc
@@ -7,7 +7,6 @@
 #include <string>
 #include <utility>
 
-#include "base/callback_helpers.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/sync/base/sync_prefs.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/components/sync/driver/sync_service_impl_bundle.h b/components/sync/driver/sync_service_impl_bundle.h
index 4b0f4220..f09e895 100644
--- a/components/sync/driver/sync_service_impl_bundle.h
+++ b/components/sync/driver/sync_service_impl_bundle.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
diff --git a/components/sync/engine/sync_scheduler.h b/components/sync/engine/sync_scheduler.h
index bd8514a..2a8f550 100644
--- a/components/sync/engine/sync_scheduler.h
+++ b/components/sync/engine/sync_scheduler.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "base/time/time.h"
 #include "components/sync/base/sync_invalidation.h"
diff --git a/components/sync/invalidations/interested_data_types_handler.h b/components/sync/invalidations/interested_data_types_handler.h
index d50c990..a9efffc 100644
--- a/components/sync/invalidations/interested_data_types_handler.h
+++ b/components/sync/invalidations/interested_data_types_handler.h
@@ -5,7 +5,7 @@
 #ifndef COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_HANDLER_H_
 #define COMPONENTS_SYNC_INVALIDATIONS_INTERESTED_DATA_TYPES_HANDLER_H_
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "components/sync/base/model_type.h"
 
 namespace syncer {
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.h b/components/sync/nigori/nigori_sync_bridge_impl.h
index 7d7dcd1..37138768 100644
--- a/components/sync/nigori/nigori_sync_bridge_impl.h
+++ b/components/sync/nigori/nigori_sync_bridge_impl.h
@@ -10,7 +10,6 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "components/sync/engine/nigori/key_derivation_params.h"
diff --git a/components/sync/nigori/pending_local_nigori_commit.h b/components/sync/nigori/pending_local_nigori_commit.h
index 92c16c4..3f6a3b9 100644
--- a/components/sync/nigori/pending_local_nigori_commit.h
+++ b/components/sync/nigori/pending_local_nigori_commit.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <string>
 
-#include "base/callback.h"
 #include "components/sync/engine/sync_encryption_handler.h"
 
 namespace syncer {
diff --git a/components/sync/test/engine/fake_sync_engine.cc b/components/sync/test/engine/fake_sync_engine.cc
index f665bdb..aa81553 100644
--- a/components/sync/test/engine/fake_sync_engine.cc
+++ b/components/sync/test/engine/fake_sync_engine.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/callback.h"
 #include "components/sync/engine/data_type_activation_response.h"
 #include "components/sync/engine/nigori/nigori.h"
 #include "components/sync/engine/sync_engine_host.h"
diff --git a/components/sync/test/engine/fake_sync_engine.h b/components/sync/test/engine/fake_sync_engine.h
index de60ca8b..6565d46a 100644
--- a/components/sync/test/engine/fake_sync_engine.h
+++ b/components/sync/test/engine/fake_sync_engine.h
@@ -9,7 +9,7 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
diff --git a/components/sync/test/fake_server/fake_server_http_post_provider.h b/components/sync/test/fake_server/fake_server_http_post_provider.h
index fb12925..98d2910 100644
--- a/components/sync/test/fake_server/fake_server_http_post_provider.h
+++ b/components/sync/test/fake_server/fake_server_http_post_provider.h
@@ -8,7 +8,6 @@
 #include <atomic>
 #include <string>
 
-#include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
diff --git a/components/sync/trusted_vault/standalone_trusted_vault_client.cc b/components/sync/trusted_vault/standalone_trusted_vault_client.cc
index 691c791f..fcd08bf5 100644
--- a/components/sync/trusted_vault/standalone_trusted_vault_client.cc
+++ b/components/sync/trusted_vault/standalone_trusted_vault_client.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/memory/raw_ptr.h"
diff --git a/components/sync/trusted_vault/standalone_trusted_vault_client.h b/components/sync/trusted_vault/standalone_trusted_vault_client.h
index 7888fab..1bebc9b 100644
--- a/components/sync/trusted_vault/standalone_trusted_vault_client.h
+++ b/components/sync/trusted_vault/standalone_trusted_vault_client.h
@@ -9,7 +9,7 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
diff --git a/components/sync_bookmarks/bookmark_sync_service.h b/components/sync_bookmarks/bookmark_sync_service.h
index 2022a881..5e4771d 100644
--- a/components/sync_bookmarks/bookmark_sync_service.h
+++ b/components/sync_bookmarks/bookmark_sync_service.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <string>
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "components/keyed_service/core/keyed_service.h"
diff --git a/components/sync_device_info/device_info.h b/components/sync_device_info/device_info.h
index 0c856c3..fd02204 100644
--- a/components/sync_device_info/device_info.h
+++ b/components/sync_device_info/device_info.h
@@ -11,7 +11,6 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
 #include "base/time/time.h"
 #include "components/sync/base/model_type.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/components/sync_device_info/device_info_sync_service.h b/components/sync_device_info/device_info_sync_service.h
index 4a54d2c0..11672a2 100644
--- a/components/sync_device_info/device_info_sync_service.h
+++ b/components/sync_device_info/device_info_sync_service.h
@@ -5,8 +5,6 @@
 #ifndef COMPONENTS_SYNC_DEVICE_INFO_DEVICE_INFO_SYNC_SERVICE_H_
 #define COMPONENTS_SYNC_DEVICE_INFO_DEVICE_INFO_SYNC_SERVICE_H_
 
-#include "base/callback.h"
-#include "base/callback_helpers.h"
 #include "base/memory/weak_ptr.h"
 #include "components/keyed_service/core/keyed_service.h"
 
diff --git a/components/sync_device_info/device_info_sync_service_impl.cc b/components/sync_device_info/device_info_sync_service_impl.cc
index ce55a57..62ce998 100644
--- a/components/sync_device_info/device_info_sync_service_impl.cc
+++ b/components/sync_device_info/device_info_sync_service_impl.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "base/callback_helpers.h"
+#include "base/callback.h"
 #include "components/sync/base/report_unrecoverable_error.h"
 #include "components/sync/invalidations/sync_invalidations_service.h"
 #include "components/sync/model/client_tag_based_model_type_processor.h"
diff --git a/components/sync_device_info/device_info_sync_service_impl.h b/components/sync_device_info/device_info_sync_service_impl.h
index 1154409..bb183cf 100644
--- a/components/sync_device_info/device_info_sync_service_impl.h
+++ b/components/sync_device_info/device_info_sync_service_impl.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/callback_helpers.h"
 #include "base/memory/raw_ptr.h"
 #include "components/sync/invalidations/fcm_registration_token_observer.h"
 #include "components/sync/invalidations/interested_data_types_handler.h"
diff --git a/components/sync_device_info/fake_device_info_sync_service.h b/components/sync_device_info/fake_device_info_sync_service.h
index 53dbc96b..12c40b0 100644
--- a/components/sync_device_info/fake_device_info_sync_service.h
+++ b/components/sync_device_info/fake_device_info_sync_service.h
@@ -5,7 +5,6 @@
 #ifndef COMPONENTS_SYNC_DEVICE_INFO_FAKE_DEVICE_INFO_SYNC_SERVICE_H_
 #define COMPONENTS_SYNC_DEVICE_INFO_FAKE_DEVICE_INFO_SYNC_SERVICE_H_
 
-#include "base/callback.h"
 #include "components/sync/test/model/fake_model_type_controller_delegate.h"
 #include "components/sync_device_info/device_info_sync_service.h"
 #include "components/sync_device_info/fake_device_info_tracker.h"
diff --git a/components/sync_preferences/pref_model_associator.cc b/components/sync_preferences/pref_model_associator.cc
index 34433b9..578e2b7 100644
--- a/components/sync_preferences/pref_model_associator.cc
+++ b/components/sync_preferences/pref_model_associator.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/auto_reset.h"
+#include "base/callback.h"
 #include "base/containers/contains.h"
 #include "base/feature_list.h"
 #include "base/json/json_reader.h"
diff --git a/components/sync_preferences/pref_model_associator.h b/components/sync_preferences/pref_model_associator.h
index 71c8e4e..70768f8 100644
--- a/components/sync_preferences/pref_model_associator.h
+++ b/components/sync_preferences/pref_model_associator.h
@@ -10,7 +10,7 @@
 #include <string>
 #include <unordered_map>
 
-#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
diff --git a/content/browser/first_party_sets/first_party_sets_handler_impl.cc b/content/browser/first_party_sets/first_party_sets_handler_impl.cc
index 22103add..0ee2feec 100644
--- a/content/browser/first_party_sets/first_party_sets_handler_impl.cc
+++ b/content/browser/first_party_sets/first_party_sets_handler_impl.cc
@@ -117,10 +117,16 @@
                                      const std::string& flag_value,
                                      SetsReadyOnceCallback on_sets_ready) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!initialized_);
+  DCHECK(persisted_sets_path_.empty());
+  DCHECK(on_sets_ready_.is_null());
+
+  initialized_ = true;
   on_sets_ready_ = std::move(on_sets_ready);
   SetPersistedSets(user_data_dir);
 
   if (IsEnabled()) {
+    DCHECK(!on_sets_ready_.is_null());
     sets_loader_->SetManuallySpecifiedSet(flag_value);
     if (!embedder_will_provide_public_sets_) {
       sets_loader_->SetComponentSets(base::File());
@@ -144,6 +150,7 @@
 
 void FirstPartySetsHandlerImpl::ResetForTesting() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  initialized_ = false;
   enabled_ = GetContentClient()->browser()->IsFirstPartySetsEnabled();
   embedder_will_provide_public_sets_ =
       GetContentClient()->browser()->WillProvidePublicFirstPartySets();
@@ -166,6 +173,8 @@
 void FirstPartySetsHandlerImpl::SetPersistedSets(
     const base::FilePath& user_data_dir) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!raw_persisted_sets_.has_value());
+  DCHECK(persisted_sets_path_.empty());
   if (user_data_dir.empty()) {
     VLOG(1) << "Empty path. Failed loading serialized First-Party Sets file.";
     // We have to continue, in case the embedder has enabled FPS but has not
@@ -189,18 +198,36 @@
 void FirstPartySetsHandlerImpl::OnReadPersistedSetsFile(
     const std::string& raw_persisted_sets) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!raw_persisted_sets_.has_value());
   raw_persisted_sets_ = raw_persisted_sets;
   UmaHistogramTimes(
       "Cookie.FirstPartySets.InitializationDuration.ReadPersistedSets2",
       construction_timer_.Elapsed());
-  ClearSiteDataOnChangedSetsIfReady();
+
+  if (sets_.has_value()) {
+    ClearSiteDataOnChangedSets();
+
+    if (IsEnabled()) {
+      DCHECK(!on_sets_ready_.is_null());
+      std::move(on_sets_ready_).Run(sets_.value());
+    }
+  }
 }
 
 void FirstPartySetsHandlerImpl::SetCompleteSets(
     base::flat_map<net::SchemefulSite, net::SchemefulSite> sets) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!sets_.has_value());
   sets_ = std::move(sets);
-  ClearSiteDataOnChangedSetsIfReady();
+
+  if (raw_persisted_sets_.has_value()) {
+    ClearSiteDataOnChangedSets();
+
+    if (IsEnabled()) {
+      DCHECK(!on_sets_ready_.is_null());
+      std::move(on_sets_ready_).Run(sets_.value());
+    }
+  }
 }
 
 // static
@@ -233,10 +260,10 @@
   return result;
 }
 
-void FirstPartySetsHandlerImpl::ClearSiteDataOnChangedSetsIfReady() {
+void FirstPartySetsHandlerImpl::ClearSiteDataOnChangedSets() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!raw_persisted_sets_.has_value() || !sets_.has_value())
-    return;
+  DCHECK(sets_.has_value());
+  DCHECK(raw_persisted_sets_.has_value());
 
   base::flat_set<net::SchemefulSite> diff =
       ComputeSetsDiff(FirstPartySetParser::DeserializeFirstPartySets(
@@ -245,9 +272,6 @@
 
   // TODO(shuuran@chromium.org): Implement site state clearing.
 
-  if (!on_sets_ready_.is_null() && IsEnabledAndReady())
-    std::move(on_sets_ready_).Run(sets_.value());
-
   if (!persisted_sets_path_.empty()) {
     base::ThreadPool::PostTask(
         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
diff --git a/content/browser/first_party_sets/first_party_sets_handler_impl.h b/content/browser/first_party_sets/first_party_sets_handler_impl.h
index f1a6d4d..13a82a80 100644
--- a/content/browser/first_party_sets/first_party_sets_handler_impl.h
+++ b/content/browser/first_party_sets/first_party_sets_handler_impl.h
@@ -55,10 +55,9 @@
   // persisted sets, since we may still need to clear data from a previous
   // invocation of Chromium which had First-Party Sets enabled.
   //
-  // TODO(https://crbug.com/1309188): Init() should be called in the
-  // BrowserMainLoop::PreMainMessageLoopRun(). But just in case it's
-  // accidentally called from other places, make sure it's no-op for the
-  // following calls.
+  // If First-Party Sets is enabled, `on_sets_ready` must not be null.
+  //
+  // Must be called exactly once.
   void Init(const base::FilePath& user_data_dir,
             const std::string& flag_value,
             SetsReadyOnceCallback on_sets_ready);
@@ -101,31 +100,34 @@
                             bool embedder_will_provide_public_sets);
 
   // This method reads the persisted First-Party Sets from the file under
-  // `user_data_dir`.
+  // `user_data_dir`. Must be called exactly once.
   void SetPersistedSets(const base::FilePath& user_data_dir);
 
-  // Stores the read persisted sets in `raw_persisted_sets_`.
+  // Stores the read persisted sets in `raw_persisted_sets_`. Must be called
+  // exactly once.
   void OnReadPersistedSetsFile(const std::string& raw_persisted_sets);
 
-  // Sets the current First-Party Sets data.
+  // Sets the current First-Party Sets data. Must be called exactly once.
   void SetCompleteSets(FlattenedSets sets);
 
-  // Checks the required inputs have been received, and if so:
+  // Does the following:
   // 1) computes the diff between the `sets_` and the parsed
   // `raw_persisted_sets_`;
   // 2) clears the site data of the set of sites based on the diff;
-  // 3) calls `on_sets_ready_` if conditions are met;
-  // 4) writes the current First-Party Sets to the file in
+  // 3) writes the current First-Party Sets to the file in
   // `persisted_sets_path_`.
   //
   // TODO(shuuran@chromium.org): Implement the code to clear site state.
-  void ClearSiteDataOnChangedSetsIfReady();
+  void ClearSiteDataOnChangedSets() const;
 
   // Returns true if:
   // * First-Party Sets are enabled;
   // * `sets_` is ready to be used.
   bool IsEnabledAndReady() const;
 
+  // Whether Init has been called already or not.
+  bool initialized_ = false;
+
   // Represents the mapping of site -> site, where keys are members of sets, and
   // values are owners of the sets. Owners are explicitly represented as members
   // of the set.
diff --git a/content/browser/speculation_rules/prefetch/prefetch_document_manager_unittest.cc b/content/browser/speculation_rules/prefetch/prefetch_document_manager_unittest.cc
index fc09b72..e93b32e 100644
--- a/content/browser/speculation_rules/prefetch/prefetch_document_manager_unittest.cc
+++ b/content/browser/speculation_rules/prefetch/prefetch_document_manager_unittest.cc
@@ -64,7 +64,9 @@
     RenderViewHostTestHarness::TearDown();
   }
 
-  RenderFrameHostImpl* GetMainFrame() { return web_contents_->GetMainFrame(); }
+  RenderFrameHostImpl& GetMainFrame() {
+    return web_contents_->GetPrimaryPage().GetMainDocument();
+  }
 
   GURL GetSameOriginUrl(const std::string& path) {
     return GURL("https://example.com" + path);
@@ -133,7 +135,7 @@
 
   // Process the candidates with the |PrefetchDocumentManager| for the current
   // document.
-  PrefetchDocumentManager::GetOrCreateForCurrentDocument(GetMainFrame())
+  PrefetchDocumentManager::GetOrCreateForCurrentDocument(&GetMainFrame())
       ->ProcessCandidates(candidates);
 
   // Check that the candidates that should be prefetched were sent to
diff --git a/content/public/browser/first_party_sets_handler.h b/content/public/browser/first_party_sets_handler.h
index 3ff5dea..f770495 100644
--- a/content/public/browser/first_party_sets_handler.h
+++ b/content/public/browser/first_party_sets_handler.h
@@ -75,6 +75,8 @@
   // are answered until initialization is complete. Must not be called if
   // `ContentBrowserClient::WillProvidePublicFirstPartySets` returns false or
   // `ContentBrowserClient::IsFrstpartySetsEnabled` returns false.
+  //
+  // Must be called at most once.
   virtual void SetPublicFirstPartySets(base::File sets_file) = 0;
 
   // Resets the state on the instance for testing.
diff --git a/fuchsia/engine/mojom/BUILD.gn b/fuchsia/engine/mojom/BUILD.gn
index 4f9edde..cadb5ed 100644
--- a/fuchsia/engine/mojom/BUILD.gn
+++ b/fuchsia/engine/mojom/BUILD.gn
@@ -21,7 +21,7 @@
     ]
     traits_headers = [ "web_engine_media_resource_provider_mojom_traits.h" ]
     traits_public_deps = [
-      "//fuchsia/mojom:traits",
+      "//mojo/public/cpp/base/fuchsia:traits",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.media",
     ]
   }
diff --git a/fuchsia/engine/mojom/DEPS b/fuchsia/engine/mojom/DEPS
index 31dab83..4d4fa2d5 100644
--- a/fuchsia/engine/mojom/DEPS
+++ b/fuchsia/engine/mojom/DEPS
@@ -1,5 +1,5 @@
 specific_include_rules = {
   "web_engine_.*_provider_mojom_traits\.h": [
-    "+fuchsia/mojom/fidl_interface_request_mojom_traits.h",
+    "+mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits.h",
   ],
 }
diff --git a/fuchsia/engine/mojom/web_engine_media_resource_provider_mojom_traits.h b/fuchsia/engine/mojom/web_engine_media_resource_provider_mojom_traits.h
index 347fdc3..5807ba1 100644
--- a/fuchsia/engine/mojom/web_engine_media_resource_provider_mojom_traits.h
+++ b/fuchsia/engine/mojom/web_engine_media_resource_provider_mojom_traits.h
@@ -7,7 +7,7 @@
 
 #include <fuchsia/media/cpp/fidl.h>
 
-#include "fuchsia/mojom/fidl_interface_request_mojom_traits.h"
+#include "mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/fuchsia/mojom/DEPS b/fuchsia/mojom/DEPS
deleted file mode 100644
index ef8ad28..0000000
--- a/fuchsia/mojom/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+mojo/public",
-]
diff --git a/infra/config/generated/builders/ci/win-swangle-x86/properties.json b/infra/config/generated/builders/ci/win-swangle-x86/properties.json
index 31e1f463..91ee1f3 100644
--- a/infra/config/generated/builders/ci/win-swangle-x86/properties.json
+++ b/infra/config/generated/builders/ci/win-swangle-x86/properties.json
@@ -1,9 +1,8 @@
 {
-  "$build/goma": {
-    "enable_ats": true,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org",
-    "use_luci_auth": true
+  "$build/reclient": {
+    "instance": "rbe-chromium-trusted",
+    "jobs": 80,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/subprojects/chromium/ci/chromium.swangle.star b/infra/config/subprojects/chromium/ci/chromium.swangle.star
index 5ea741d..430a809 100644
--- a/infra/config/subprojects/chromium/ci/chromium.swangle.star
+++ b/infra/config/subprojects/chromium/ci/chromium.swangle.star
@@ -162,5 +162,7 @@
         short_name = "x86",
     ),
     executable = ci.DEFAULT_EXECUTABLE,
-    goma_backend = goma.backend.RBE_PROD,
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.LOW_JOBS_FOR_CI,
+    reclient_instance = rbe_instance.DEFAULT,
 )
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index b2649d5..dde7679 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1036,6 +1036,21 @@
                                    policy::key::kEnableExperimentalPolicies)];
   }
 
+  NSString* metrics_reporting_key = @"MetricsReportingEnabled";
+  switch ([defaults integerForKey:metrics_reporting_key]) {
+    case 1:
+      // Metrics reporting forced.
+      [testing_policies setValue:@(YES) forKey:metrics_reporting_key];
+      break;
+    case 2:
+      // Metrics reporting disabled.
+      [testing_policies setValue:@(NO) forKey:metrics_reporting_key];
+      break;
+    default:
+      // Metrics reporting not managed.
+      break;
+  }
+
   // Warning: Add new flags to TestingPoliciesHash() below.
 
   return testing_policies;
@@ -1046,12 +1061,12 @@
 NSString* TestingPoliciesHash() {
   NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
   return [NSString
-      stringWithFormat:@"%d|%d|%d|%d|%@|%d|%d|%d|%d|%d|%d|%d",
+      stringWithFormat:@"%d|%d|%d|%d|%@|%d|%d|%d|%d|%d|%d|%d|%d|%@|%d",
                        [defaults boolForKey:@"DisallowChromeDataInBackups"],
                        [defaults boolForKey:@"EnableSyncDisabledPolicy"],
                        [defaults boolForKey:@"EnableSamplePolicies"],
-                       (int)[defaults
-                           integerForKey:@"IncognitoModeAvailability"],
+                       static_cast<int>([defaults
+                           integerForKey:@"IncognitoModeAvailability"]),
                        [defaults stringForKey:@"RestrictAccountsToPatterns"],
                        [defaults boolForKey:@"SyncTypesListBookmarks"],
                        [defaults boolForKey:@"SyncTypesListReadingList"],
@@ -1059,7 +1074,12 @@
                        [defaults boolForKey:@"SyncTypesListPasswords"],
                        [defaults boolForKey:@"SyncTypesListAutofill"],
                        [defaults boolForKey:@"SyncTypesListTypedUrls"],
-                       [defaults boolForKey:@"SyncTypesListTabs"]];
+                       [defaults boolForKey:@"SyncTypesListTabs"],
+                       static_cast<int>(
+                           [defaults integerForKey:@"BrowserSignin"]),
+                       [defaults stringForKey:@"NTPLocation"],
+                       static_cast<int>([defaults
+                           integerForKey:@"MetricsReportingEnabled"])];
 }
 }  // namespace
 
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
index 6e0272d..1ce0cb1 100644
--- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
+++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -270,6 +270,28 @@
 		</dict>
 		<dict>
 			<key>Type</key>
+			<string>PSMultiValueSpecifier</string>
+			<key>Title</key>
+			<string>UMA Reporting</string>
+			<key>Key</key>
+			<string>MetricsReportingEnabled</string>
+			<key>DefaultValue</key>
+			<integer>0</integer>
+			<key>Values</key>
+			<array>
+				<integer>0</integer>
+				<integer>1</integer>
+				<integer>2</integer>
+			</array>
+			<key>Titles</key>
+			<array>
+				<string>Default</string>
+				<string>UMA Reporting Forced</string>
+				<string>UMA Reporting Disabled</string>
+			</array>
+		</dict>
+		<dict>
+			<key>Type</key>
 			<string>PSTextFieldSpecifier</string>
 			<key>Title</key>
 			<string>CBCM Enrollment Token</string>
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
index ec3328ab..79a7da2c 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
@@ -58,6 +58,7 @@
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_ui_util",
     "//ios/chrome/browser/ui/content_suggestions:public",
     "//ios/chrome/browser/ui/content_suggestions/identifier",
+    "//ios/chrome/browser/ui/icons:symbols",
     "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common:string_util",
@@ -86,6 +87,7 @@
 
   deps = [
     "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser/ui/icons:symbols",
     "//ios/third_party/material_components_ios",
     "//ui/base:base",
   ]
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_item.mm
index 5441e19..4d23365 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_item.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_item.mm
@@ -7,6 +7,7 @@
 #include "base/check.h"
 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_cell.h"
 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.h"
+#import "ios/chrome/browser/ui/icons/chrome_symbol.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -69,7 +70,10 @@
   // The accessibilityUserInputLabel should just be the title, with nothing
   // extra from the accessibilityLabel.
   cell.accessibilityUserInputLabels = @[ self.title ];
-  cell.iconView.image = ImageForCollectionShortcutType(_collectionShortcutType);
+  cell.iconView.image =
+      UseSymbols() ? SymbolForCollectionShortcutType(_collectionShortcutType)
+                   : ImageForCollectionShortcutType(_collectionShortcutType);
+  cell.iconView.contentMode = UIViewContentModeCenter;
   if (self.count != 0) {
     cell.countLabel.text = [@(self.count) stringValue];
     cell.countContainer.hidden = NO;
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_shortcut_tile_view.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_shortcut_tile_view.mm
index c7bc669..aba9b56f 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_shortcut_tile_view.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_shortcut_tile_view.mm
@@ -7,6 +7,7 @@
 #import <MaterialComponents/MaterialTypography.h>
 
 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_item.h"
+#import "ios/chrome/browser/ui/icons/chrome_symbol.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/util/constraints_ui_util.h"
 
@@ -58,9 +59,13 @@
     // extra from the accessibilityLabel.
     self.accessibilityUserInputLabels = @[ config.title ];
     _iconView.image =
-        ImageForCollectionShortcutType(config.collectionShortcutType);
-      _countContainer.hidden = !config.count;
-      _countLabel.text = [@(config.count) stringValue];
+        UseSymbols()
+            ? SymbolForCollectionShortcutType(config.collectionShortcutType)
+            : ImageForCollectionShortcutType(config.collectionShortcutType);
+    _iconView.contentMode = UIViewContentModeCenter;
+
+    _countContainer.hidden = !config.count;
+    _countLabel.text = [@(config.count) stringValue];
     _config = config;
   }
   return self;
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.h b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.h
index 73acf8b..6b50844 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.h
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.h
@@ -23,12 +23,18 @@
 
 // Returns a localized title for a given collection shortcut type.
 NSString* TitleForCollectionShortcutType(NTPCollectionShortcutType action);
+
 // Returns an icon for a given collection shortcut type to be used in an NTP
 // tile.
 UIImage* ImageForCollectionShortcutType(NTPCollectionShortcutType action);
-// Returns a localized string that can be used as an accessibility label for the
-// reading list tile when it's displaying the |count| badge, or, if |count| = 0,
-// for a reading list tile with no badge.
+
+// Returns a symbol image for a given collection shortcut type to be used in an
+// NTP tile.
+UIImage* SymbolForCollectionShortcutType(NTPCollectionShortcutType type);
+
+// Returns a localized string that can be used as an accessibility label for
+// the reading list tile when it's displaying the |count| badge, or, if
+// |count| = 0, for a reading list tile with no badge.
 NSString* AccessibilityLabelForReadingListCellWithCount(int count);
 
 #endif  // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_CONTENT_SUGGESTIONS_TILE_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.mm
index 5a43f59..4d641c9 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_constants.mm
@@ -7,6 +7,7 @@
 #include "base/notreached.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#import "ios/chrome/browser/ui/icons/chrome_symbol.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -14,7 +15,16 @@
 #error "This file requires ARC support."
 #endif
 
-// Returns the title to use for a cell with |action|.
+namespace {
+
+// The size of the symbol image used in content suggestions.
+NSInteger kSymbolContentSuggestionsPointSize = 22;
+
+// Specific symbols used in the content suggestions.
+NSString* kContentSuggestionsBookmarksSymbol = @"star.fill";
+
+}  // namespace
+
 NSString* TitleForCollectionShortcutType(NTPCollectionShortcutType type) {
   switch (type) {
     case NTPCollectionShortcutTypeBookmark:
@@ -31,7 +41,6 @@
   }
 }
 
-// Returns the image to use for a cell with |action|.
 UIImage* ImageForCollectionShortcutType(NTPCollectionShortcutType type) {
   NSString* imageName = nil;
   switch (type) {
@@ -55,6 +64,30 @@
       imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
 }
 
+UIImage* SymbolForCollectionShortcutType(NTPCollectionShortcutType type) {
+  // TODO(crbug.com/1315544): use right SF symbols.
+  NSString* imageName = nil;
+  switch (type) {
+    case NTPCollectionShortcutTypeBookmark:
+      imageName = kContentSuggestionsBookmarksSymbol;
+      break;
+    case NTPCollectionShortcutTypeReadingList:
+      imageName = kContentSuggestionsBookmarksSymbol;
+      break;
+    case NTPCollectionShortcutTypeRecentTabs:
+      imageName = kContentSuggestionsBookmarksSymbol;
+      break;
+    case NTPCollectionShortcutTypeHistory:
+      imageName = kContentSuggestionsBookmarksSymbol;
+      break;
+    case NTPCollectionShortcutTypeCount:
+      NOTREACHED();
+      break;
+  }
+  return DefaultSymbolTemplateWithPointSize(imageName,
+                                            kSymbolContentSuggestionsPointSize);
+}
+
 NSString* AccessibilityLabelForReadingListCellWithCount(int count) {
   BOOL hasMultipleArticles = count > 1;
   int messageID =
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
index 9f2d7e8b..ae2ea053 100644
--- a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
+++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
@@ -28,7 +28,7 @@
 // Width of the identity control if nothing is contraining it.
 constexpr CGFloat kIdentityControlMaxWidth = 327.;
 // Margin above the identity button.
-constexpr CGFloat kIdentityTopMargin = 16.;
+constexpr CGFloat kTopMarginForBottomView = 16.;
 // Margin between elements in the bottom view.
 constexpr CGFloat kBottomViewInnerVerticalMargin = 8.;
 
@@ -169,8 +169,7 @@
     widthConstraint.priority = UILayoutPriorityDefaultHigh;
     [NSLayoutConstraint activateConstraints:@[
       [self.identityControl.topAnchor
-          constraintEqualToAnchor:self.specificContentView.topAnchor
-                         constant:kIdentityTopMargin],
+          constraintEqualToAnchor:self.specificContentView.topAnchor],
       [self.identityControl.centerXAnchor
           constraintEqualToAnchor:self.specificContentView.centerXAnchor],
       [self.identityControl.widthAnchor
@@ -190,7 +189,7 @@
   [NSLayoutConstraint activateConstraints:@[
     [self.bottomView.topAnchor
         constraintGreaterThanOrEqualToAnchor:topAnchorForBottomView
-                                    constant:kIdentityTopMargin],
+                                    constant:kTopMarginForBottomView],
     [self.bottomView.bottomAnchor
         constraintEqualToAnchor:self.specificContentView.bottomAnchor],
     [self.bottomView.centerXAnchor
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
index 7dbc176e..c141187f 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
@@ -75,25 +75,28 @@
     viewController.view.translatesAutoresizingMaskIntoConstraints = NO;
     AddSameConstraints(viewController.view, _popupContainerView);
 
-    // Add bottom separator. This will only be visible on iPad where
-    // the omnibox doesn't fill the whole screen.
-    _bottomSeparator = [[UIView alloc] initWithFrame:CGRectZero];
-    _bottomSeparator.translatesAutoresizingMaskIntoConstraints = NO;
-    _bottomSeparator.backgroundColor = [UIColor colorNamed:kToolbarShadowColor];
+    if (!base::FeatureList::IsEnabled(kIOSOmniboxUpdatedPopupUI)) {
+      // Add bottom separator. This will only be visible on iPad where
+      // the omnibox doesn't fill the whole screen.
+      _bottomSeparator = [[UIView alloc] initWithFrame:CGRectZero];
+      _bottomSeparator.translatesAutoresizingMaskIntoConstraints = NO;
+      _bottomSeparator.backgroundColor =
+          [UIColor colorNamed:kToolbarShadowColor];
 
-    [_popupContainerView addSubview:self.bottomSeparator];
-    CGFloat separatorHeight =
-        ui::AlignValueToUpperPixel(kToolbarSeparatorHeight);
-    [NSLayoutConstraint activateConstraints:@[
-      [self.bottomSeparator.heightAnchor
-          constraintEqualToConstant:separatorHeight],
-      [self.bottomSeparator.leadingAnchor
-          constraintEqualToAnchor:_popupContainerView.leadingAnchor],
-      [self.bottomSeparator.trailingAnchor
-          constraintEqualToAnchor:_popupContainerView.trailingAnchor],
-      [self.bottomSeparator.topAnchor
-          constraintEqualToAnchor:_popupContainerView.bottomAnchor],
-    ]];
+      [_popupContainerView addSubview:self.bottomSeparator];
+      CGFloat separatorHeight =
+          ui::AlignValueToUpperPixel(kToolbarSeparatorHeight);
+      [NSLayoutConstraint activateConstraints:@[
+        [self.bottomSeparator.heightAnchor
+            constraintEqualToConstant:separatorHeight],
+        [self.bottomSeparator.leadingAnchor
+            constraintEqualToAnchor:_popupContainerView.leadingAnchor],
+        [self.bottomSeparator.trailingAnchor
+            constraintEqualToAnchor:_popupContainerView.trailingAnchor],
+        [self.bottomSeparator.topAnchor
+            constraintEqualToAnchor:_popupContainerView.bottomAnchor],
+      ]];
+    }
   }
   return self;
 }
diff --git a/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h b/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h
index 2381d126..5b58f61 100644
--- a/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h
+++ b/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h
@@ -14,6 +14,7 @@
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_pedal.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h"
 #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h"
 #import "ios/chrome/browser/ui/util/named_guide.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/swift_bridge.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
index 17b2c314..317de91c 100644
--- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
+++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
@@ -40,10 +40,16 @@
   }
 }
 
+/// Returns the closest pixel-aligned value higher than `value`, taking the scale
+/// factor into account. At a scale of 1, equivalent to ceil().
+func alignValueToUpperPixel(_ value: CGFloat) -> CGFloat {
+  let scale = UIScreen.main.scale
+  return ceil(value * scale) / scale
+}
+
 struct PopupView: View {
   enum Dimensions {
     static let matchListRowInsets = EdgeInsets(.zero)
-    static let selfSizingListBottomMargin: CGFloat = 16
 
     enum VariationOne {
       static let pedalSectionSeparatorPadding = EdgeInsets(
@@ -51,6 +57,8 @@
       static let visibleTopContentInset: CGFloat = 4
       // This allows hiding floating section headers at the top of the list in variation one.
       static let hiddenTopContentInset: CGFloat = -50
+
+      static let selfSizingListBottomMargin: CGFloat = 8
     }
 
     enum VariationTwo {
@@ -61,6 +69,8 @@
       // Default list row insets. These are removed to inset the popup to the
       // width of the omnibox.
       static let defaultInset: CGFloat = 16
+
+      static let selfSizingListBottomMargin: CGFloat = 16
     }
   }
 
@@ -161,7 +171,7 @@
           // If there is only one row or less in a section, no row separators.
           let shouldDisplayCustomSeparator =
             !highlighted && (section.matches.count > 1)
-            && (matchIndex < section.matches.count - 1 || popupUIVariation == .one)
+            && (matchIndex < section.matches.count - 1)
 
           PopupMatchRowView(
             match: match,
@@ -209,6 +219,20 @@
   }
 
   @ViewBuilder
+  var bottomSeparator: some View {
+    Color.toolbarShadow.frame(height: alignValueToUpperPixel(kToolbarSeparatorHeight))
+  }
+
+  var selfSizingListBottomMargin: CGFloat {
+    switch popupUIVariation {
+    case .one:
+      return Dimensions.VariationOne.selfSizingListBottomMargin
+    case .two:
+      return Dimensions.VariationTwo.selfSizingListBottomMargin
+    }
+  }
+
+  @ViewBuilder
   var listView: some View {
     let commonListModifier = AccessibilityIdentifierModifier(
       identifier: kOmniboxPopupTableViewAccessibilityIdentifier
@@ -226,7 +250,7 @@
         ZStack(alignment: .top) {
           listBackground.frame(height: selfSizingListHeight)
           SelfSizingList(
-            bottomMargin: Dimensions.selfSizingListBottomMargin,
+            bottomMargin: selfSizingListBottomMargin,
             listModifier: selfSizingListModifier,
             content: {
               listContent(geometry: geometry)
@@ -240,6 +264,7 @@
             selfSizingListHeight = height
           }
         }
+        bottomSeparator.offset(x: 0, y: selfSizingListHeight ?? 0)
       } else {
         List {
           listContent(geometry: geometry)
diff --git a/ios/chrome/common/ui/colors/Color+Chrome.swift b/ios/chrome/common/ui/colors/Color+Chrome.swift
index cc36345..3799f6e 100644
--- a/ios/chrome/common/ui/colors/Color+Chrome.swift
+++ b/ios/chrome/common/ui/colors/Color+Chrome.swift
@@ -76,8 +76,13 @@
     return Color(kTableViewRowHighlightColor)
   }
 
-  /// The table view sseparator color.
+  /// The table view separator color.
   public static var separator: Color {
     return Color(kSeparatorColor)
   }
+
+  /// The toolbar shadow color.
+  public static var toolbarShadow: Color {
+    return Color(kToolbarShadowColor)
+  }
 }
diff --git a/media/fuchsia/mojom/BUILD.gn b/media/fuchsia/mojom/BUILD.gn
index 3918575..8e68e46 100644
--- a/media/fuchsia/mojom/BUILD.gn
+++ b/media/fuchsia/mojom/BUILD.gn
@@ -21,7 +21,7 @@
     ]
     traits_headers = [ "fuchsia_media_resource_provider_mojom_traits.h" ]
     traits_public_deps = [
-      "//fuchsia/mojom:traits",
+      "//mojo/public/cpp/base/fuchsia:traits",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.media.drm",
     ]
   }
diff --git a/media/fuchsia/mojom/DEPS b/media/fuchsia/mojom/DEPS
index 207080cb..5222e05 100644
--- a/media/fuchsia/mojom/DEPS
+++ b/media/fuchsia/mojom/DEPS
@@ -1,5 +1,5 @@
 specific_include_rules = {
   "fuchsia_.*_provider_mojom_traits\.h": [
-    "+fuchsia/mojom/fidl_interface_request_mojom_traits.h",
+    "+mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits.h",
   ],
 }
diff --git a/media/fuchsia/mojom/fuchsia_media_resource_provider_mojom_traits.h b/media/fuchsia/mojom/fuchsia_media_resource_provider_mojom_traits.h
index 30b18a0..18bfe1e 100644
--- a/media/fuchsia/mojom/fuchsia_media_resource_provider_mojom_traits.h
+++ b/media/fuchsia/mojom/fuchsia_media_resource_provider_mojom_traits.h
@@ -7,7 +7,7 @@
 
 #include <fuchsia/media/drm/cpp/fidl.h>
 
-#include "fuchsia/mojom/fidl_interface_request_mojom_traits.h"
+#include "mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits.h"
 
 namespace mojo {
 
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index 1fd9df7..c64aaae 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -347,6 +347,14 @@
   return is_low_power_intel;
 }
 
+bool IsModeDecoding(VaapiWrapper::CodecMode mode) {
+  return mode == VaapiWrapper::CodecMode::kDecode
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+         || VaapiWrapper::CodecMode::kDecodeProtected
+#endif
+      ;
+}
+
 bool IsModeEncoding(VaapiWrapper::CodecMode mode) {
   return mode == VaapiWrapper::CodecMode::kEncodeConstantBitrate ||
          mode == VaapiWrapper::CodecMode::kEncodeConstantQuantizationParameter;
@@ -3279,8 +3287,11 @@
   va_res = vaEndPicture(va_display_, va_context_id_);
   VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVAEndPicture, false);
 
-  UMA_HISTOGRAM_TIMES("Media.PlatformVideoDecoding.Decode",
-                      base::TimeTicks::Now() - decode_start_time);
+  if (IsModeDecoding(mode_) && va_profile_ != VAProfileNone &&
+      va_profile_ != VAProfileJPEGBaseline) {
+    UMA_HISTOGRAM_TIMES("Media.PlatformVideoDecoding.Decode",
+                        base::TimeTicks::Now() - decode_start_time);
+  }
 
   return true;
 }
diff --git a/fuchsia/mojom/BUILD.gn b/mojo/public/cpp/base/fuchsia/BUILD.gn
similarity index 87%
rename from fuchsia/mojom/BUILD.gn
rename to mojo/public/cpp/base/fuchsia/BUILD.gn
index ee569f0..32865f5 100644
--- a/fuchsia/mojom/BUILD.gn
+++ b/mojo/public/cpp/base/fuchsia/BUILD.gn
@@ -22,7 +22,7 @@
 
       traits_headers = [
         "//base/testfidl/cpp/fidl.h",
-        "//fuchsia/mojom/test_interface_request_mojom_traits.h",
+        "//mojo/public/cpp/base/fuchsia/test_interface_request_mojom_traits.h",
       ]
       traits_public_deps = [
         ":traits",
@@ -48,6 +48,8 @@
   ]
 }
 
+# TODO(crbug/1081525): Consider merging into //mojo:mojo_unittests, possibly
+# via ../:tests.
 test("fuchsia_mojo_unittests") {
   sources = [
     "fidl_interface_request_mojom_traits_unittest.cc",
@@ -63,8 +65,5 @@
     "//testing/gtest",
   ]
 
-  visibility = [
-    ":*",
-    "//fuchsia:gn_all",
-  ]
+  visibility = []
 }
diff --git a/mojo/public/cpp/base/fuchsia/DIR_METADATA b/mojo/public/cpp/base/fuchsia/DIR_METADATA
new file mode 100644
index 0000000..210aa6a
--- /dev/null
+++ b/mojo/public/cpp/base/fuchsia/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//build/fuchsia/COMMON_METADATA"
diff --git a/fuchsia/mojom/OWNERS b/mojo/public/cpp/base/fuchsia/OWNERS
similarity index 84%
rename from fuchsia/mojom/OWNERS
rename to mojo/public/cpp/base/fuchsia/OWNERS
index 1feb514..e37b6cd 100644
--- a/fuchsia/mojom/OWNERS
+++ b/mojo/public/cpp/base/fuchsia/OWNERS
@@ -1,3 +1,5 @@
+file://build/fuchsia/OWNERS
+
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
 per-file *_mojom_traits*.*=set noparent
diff --git a/fuchsia/mojom/example.mojom b/mojo/public/cpp/base/fuchsia/example.mojom
similarity index 100%
rename from fuchsia/mojom/example.mojom
rename to mojo/public/cpp/base/fuchsia/example.mojom
diff --git a/fuchsia/mojom/fidl_interface_request_mojom_traits.h b/mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits.h
similarity index 81%
rename from fuchsia/mojom/fidl_interface_request_mojom_traits.h
rename to mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits.h
index b2e06bb..67455a4 100644
--- a/fuchsia/mojom/fidl_interface_request_mojom_traits.h
+++ b/mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits.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 FUCHSIA_MOJOM_FIDL_INTERFACE_REQUEST_MOJOM_TRAITS_H_
-#define FUCHSIA_MOJOM_FIDL_INTERFACE_REQUEST_MOJOM_TRAITS_H_
+#ifndef MOJO_PUBLIC_CPP_BASE_FUCHSIA_FIDL_INTERFACE_REQUEST_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_FUCHSIA_FIDL_INTERFACE_REQUEST_MOJOM_TRAITS_H_
 
 #include <lib/fidl/cpp/interface_request.h>
 
@@ -33,4 +33,4 @@
 
 }  // namespace mojo
 
-#endif  // FUCHSIA_MOJOM_FIDL_INTERFACE_REQUEST_MOJOM_TRAITS_H_
+#endif  // MOJO_PUBLIC_CPP_BASE_FUCHSIA_FIDL_INTERFACE_REQUEST_MOJOM_TRAITS_H_
diff --git a/fuchsia/mojom/fidl_interface_request_mojom_traits_unittest.cc b/mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits_unittest.cc
similarity index 88%
rename from fuchsia/mojom/fidl_interface_request_mojom_traits_unittest.cc
rename to mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits_unittest.cc
index 0d67fa21..3619016 100644
--- a/fuchsia/mojom/fidl_interface_request_mojom_traits_unittest.cc
+++ b/mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "base/test/task_environment.h"
 #include "base/testfidl/cpp/fidl.h"
-#include "fuchsia/mojom/example.mojom.h"
-#include "fuchsia/mojom/test_interface_request_mojom_traits.h"
+#include "mojo/public/cpp/base/fuchsia/example.mojom.h"
+#include "mojo/public/cpp/base/fuchsia/test_interface_request_mojom_traits.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/fuchsia/mojom/test_interface_request_mojom_traits.h b/mojo/public/cpp/base/fuchsia/test_interface_request_mojom_traits.h
similarity index 62%
rename from fuchsia/mojom/test_interface_request_mojom_traits.h
rename to mojo/public/cpp/base/fuchsia/test_interface_request_mojom_traits.h
index cdae0d69..7b14d095 100644
--- a/fuchsia/mojom/test_interface_request_mojom_traits.h
+++ b/mojo/public/cpp/base/fuchsia/test_interface_request_mojom_traits.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 FUCHSIA_MOJOM_TEST_INTERFACE_REQUEST_MOJOM_TRAITS_H_
-#define FUCHSIA_MOJOM_TEST_INTERFACE_REQUEST_MOJOM_TRAITS_H_
+#ifndef MOJO_PUBLIC_CPP_BASE_FUCHSIA_TEST_INTERFACE_REQUEST_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_FUCHSIA_TEST_INTERFACE_REQUEST_MOJOM_TRAITS_H_
 
-#include "fuchsia/mojom/fidl_interface_request_mojom_traits.h"
+#include "mojo/public/cpp/base/fuchsia/fidl_interface_request_mojom_traits.h"
 
 namespace mojo {
 
@@ -18,4 +18,4 @@
 
 }  // namespace mojo
 
-#endif  // FUCHSIA_MOJOM_TEST_INTERFACE_REQUEST_MOJOM_TRAITS_H_
+#endif  // MOJO_PUBLIC_CPP_BASE_FUCHSIA_TEST_INTERFACE_REQUEST_MOJOM_TRAITS_H_
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index 28ff9365..9be7d47c 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -3876,51 +3876,49 @@
   EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, kOneMB));
 }
 
-// TODO(crbug.com/1317648): Revive this test.
-#if BUILDFLAG(IS_WIN)
-#define MAYBE_FileSharing DISABLED_FileSharing
-#else
-#define MAYBE_FileSharing FileSharing
-#endif
 // Tests that sharing of external files works and we are able to delete the
 // files when we need to.
-TEST_F(DiskCacheBackendTest, MAYBE_FileSharing) {
+TEST_F(DiskCacheBackendTest, FileSharing) {
   InitCache();
 
   disk_cache::Addr address(0x80000001);
   ASSERT_TRUE(cache_impl_->CreateExternalFile(&address));
   base::FilePath name = cache_impl_->GetFileName(address);
 
-  scoped_refptr<disk_cache::File> file(new disk_cache::File(false));
-  file->Init(name);
+  {
+    scoped_refptr<disk_cache::File> file(new disk_cache::File(false));
+    file->Init(name);
 
 #if BUILDFLAG(IS_WIN)
-  DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
-  DWORD access = GENERIC_READ | GENERIC_WRITE;
-  base::win::ScopedHandle file2(CreateFile(name.value().c_str(), access,
-                                           sharing, nullptr, OPEN_EXISTING, 0,
-                                           nullptr));
-  EXPECT_FALSE(file2.IsValid());
+    DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
+    DWORD access = GENERIC_READ | GENERIC_WRITE;
+    base::win::ScopedHandle file2(CreateFile(name.value().c_str(), access,
+                                             sharing, nullptr, OPEN_EXISTING, 0,
+                                             nullptr));
+    EXPECT_FALSE(file2.IsValid());
 
-  sharing |= FILE_SHARE_DELETE;
-  file2.Set(CreateFile(name.value().c_str(), access, sharing, nullptr,
-                       OPEN_EXISTING, 0, nullptr));
-  EXPECT_TRUE(file2.IsValid());
+    sharing |= FILE_SHARE_DELETE;
+    file2.Set(CreateFile(name.value().c_str(), access, sharing, nullptr,
+                         OPEN_EXISTING, 0, nullptr));
+    EXPECT_TRUE(file2.IsValid());
 #endif
 
-  EXPECT_TRUE(base::DeleteFile(name));
+    EXPECT_TRUE(base::DeleteFile(name));
 
-  // We should be able to use the file.
-  const int kSize = 200;
-  char buffer1[kSize];
-  char buffer2[kSize];
-  memset(buffer1, 't', kSize);
-  memset(buffer2, 0, kSize);
-  EXPECT_TRUE(file->Write(buffer1, kSize, 0));
-  EXPECT_TRUE(file->Read(buffer2, kSize, 0));
-  EXPECT_EQ(0, memcmp(buffer1, buffer2, kSize));
+    // We should be able to use the file.
+    const int kSize = 200;
+    char buffer1[kSize];
+    char buffer2[kSize];
+    memset(buffer1, 't', kSize);
+    memset(buffer2, 0, kSize);
+    EXPECT_TRUE(file->Write(buffer1, kSize, 0));
+    EXPECT_TRUE(file->Read(buffer2, kSize, 0));
+    EXPECT_EQ(0, memcmp(buffer1, buffer2, kSize));
+  }
 
-  EXPECT_TRUE(base::DeleteFile(name));
+  base::File file(name, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  EXPECT_FALSE(file.IsValid());
+  EXPECT_EQ(file.error_details(), base::File::FILE_ERROR_NOT_FOUND);
 }
 
 TEST_F(DiskCacheBackendTest, UpdateRankForExternalCacheHit) {
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc
index c5e6a6b..20908bdf 100644
--- a/services/network/cors/cors_url_loader_unittest.cc
+++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -909,6 +909,55 @@
   EXPECT_EQ(net::OK, client().completion_status().error_code);
 }
 
+TEST_F(CorsURLLoaderTest, CrossOriginPreflightReceiveRedirect) {
+  const GURL origin("https://example.com");
+  const GURL url("https://other.example.com/foo.png");
+  const GURL new_url("https://other2.example.com/bar.png");
+
+  ResourceRequest original_request;
+  original_request.mode = mojom::RequestMode::kCors;
+  original_request.credentials_mode = mojom::CredentialsMode::kOmit;
+  original_request.method = "GET";
+  original_request.headers.SetHeader("Content-type", "application/json");
+  original_request.url = url;
+  original_request.request_initiator = url::Origin::Create(origin);
+  CreateLoaderAndStart(original_request);
+  RunUntilCreateLoaderAndStartCalled();
+
+  // preflight request
+  EXPECT_EQ(1, num_created_loaders());
+  EXPECT_EQ(GetRequest().url, url);
+  EXPECT_EQ(GetRequest().method, "OPTIONS");
+
+  NotifyLoaderClientOnReceiveRedirect(
+      CreateRedirectInfo(301, "OPTIONS", new_url),
+      {{"Access-Control-Allow-Origin", "https://example.com"},
+       {"Access-Control-Allow-Headers", "Content-type"}});
+
+  RunUntilComplete();
+  EXPECT_FALSE(client().has_received_redirect());
+  EXPECT_TRUE(client().has_received_completion());
+  EXPECT_FALSE(client().has_received_response());
+  EXPECT_EQ(net::ERR_FAILED, client().completion_status().error_code);
+
+  std::vector<net::NetLogEntry> entries = GetEntries();
+  std::vector<net::NetLogEventType> types = GetTypesOfNetLogEntries(entries);
+  EXPECT_THAT(types,
+              Contains(net::NetLogEventType::CORS_PREFLIGHT_RESULT).Times(0));
+  ASSERT_THAT(types,
+              Contains(net::NetLogEventType::CORS_PREFLIGHT_ERROR).Times(1));
+
+  const net::NetLogEntry* entry =
+      FindEntryByType(entries, net::NetLogEventType::CORS_PREFLIGHT_ERROR);
+  const base::Value::Dict* params = entry->params.GetIfDict();
+  ASSERT_TRUE(params);
+  EXPECT_THAT(params->FindString("error"), Pointee(Eq("ERR_FAILED")));
+  EXPECT_THAT(params->FindInt("cors-error"),
+              Optional(Eq(static_cast<int>(
+                  mojom::CorsError::kPreflightDisallowedRedirect))));
+  EXPECT_THAT(params->FindString("failed-parameter"), IsNull());
+}
+
 TEST_F(CorsURLLoaderTest, RedirectInfoShouldBeUsed) {
   const GURL origin("https://example.com");
   const GURL url("https://example.com/foo.png");
diff --git a/storage/BUILD.gn b/storage/BUILD.gn
index 05211769..2378954 100644
--- a/storage/BUILD.gn
+++ b/storage/BUILD.gn
@@ -10,6 +10,4 @@
   ]
 
   data = [ "//storage/test/data/" ]
-
-  data_deps = [ "//testing/buildbot/filters:storage_unittests_filters" ]
 }
diff --git a/storage/browser/file_system/dragged_file_util_unittest.cc b/storage/browser/file_system/dragged_file_util_unittest.cc
index ee4b3a6f..e1020fed 100644
--- a/storage/browser/file_system/dragged_file_util_unittest.cc
+++ b/storage/browser/file_system/dragged_file_util_unittest.cc
@@ -476,6 +476,12 @@
   }
 }
 
+// TODO(https://crbug.com/702990): Remove this test once last_access_time has
+// been removed after PPAPI has been deprecated. Fuchsia does not support touch,
+// which breaks this test that relies on it. Since PPAPI is being deprecated,
+// this test is excluded from the Fuchsia build.
+// See https://crbug.com/1077456 for details.
+#if !BUILDFLAG(IS_FUCHSIA)
 TEST_F(DraggedFileUtilTest, TouchTest) {
   for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
     const FileSystemTestCaseRecord& test_case = kRegularFileSystemTestCases[i];
@@ -501,6 +507,7 @@
     EXPECT_EQ(last_modified_time.ToTimeT(), info.last_modified.ToTimeT());
   }
 }
+#endif  // !BUILDFLAG(IS_FUCHSIA)
 
 TEST_F(DraggedFileUtilTest, TruncateTest) {
   for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
diff --git a/storage/browser/file_system/file_system_operation_impl_unittest.cc b/storage/browser/file_system/file_system_operation_impl_unittest.cc
index ad8abd5..b59b8511 100644
--- a/storage/browser/file_system/file_system_operation_impl_unittest.cc
+++ b/storage/browser/file_system/file_system_operation_impl_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "components/services/filesystem/public/mojom/types.mojom.h"
 #include "storage/browser/blob/shareable_file_reference.h"
 #include "storage/browser/file_system/copy_or_move_hook_delegate.h"
@@ -1140,6 +1141,12 @@
   EXPECT_EQ(10, GetFileSize("dir/file"));
 }
 
+// TODO(https://crbug.com/702990): Remove this test once last_access_time has
+// been removed after PPAPI has been deprecated. Fuchsia does not support touch,
+// which breaks this test that relies on it. Since PPAPI is being deprecated,
+// this test is excluded from the Fuchsia build.
+// See https://crbug.com/1077456 for details.
+#if !BUILDFLAG(IS_FUCHSIA)
 TEST_F(FileSystemOperationImplTest, TestTouchFile) {
   FileSystemURL file(CreateFile("file"));
   base::FilePath platform_path = PlatformPath("file");
@@ -1167,6 +1174,7 @@
   EXPECT_EQ(new_modified_time.ToTimeT(), info.last_modified.ToTimeT());
   EXPECT_EQ(new_accessed_time.ToTimeT(), info.last_accessed.ToTimeT());
 }
+#endif  // !BUILDFLAG(IS_FUCHSIA)
 
 TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) {
   FileSystemURL dir(CreateDirectory("dir"));
diff --git a/storage/browser/file_system/local_file_util_unittest.cc b/storage/browser/file_system/local_file_util_unittest.cc
index 90f9106..d7a6b93 100644
--- a/storage/browser/file_system/local_file_util_unittest.cc
+++ b/storage/browser/file_system/local_file_util_unittest.cc
@@ -174,6 +174,12 @@
   EXPECT_FALSE(created);
 }
 
+// TODO(https://crbug.com/702990): Remove this test once last_access_time has
+// been removed after PPAPI has been deprecated. Fuchsia does not support touch,
+// which breaks this test that relies on it. Since PPAPI is being deprecated,
+// this test is excluded from the Fuchsia build.
+// See https://crbug.com/1077456 for details.
+#if !BUILDFLAG(IS_FUCHSIA)
 TEST_F(LocalFileUtilTest, TouchFile) {
   const char* file_name = "test_file";
   base::File file = CreateFile(file_name);
@@ -217,6 +223,7 @@
   EXPECT_EQ(new_accessed, info.last_accessed);
   EXPECT_EQ(new_modified, info.last_modified);
 }
+#endif  // !BUILDFLAG(IS_FUCHSIA)
 
 TEST_F(LocalFileUtilTest, Truncate) {
   const char* file_name = "truncated";
diff --git a/storage/browser/file_system/native_file_util_unittest.cc b/storage/browser/file_system/native_file_util_unittest.cc
index 4038989..db395ab16 100644
--- a/storage/browser/file_system/native_file_util_unittest.cc
+++ b/storage/browser/file_system/native_file_util_unittest.cc
@@ -137,6 +137,12 @@
   EXPECT_FALSE(NativeFileUtil::DirectoryExists(dir_name));
 }
 
+// TODO(https://crbug.com/702990): Remove this test once last_access_time has
+// been removed after PPAPI has been deprecated. Fuchsia does not support touch,
+// which breaks this test that relies on it. Since PPAPI is being deprecated,
+// this test is excluded from the Fuchsia build.
+// See https://crbug.com/1077456 for details.
+#if !BUILDFLAG(IS_FUCHSIA)
 TEST_F(NativeFileUtilTest, TouchFileAndGetFileInfo) {
   base::FilePath file_name = Path("test_file");
   base::File::Info native_info;
@@ -169,6 +175,7 @@
   EXPECT_EQ(new_accessed, info.last_accessed);
   EXPECT_EQ(new_modified, info.last_modified);
 }
+#endif  // !BUILDFLAG(IS_FUCHSIA)
 
 TEST_F(NativeFileUtilTest, CreateFileEnumerator) {
   base::FilePath path_1 = Path("dir1");
diff --git a/storage/browser/file_system/obfuscated_file_util_unittest.cc b/storage/browser/file_system/obfuscated_file_util_unittest.cc
index 49f700b..19210c8 100644
--- a/storage/browser/file_system/obfuscated_file_util_unittest.cc
+++ b/storage/browser/file_system/obfuscated_file_util_unittest.cc
@@ -1233,6 +1233,12 @@
   EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
 }
 
+// TODO(https://crbug.com/702990): Remove this test once last_access_time has
+// been removed after PPAPI has been deprecated. Fuchsia does not support touch,
+// which breaks this test that relies on it. Since PPAPI is being deprecated,
+// this test is excluded from the Fuchsia build.
+// See https://crbug.com/1077456 for details.
+#if !BUILDFLAG(IS_FUCHSIA)
 TEST_P(ObfuscatedFileUtilTest, TestTouch) {
   FileSystemURL url = CreateURLFromUTF8("file");
   std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
@@ -1262,6 +1268,7 @@
             ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
   TestTouchHelper(url, false);
 }
+#endif  // !BUILDFLAG(IS_FUCHSIA)
 
 TEST_P(ObfuscatedFileUtilTest, TestPathQuotas) {
   FileSystemURL url = CreateURLFromUTF8("fake/file");
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index e60476a..e290f26 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -3594,7 +3594,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter",
           "--lacros-chrome-path=lacros_clang_x64"
         ],
-        "experiment_percentage": 10,
+        "ci_only": true,
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -5890,21 +5890,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5045.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "dimension_sets": [
@@ -5916,7 +5916,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       },
       {
         "args": [
@@ -6036,21 +6036,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5045.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "dimension_sets": [
@@ -6062,7 +6062,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 655e41d..3ad6a7d 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -9199,7 +9199,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "merge": {
@@ -9680,9 +9680,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -10669,7 +10666,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "merge": {
@@ -11119,9 +11116,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.fuchsia.fyi.json b/testing/buildbot/chromium.fuchsia.fyi.json
index 137fde9..c9df3fb 100644
--- a/testing/buildbot/chromium.fuchsia.fyi.json
+++ b/testing/buildbot/chromium.fuchsia.fyi.json
@@ -448,7 +448,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "merge": {
@@ -904,9 +904,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -1649,7 +1646,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "merge": {
@@ -2142,9 +2139,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -2933,7 +2927,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "merge": {
@@ -3414,9 +3408,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index e90cd9f..952abe55 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -22753,7 +22753,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "args": [
@@ -23365,7 +23365,6 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter",
           "--ram-size-mb=16384",
           "--code-coverage",
           "--code-coverage-dir=${ISOLATED_OUTDIR}"
@@ -24271,7 +24270,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "merge": {
@@ -24804,9 +24803,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25898,7 +25894,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "args": [
@@ -26412,7 +26408,6 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter",
           "--gtest_also_run_disabled_tests",
           "--gtest_filter=*DISABLE*"
         ],
@@ -87869,28 +87864,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5045.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       },
       {
         "args": [
@@ -87990,28 +87985,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5045.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       },
       {
         "isolate_profile_data": true,
@@ -89386,20 +89381,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5045.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "dimension_sets": [
@@ -89412,7 +89407,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       },
       {
         "args": [
@@ -89532,20 +89527,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5045.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "dimension_sets": [
@@ -89558,7 +89553,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       },
       {
         "merge": {
@@ -91091,20 +91086,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5045.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "dimension_sets": [
@@ -91117,7 +91112,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       },
       {
         "args": [
@@ -91237,20 +91232,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5045.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "dimension_sets": [
@@ -91263,7 +91258,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       },
       {
         "merge": {
@@ -91998,20 +91993,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5045.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5046.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5045.0",
-              "revision": "version:103.0.5045.0"
+              "location": "lacros_version_skew_tests_v103.0.5046.0",
+              "revision": "version:103.0.5046.0"
             }
           ],
           "dimension_sets": [
@@ -92024,7 +92019,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5045.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5046.0"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 952a8e3..2987ec2 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -2287,7 +2287,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "merge": {
@@ -2737,9 +2737,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -3499,7 +3496,7 @@
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "fuchsia_mojo_unittests",
-        "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/"
+        "test_id_prefix": "ninja://mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests/"
       },
       {
         "merge": {
@@ -3980,9 +3977,6 @@
         "test_id_prefix": "ninja://sql:sql_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index d54233b..cb4e5b1 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -213,12 +213,6 @@
   data = [ "//testing/buildbot/filters/fuchsia.services_unittests.filter" ]
 }
 
-source_set("storage_unittests_filters") {
-  testonly = true
-
-  data = [ "//testing/buildbot/filters/fuchsia.storage_unittests.filter" ]
-}
-
 source_set("ui_base_unittests_filters") {
   testonly = true
 
diff --git a/testing/buildbot/filters/fuchsia.storage_unittests.filter b/testing/buildbot/filters/fuchsia.storage_unittests.filter
deleted file mode 100644
index e7798fa..0000000
--- a/testing/buildbot/filters/fuchsia.storage_unittests.filter
+++ /dev/null
@@ -1,7 +0,0 @@
-# crbug.com/1077456
--All/ObfuscatedFileUtilTest.TestTouch/0
--DraggedFileUtilTest.TouchTest
--FileSystemOperationImplTest.TestTouchFile
--LocalFileUtilTest.TouchDirectory
--LocalFileUtilTest.TouchFile
--NativeFileUtilTest.TouchFileAndGetFileInfo
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index c486d65a..ec2c54e1 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -859,7 +859,7 @@
     "type": "script",
   },
   "fuchsia_mojo_unittests": {
-    "label": "//fuchsia/mojom:fuchsia_mojo_unittests",
+    "label": "//mojo/public/cpp/base/fuchsia:fuchsia_mojo_unittests",
     "type": "console_test_launcher",
   },
   "fuchsia_sizes": {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 2473ff0..42f8f03 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -1845,11 +1845,7 @@
       'skia_unittests': {},
       'snapshot_unittests': {},
       'sql_unittests': {},
-      'storage_unittests': {
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter',
-        ],
-      },
+      'storage_unittests': {},
       'ui_base_unittests': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter',
@@ -4139,7 +4135,7 @@
         ],
         # TODO(crbug.com/1195974): Decides whether we want to run this on CQ.
         # This target is heavy, which currently takes ~1 hour to run.
-        'experiment_percentage': 10,
+        'ci_only': True,
         'test': 'browser_tests',
         'swarming': {
           'shards': 4,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 62f9c18..53e09f60 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5045.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5046.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 103.0.5045.0',
+    'identifier': 'Lacros version skew testing ash 103.0.5046.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v103.0.5045.0',
-          'revision': 'version:103.0.5045.0',
+          'location': 'lacros_version_skew_tests_v103.0.5046.0',
+          'revision': 'version:103.0.5046.0',
         },
       ],
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index e76e1d7a..7b3ec7e7 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -8730,6 +8730,24 @@
             ]
         }
     ],
+    "WebViewOriginTrials": [
+        {
+            "platforms": [
+                "android_webview"
+            ],
+            "experiments": [
+                {
+                    "name": "EnabledOnlyOriginTrials",
+                    "enable_features": [
+                        "WebViewOriginTrials"
+                    ],
+                    "disable_features": [
+                        "WebViewEmptyComponentLoaderPolicy"
+                    ]
+                }
+            ]
+        }
+    ],
     "WebViewTempTrustTokens": [
         {
             "platforms": [
diff --git a/third_party/android_deps/fetch_all.py b/third_party/android_deps/fetch_all.py
index c7d70162..891f168 100755
--- a/third_party/android_deps/fetch_all.py
+++ b/third_party/android_deps/fetch_all.py
@@ -27,6 +27,7 @@
 import re
 import shutil
 import subprocess
+import urllib.request
 import zipfile
 
 # Assume this script is stored under third_party/android_deps/
@@ -428,6 +429,21 @@
     print('\n'.join('    - ' + p for p in packages))
 
 
+def _DownloadOverrides(overrides, build_libs_dir):
+    for spec in overrides:
+        subpath, url = spec.split(':', 1)
+        target_path = os.path.join(build_libs_dir, subpath)
+        if not os.path.isfile(target_path):
+            found_files = 'Found instead:\n' + '\n'.join(
+                FindInDirectory(os.path.dirname(target_path), '*'))
+            raise Exception(
+                f'Override path does not exist: {target_path}\n{found_files}')
+        logging.info('Fetching override for %s', target_path)
+        with urllib.request.urlopen(url) as response:
+            with open(target_path, 'wb') as f:
+                shutil.copyfileobj(response, f)
+
+
 def _CreateAarInfos(aar_files):
     jobs = []
 
@@ -478,6 +494,9 @@
     parser.add_argument('--ignore-vulnerabilities',
                         help='Ignores vulnerabilities for these deps.',
                         action='store_true')
+    parser.add_argument('--override-artifact',
+                        action='append',
+                        help='lib_subpath:url of .aar / .jar to override.')
     parser.add_argument('-v',
                         '--verbose',
                         dest='verbose_count',
@@ -556,6 +575,8 @@
         RunCommand(gn_args, print_stdout=debug, cwd=_CHROMIUM_SRC)
 
         build_libs_dir = os.path.join(build_android_deps_dir, _LIBS_DIR)
+        if args.override_artifact:
+            _DownloadOverrides(args.override_artifact, build_libs_dir)
         aar_files = FindInDirectory(build_libs_dir, '*.aar')
 
         logging.info('# Generate Android .aar info files.')
diff --git a/third_party/androidx/fetch_all_androidx.py b/third_party/androidx/fetch_all_androidx.py
index 20dd629a4..57f8172 100755
--- a/third_party/androidx/fetch_all_androidx.py
+++ b/third_party/androidx/fetch_all_androidx.py
@@ -37,6 +37,15 @@
 # Snapshot repository URL with {{version}} placeholder.
 _SNAPSHOT_REPOSITORY_URL = 'https://androidx.dev/snapshots/builds/{{version}}/artifacts/repository'
 
+# When androidx roller is breaking, and a fix is not immenent, use this to pin a
+# broken library to an old known-working version.
+_OVERRIDES = [
+    # Example (find URL by looking in BUILD_INFO):
+    #('androidx_core_core/core-1.9.0-SNAPSHOT.aar',
+    # 'https://androidx.dev/snapshots/builds/8545498/artifacts/repository/'
+    # 'androidx/core/core/1.8.0-SNAPSHOT/core-1.8.0-20220505.122105-1.aar'),
+]
+
 
 def _build_snapshot_repository_url(version):
     return _SNAPSHOT_REPOSITORY_URL.replace('{{version}}', version)
@@ -258,6 +267,8 @@
         _FETCH_ALL_PATH, '--android-deps-dir', _ANDROIDX_PATH,
         '--ignore-vulnerabilities'
     ]
+    for subpath, url in _OVERRIDES:
+        fetch_all_cmd += ['--override-artifact', f'{subpath}:{url}']
     subprocess.run(fetch_all_cmd, check=True)
 
     if not args.local_repo:
diff --git a/third_party/blink/common/loader/mime_sniffing_throttle.cc b/third_party/blink/common/loader/mime_sniffing_throttle.cc
index 8dd2472..54e225e 100644
--- a/third_party/blink/common/loader/mime_sniffing_throttle.cc
+++ b/third_party/blink/common/loader/mime_sniffing_throttle.cc
@@ -75,8 +75,10 @@
 }
 
 void MimeSniffingThrottle::ResumeWithNewResponseHead(
-    network::mojom::URLResponseHeadPtr new_response_head) {
-  delegate_->UpdateDeferredResponseHead(std::move(new_response_head));
+    network::mojom::URLResponseHeadPtr new_response_head,
+    mojo::ScopedDataPipeConsumerHandle body) {
+  delegate_->UpdateDeferredResponseHead(std::move(new_response_head),
+                                        std::move(body));
   delegate_->Resume();
 }
 
diff --git a/third_party/blink/common/loader/mime_sniffing_throttle_unittest.cc b/third_party/blink/common/loader/mime_sniffing_throttle_unittest.cc
index c4eded8..764442f7 100644
--- a/third_party/blink/common/loader/mime_sniffing_throttle_unittest.cc
+++ b/third_party/blink/common/loader/mime_sniffing_throttle_unittest.cc
@@ -88,14 +88,15 @@
     is_resumed_ = true;
     // Resume from OnReceiveResponse() with a customized response header.
     destination_loader_client()->OnReceiveResponse(
-        std::move(updated_response_head_),
-        mojo::ScopedDataPipeConsumerHandle());
+        std::move(updated_response_head_), std::move(body_));
   }
 
   void SetPriority(net::RequestPriority priority) override { NOTIMPLEMENTED(); }
   void UpdateDeferredResponseHead(
-      network::mojom::URLResponseHeadPtr new_response_head) override {
+      network::mojom::URLResponseHeadPtr new_response_head,
+      mojo::ScopedDataPipeConsumerHandle body) override {
     updated_response_head_ = std::move(new_response_head);
+    body_ = std::move(body);
   }
   void PauseReadingBodyFromNet() override { NOTIMPLEMENTED(); }
   void ResumeReadingBodyFromNet() override { NOTIMPLEMENTED(); }
@@ -177,6 +178,7 @@
   bool is_intercepted_ = false;
   bool is_resumed_ = false;
   network::mojom::URLResponseHeadPtr updated_response_head_;
+  mojo::ScopedDataPipeConsumerHandle body_;
 
   // A pair of a loader and a loader client for destination of the response.
   mojo::Remote<network::mojom::URLLoader> destination_loader_remote_;
diff --git a/third_party/blink/common/loader/mime_sniffing_url_loader.cc b/third_party/blink/common/loader/mime_sniffing_url_loader.cc
index 3cbf9362f..d3b31f9 100644
--- a/third_party/blink/common/loader/mime_sniffing_url_loader.cc
+++ b/third_party/blink/common/loader/mime_sniffing_url_loader.cc
@@ -142,7 +142,8 @@
         Abort();
         return;
       }
-      throttle_->ResumeWithNewResponseHead(std::move(response_head_));
+      throttle_->ResumeWithNewResponseHead(
+          std::move(response_head_), mojo::ScopedDataPipeConsumerHandle());
       destination_url_loader_client_->OnComplete(status);
       return;
     case State::kSniffing:
@@ -260,7 +261,6 @@
     Abort();
     return;
   }
-  throttle_->ResumeWithNewResponseHead(std::move(response_head_));
   mojo::ScopedDataPipeConsumerHandle body_to_send;
   MojoResult result =
       mojo::CreateDataPipe(nullptr, body_producer_handle_, body_to_send);
@@ -268,6 +268,8 @@
     Abort();
     return;
   }
+  throttle_->ResumeWithNewResponseHead(std::move(response_head_),
+                                       std::move(body_to_send));
   // Set up the watcher for the producer handle.
   body_producer_watcher_.Watch(
       body_producer_handle_.get(),
@@ -275,10 +277,6 @@
       base::BindRepeating(&MimeSniffingURLLoader::OnBodyWritable,
                           base::Unretained(this)));
 
-  // Send deferred message.
-  destination_url_loader_client_->OnStartLoadingResponseBody(
-      std::move(body_to_send));
-
   if (bytes_remaining_in_buffer_) {
     SendReceivedBodyToClient();
     return;
diff --git a/third_party/blink/common/loader/throttling_url_loader.cc b/third_party/blink/common/loader/throttling_url_loader.cc
index 9df138f..14877e4 100644
--- a/third_party/blink/common/loader/throttling_url_loader.cc
+++ b/third_party/blink/common/loader/throttling_url_loader.cc
@@ -152,11 +152,13 @@
   }
 
   void UpdateDeferredResponseHead(
-      network::mojom::URLResponseHeadPtr new_response_head) override {
+      network::mojom::URLResponseHeadPtr new_response_head,
+      mojo::ScopedDataPipeConsumerHandle body) override {
     if (!loader_)
       return;
     ScopedDelegateCall scoped_delegate_call(this);
-    loader_->UpdateDeferredResponseHead(std::move(new_response_head));
+    loader_->UpdateDeferredResponseHead(std::move(new_response_head),
+                                        std::move(body));
   }
 
   void PauseReadingBodyFromNet() override {
@@ -1002,10 +1004,13 @@
 }
 
 void ThrottlingURLLoader::UpdateDeferredResponseHead(
-    network::mojom::URLResponseHeadPtr new_response_head) {
+    network::mojom::URLResponseHeadPtr new_response_head,
+    mojo::ScopedDataPipeConsumerHandle body) {
   DCHECK(response_info_);
+  DCHECK(!body_);
   DCHECK_EQ(DEFERRED_RESPONSE, deferred_stage_);
   response_info_->response_head = std::move(new_response_head);
+  body_ = std::move(body);
 }
 
 void ThrottlingURLLoader::PauseReadingBodyFromNet(URLLoaderThrottle* throttle) {
diff --git a/third_party/blink/common/loader/url_loader_throttle.cc b/third_party/blink/common/loader/url_loader_throttle.cc
index 40275e66..037dee41 100644
--- a/third_party/blink/common/loader/url_loader_throttle.cc
+++ b/third_party/blink/common/loader/url_loader_throttle.cc
@@ -15,7 +15,8 @@
     const net::HttpRequestHeaders& modified_request_headers,
     const net::HttpRequestHeaders& modified_cors_exempt_request_headers) {}
 void URLLoaderThrottle::Delegate::UpdateDeferredResponseHead(
-    network::mojom::URLResponseHeadPtr new_response_head) {}
+    network::mojom::URLResponseHeadPtr new_response_head,
+    mojo::ScopedDataPipeConsumerHandle body) {}
 void URLLoaderThrottle::Delegate::PauseReadingBodyFromNet() {}
 void URLLoaderThrottle::Delegate::ResumeReadingBodyFromNet() {}
 
diff --git a/third_party/blink/public/common/loader/mime_sniffing_throttle.h b/third_party/blink/public/common/loader/mime_sniffing_throttle.h
index cee4924..0f595452 100644
--- a/third_party/blink/public/common/loader/mime_sniffing_throttle.h
+++ b/third_party/blink/public/common/loader/mime_sniffing_throttle.h
@@ -32,7 +32,8 @@
 
   // Called from MimeSniffingURLLoader once mime type is ready.
   void ResumeWithNewResponseHead(
-      network::mojom::URLResponseHeadPtr new_response_head);
+      network::mojom::URLResponseHeadPtr new_response_head,
+      mojo::ScopedDataPipeConsumerHandle body);
 
  private:
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/third_party/blink/public/common/loader/throttling_url_loader.h b/third_party/blink/public/common/loader/throttling_url_loader.h
index 0439eba5..04ddf6e 100644
--- a/third_party/blink/public/common/loader/throttling_url_loader.h
+++ b/third_party/blink/public/common/loader/throttling_url_loader.h
@@ -182,7 +182,8 @@
       const net::HttpRequestHeaders& modified_cors_exempt_request_headers);
   void UpdateRequestHeaders(network::ResourceRequest& resource_request);
   void UpdateDeferredResponseHead(
-      network::mojom::URLResponseHeadPtr new_response_head);
+      network::mojom::URLResponseHeadPtr new_response_head,
+      mojo::ScopedDataPipeConsumerHandle body);
   void PauseReadingBodyFromNet(URLLoaderThrottle* throttle);
   void ResumeReadingBodyFromNet(URLLoaderThrottle* throttle);
   void InterceptResponse(
diff --git a/third_party/blink/public/common/loader/url_loader_throttle.h b/third_party/blink/public/common/loader/url_loader_throttle.h
index dd247817..539a046 100644
--- a/third_party/blink/public/common/loader/url_loader_throttle.h
+++ b/third_party/blink/public/common/loader/url_loader_throttle.h
@@ -75,7 +75,8 @@
     // URLLoaderThrottle::WillProcessResponse() and before calling
     // Delegate::Resume().
     virtual void UpdateDeferredResponseHead(
-        network::mojom::URLResponseHeadPtr new_response_head);
+        network::mojom::URLResponseHeadPtr new_response_head,
+        mojo::ScopedDataPipeConsumerHandle body);
 
     // Pauses/resumes reading response body if the resource is fetched from
     // network.
diff --git a/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom b/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
index aa45472..2fe08946 100644
--- a/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
+++ b/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
@@ -25,6 +25,18 @@
   kShown,   // Window is placed on a screen.
 };
 
+// CrosWindowManagement methods return status in callback corresponding to
+// state of method call.
+enum CrosWindowManagementStatus {
+  kSuccess,             // Function call executed successfully.
+  kWindowNotFound,      // No window was found with the specified id.
+  kWindowNoWindowState, // Failed to acquire window state for
+                        // maximizing/minimizing. Either no window exists with
+                        // the specified id, or window is not a top level
+                        // window.
+  kWindowNoWidget,      // No widget could be found on window with specified id.
+};
+
 // Represents a Chrome OS window which can be manipulated by a Window Management
 // System Extension.
 struct CrosWindowInfo {
@@ -50,19 +62,19 @@
 
   // Sets the bounds of a CrosWindow where |hash| is used as the window
   // identifier.
-  SetWindowBounds(mojo_base.mojom.UnguessableToken id, int32 x, int32 y, int32 width, int32 height);
+  SetWindowBounds(mojo_base.mojom.UnguessableToken id, int32 x, int32 y, int32 width, int32 height) => (CrosWindowManagementStatus value);
 
   // Enable/disable fullscreen for window identified by id if one exists, else do nothing.
-  SetFullscreen(mojo_base.mojom.UnguessableToken id, bool fullscreen);
+  SetFullscreen(mojo_base.mojom.UnguessableToken id, bool fullscreen) => (CrosWindowManagementStatus value);
 
   // Maximizes the window identified by id if one exists, else do nothing.
-  Maximize(mojo_base.mojom.UnguessableToken id);
+  Maximize(mojo_base.mojom.UnguessableToken id) => (CrosWindowManagementStatus value);
 
   // Minimizes the window identified by id if one exists, else do nothing.
-  Minimize(mojo_base.mojom.UnguessableToken id);
+  Minimize(mojo_base.mojom.UnguessableToken id) => (CrosWindowManagementStatus value);
 
   // Allocates focus to the CrosWindow identified by id and brings to front.
-  Focus(mojo_base.mojom.UnguessableToken id);
+  Focus(mojo_base.mojom.UnguessableToken id) => (CrosWindowManagementStatus value);
 
   // Closes the window identified by id if it exists, else do nothing.
   Close(mojo_base.mojom.UnguessableToken id);
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index ade27fb..49756ebe 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3541,6 +3541,7 @@
   kGestureScrollStart = 4220,
   kGestureScrollUpdate = 4221,
   kGestureScrollEnd = 4222,
+  kArrayBufferTooBigForWebAPI = 4223,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc b/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
index 22fda19..e300ef1 100644
--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
+++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
@@ -3,8 +3,9 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
-
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h"
 
 namespace blink {
@@ -214,8 +215,18 @@
     v8::Local<v8::Value> value,
     ExceptionState& exception_state) {
   DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
-  if (LIKELY(array_buffer))
+  if (LIKELY(array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return array_buffer;
+  }
 
   exception_state.ThrowTypeError(
       ExceptionMessages::FailedToConvertJSValue("ArrayBuffer"));
@@ -228,8 +239,18 @@
     v8::Local<v8::Value> value,
     ExceptionState& exception_state) {
   DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
-  if (LIKELY(array_buffer))
+  if (LIKELY(array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return array_buffer;
+  }
 
   exception_state.ThrowTypeError(
       ExceptionMessages::ArgumentNotOfType(argument_index, "ArrayBuffer"));
@@ -243,8 +264,18 @@
     v8::Local<v8::Value> value,
     ExceptionState& exception_state) {
   DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
-  if (LIKELY(array_buffer))
+  if (LIKELY(array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return array_buffer;
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return nullptr;
@@ -260,8 +291,18 @@
     v8::Local<v8::Value> value,
     ExceptionState& exception_state) {
   DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
-  if (LIKELY(array_buffer))
+  if (LIKELY(array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return array_buffer;
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return nullptr;
@@ -279,8 +320,18 @@
     ExceptionState& exception_state) {
   DOMSharedArrayBuffer* shared_array_buffer =
       ToDOMSharedArrayBuffer(isolate, value);
-  if (LIKELY(shared_array_buffer))
+  if (LIKELY(shared_array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(shared_array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The SharedArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return shared_array_buffer;
+  }
 
   exception_state.ThrowTypeError(
       ExceptionMessages::FailedToConvertJSValue("SharedArrayBuffer"));
@@ -294,8 +345,18 @@
     ExceptionState& exception_state) {
   DOMSharedArrayBuffer* shared_array_buffer =
       ToDOMSharedArrayBuffer(isolate, value);
-  if (LIKELY(shared_array_buffer))
+  if (LIKELY(shared_array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(shared_array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The SharedArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return shared_array_buffer;
+  }
 
   exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
       argument_index, "SharedArrayBuffer"));
@@ -311,8 +372,18 @@
     ExceptionState& exception_state) {
   DOMSharedArrayBuffer* shared_array_buffer =
       ToDOMSharedArrayBuffer(isolate, value);
-  if (LIKELY(shared_array_buffer))
+  if (LIKELY(shared_array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(shared_array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The SharedArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return shared_array_buffer;
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return nullptr;
@@ -330,8 +401,18 @@
     ExceptionState& exception_state) {
   DOMSharedArrayBuffer* shared_array_buffer =
       ToDOMSharedArrayBuffer(isolate, value);
-  if (LIKELY(shared_array_buffer))
+  if (LIKELY(shared_array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(shared_array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The SharedArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return shared_array_buffer;
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return nullptr;
@@ -348,13 +429,33 @@
     v8::Local<v8::Value> value,
     ExceptionState& exception_state) {
   DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
-  if (LIKELY(array_buffer))
+  if (LIKELY(array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return array_buffer;
+  }
 
   DOMSharedArrayBuffer* shared_array_buffer =
       ToDOMSharedArrayBuffer(isolate, value);
-  if (LIKELY(shared_array_buffer))
+  if (LIKELY(shared_array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(shared_array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The SharedArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return shared_array_buffer;
+  }
 
   exception_state.ThrowTypeError(
       ExceptionMessages::FailedToConvertJSValue("[AllowShared] ArrayBuffer"));
@@ -367,13 +468,33 @@
     v8::Local<v8::Value> value,
     ExceptionState& exception_state) {
   DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
-  if (LIKELY(array_buffer))
+  if (LIKELY(array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return array_buffer;
+  }
 
   DOMSharedArrayBuffer* shared_array_buffer =
       ToDOMSharedArrayBuffer(isolate, value);
-  if (LIKELY(shared_array_buffer))
+  if (LIKELY(shared_array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(shared_array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The SharedArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return shared_array_buffer;
+  }
 
   exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
       argument_index, "[AllowShared] ArrayBuffer"));
@@ -388,13 +509,33 @@
     v8::Local<v8::Value> value,
     ExceptionState& exception_state) {
   DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
-  if (LIKELY(array_buffer))
+  if (LIKELY(array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return array_buffer;
+  }
 
   DOMSharedArrayBuffer* shared_array_buffer =
       ToDOMSharedArrayBuffer(isolate, value);
-  if (LIKELY(shared_array_buffer))
+  if (LIKELY(shared_array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(shared_array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The SharedArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return shared_array_buffer;
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return nullptr;
@@ -411,13 +552,33 @@
     v8::Local<v8::Value> value,
     ExceptionState& exception_state) {
   DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value);
-  if (LIKELY(array_buffer))
+  if (LIKELY(array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return array_buffer;
+  }
 
   DOMSharedArrayBuffer* shared_array_buffer =
       ToDOMSharedArrayBuffer(isolate, value);
-  if (LIKELY(shared_array_buffer))
+  if (LIKELY(shared_array_buffer)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(shared_array_buffer->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The SharedArrayBuffer size exceeds the supported range");
+      return nullptr;
+    }
     return shared_array_buffer;
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return nullptr;
@@ -437,8 +598,18 @@
                 v8::Local<v8::Value> value,
                 ExceptionState& exception_state) {
   T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value);
-  if (LIKELY(blink_view))
+  if (LIKELY(blink_view)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(blink_view->byteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return NotShared<T>();
+    }
     return NotShared<T>(blink_view);
+  }
 
   if (ABVTrait<T>::IsShared(value)) {
     exception_state.ThrowTypeError(
@@ -461,8 +632,18 @@
                   v8::Local<v8::Value> value,
                   ExceptionState& exception_state) {
   T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value);
-  if (LIKELY(blink_view))
+  if (LIKELY(blink_view)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(blink_view->byteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return NotShared<T>();
+    }
     return NotShared<T>(blink_view);
+  }
 
   if (ABVTrait<T>::IsShared(value)) {
     exception_state.ThrowTypeError(
@@ -486,8 +667,18 @@
                 v8::Local<v8::Value> value,
                 ExceptionState& exception_state) {
   T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value);
-  if (LIKELY(blink_view))
+  if (LIKELY(blink_view)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(blink_view->byteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return MaybeShared<T>();
+    }
     return MaybeShared<T>(blink_view);
+  }
 
   exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue(
       T::GetStaticWrapperTypeInfo()->interface_name));
@@ -503,8 +694,18 @@
                   v8::Local<v8::Value> value,
                   ExceptionState& exception_state) {
   T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value);
-  if (LIKELY(blink_view))
+  if (LIKELY(blink_view)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(blink_view->byteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return MaybeShared<T>();
+    }
     return MaybeShared<T>(blink_view);
+  }
 
   exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
       argument_index, T::GetStaticWrapperTypeInfo()->interface_name));
@@ -521,8 +722,18 @@
                 v8::Local<v8::Value> value,
                 ExceptionState& exception_state) {
   T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value);
-  if (LIKELY(blink_view))
+  if (LIKELY(blink_view)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(blink_view->byteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return NotShared<T>();
+    }
     return NotShared<T>(blink_view);
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return NotShared<T>();
@@ -548,8 +759,18 @@
                   v8::Local<v8::Value> value,
                   ExceptionState& exception_state) {
   T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value);
-  if (LIKELY(blink_view))
+  if (LIKELY(blink_view)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(blink_view->byteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return NotShared<T>();
+    }
     return NotShared<T>(blink_view);
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return NotShared<T>();
@@ -576,8 +797,18 @@
                 v8::Local<v8::Value> value,
                 ExceptionState& exception_state) {
   T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value);
-  if (LIKELY(blink_view))
+  if (LIKELY(blink_view)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(blink_view->byteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return MaybeShared<T>();
+    }
     return MaybeShared<T>(blink_view);
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return MaybeShared<T>();
@@ -596,8 +827,18 @@
                   v8::Local<v8::Value> value,
                   ExceptionState& exception_state) {
   T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value);
-  if (LIKELY(blink_view))
+  if (LIKELY(blink_view)) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(blink_view->byteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return MaybeShared<T>();
+    }
     return MaybeShared<T>(blink_view);
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return MaybeShared<T>();
@@ -617,8 +858,18 @@
                   int argument_index,
                   v8::Local<v8::Value> value,
                   ExceptionState& exception_state) {
-  if (LIKELY(ABVTrait<T>::IsV8ViewType(value)))
+  if (LIKELY(ABVTrait<T>::IsV8ViewType(value))) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(value.As<typename ABVTrait<T>::V8ViewType>()->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return T();
+    }
     return T(value.As<typename ABVTrait<T>::V8ViewType>());
+  }
 
   exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType(
       argument_index,
@@ -636,8 +887,18 @@
                   int argument_index,
                   v8::Local<v8::Value> value,
                   ExceptionState& exception_state) {
-  if (LIKELY(ABVTrait<T>::IsV8ViewType(value)))
+  if (LIKELY(ABVTrait<T>::IsV8ViewType(value))) {
+    // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes.
+    if (UNLIKELY(value.As<typename ABVTrait<T>::V8ViewType>()->ByteLength() >
+                 ::partition_alloc::internal::MaxDirectMapped())) {
+      UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()),
+                        WebFeature::kArrayBufferTooBigForWebAPI);
+      exception_state.ThrowRangeError(
+          "The ArrayBufferView size exceeds the supported range");
+      return T();
+    }
     return T(value.As<typename ABVTrait<T>::V8ViewType>());
+  }
 
   if (LIKELY(value->IsNullOrUndefined()))
     return T();
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
index 025df20..3dc1a4bf 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
@@ -861,6 +861,36 @@
   }
   return v8::Nothing<bool>();
 }
+namespace {
+DOMSharedArrayBuffer* ToSharedArrayBuffer(v8::Isolate* isolate,
+                                          v8::Local<v8::Value> value,
+                                          ExceptionState& exception_state) {
+  if (UNLIKELY(!value->IsSharedArrayBuffer())) {
+    exception_state.ThrowTypeError(
+        ExceptionMessages::FailedToConvertJSValue("SharedArrayBuffer"));
+    return nullptr;
+  }
+
+  v8::Local<v8::SharedArrayBuffer> v8_shared_array_buffer =
+      value.As<v8::SharedArrayBuffer>();
+  if (DOMSharedArrayBuffer* shared_array_buffer =
+          ToScriptWrappable(v8_shared_array_buffer)
+              ->ToImpl<DOMSharedArrayBuffer>()) {
+    return shared_array_buffer;
+  }
+
+  // Transfer the ownership of the allocated memory to a DOMArrayBuffer without
+  // copying.
+  ArrayBufferContents contents(v8_shared_array_buffer->GetBackingStore());
+  DOMSharedArrayBuffer* shared_array_buffer =
+      DOMSharedArrayBuffer::Create(contents);
+  v8::Local<v8::Object> wrapper = shared_array_buffer->AssociateWithWrapper(
+      isolate, shared_array_buffer->GetWrapperTypeInfo(),
+      v8_shared_array_buffer);
+  DCHECK(wrapper == v8_shared_array_buffer);
+  return shared_array_buffer;
+}
+}  // namespace
 
 v8::Maybe<uint32_t> V8ScriptValueSerializer::GetSharedArrayBufferId(
     v8::Isolate* isolate,
@@ -877,9 +907,16 @@
     return v8::Nothing<uint32_t>();
   }
 
+  // The SharedArrayBuffer here may be a WebAssembly memory and can therefore be
+  // bigger than the 2GB limit of JavaScript SharedArrayBuffers that gets
+  // checked in NativeValueTraits<DOMSharedArrayBuffer>::NativeValue(). The
+  // code here can handle bigger SharedArrayBuffers, because the ByteLength
+  // field of the Shared ArrayBuffer does not get accessed. However, it is not
+  // possible to reuse NativeValueTraits<DOMSharedArrayBuffer>::NativeValue().
+  // TODO(1201109): Use NativeValueTraits<DOMSharedArrayBuffer>::NativeValue()
+  // again once the bounds check there got removed.
   DOMSharedArrayBuffer* shared_array_buffer =
-      NativeValueTraits<DOMSharedArrayBuffer>::NativeValue(
-          isolate, v8_shared_array_buffer, exception_state);
+      ToSharedArrayBuffer(isolate, v8_shared_array_buffer, exception_state);
   if (exception_state.HadException())
     return v8::Nothing<uint32_t>();
 
diff --git a/third_party/blink/renderer/core/css/force_dark_test.cc b/third_party/blink/renderer/core/css/force_dark_test.cc
index 86bf815..247080c1 100644
--- a/third_party/blink/renderer/core/css/force_dark_test.cc
+++ b/third_party/blink/renderer/core/css/force_dark_test.cc
@@ -7,14 +7,12 @@
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 
 namespace blink {
 
-class ForceDarkTest : public PageTestBase,
-                      public ScopedCSSColorSchemeOnlyForTest {
+class ForceDarkTest : public PageTestBase {
  protected:
-  ForceDarkTest() : ScopedCSSColorSchemeOnlyForTest(true) {}
+  ForceDarkTest() = default;
 
   void SetUp() override {
     PageTestBase::SetUp();
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index e159460..31fd8022 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -1619,9 +1619,7 @@
     CSSValue* value =
         css_parsing_utils::ConsumeIdent<CSSValueID::kDark, CSSValueID::kLight,
                                         CSSValueID::kOnly>(range);
-    if (id == CSSValueID::kOnly &&
-        RuntimeEnabledFeatures::CSSColorSchemeOnlyEnabled(
-            context.GetExecutionContext())) {
+    if (id == CSSValueID::kOnly) {
       if (only)
         return nullptr;
       if (values->length()) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
index 94a40140..c0e749b3 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -2360,10 +2360,7 @@
           flags |= static_cast<ColorSchemeFlags>(ColorSchemeFlag::kLight);
           break;
         case CSSValueID::kOnly:
-          if (RuntimeEnabledFeatures::CSSColorSchemeOnlyEnabled(
-                  document.GetExecutionContext())) {
-            flags |= static_cast<ColorSchemeFlags>(ColorSchemeFlag::kOnly);
-          }
+          flags |= static_cast<ColorSchemeFlags>(ColorSchemeFlag::kOnly);
           break;
         default:
           break;
diff --git a/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.cc b/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.cc
index c1f42c3..545070f7 100644
--- a/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.cc
+++ b/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.cc
@@ -19,9 +19,6 @@
     return;
   }
 
-  if (ShouldDismissOnScrollOrClick() && Dismiss())
-    FragmentDirectiveUtils::RemoveSelectorsFromUrl(frame_);
-
   user_scrolled_ = true;
 }
 
@@ -48,9 +45,4 @@
   return dismissed_ = true;
 }
 
-bool SelectorFragmentAnchor::ShouldDismissOnScrollOrClick() {
-  return !base::FeatureList::IsEnabled(
-      shared_highlighting::kSharedHighlightingV2);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h b/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h
index 2701993..6dd436a 100644
--- a/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h
+++ b/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h
@@ -28,8 +28,6 @@
 
   bool Dismiss() override;
 
-  static bool ShouldDismissOnScrollOrClick();
-
  protected:
   // This will be invoked by Invoke() when the page is visible until the
   // fragment has been dismissed. See FragmentAnchor::Invoke for details about
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_test.cc
index 5bbaca0..ff2f966 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_test.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_test.cc
@@ -1092,8 +1092,7 @@
   EXPECT_TRUE(GetDocument().View()->GetFragmentAnchor());
 }
 
-// Test that user scrolling doesn't dismiss the highlight, when the
-// SharedHighlightingV2 flag is enabled.
+// Test that user scrolling doesn't dismiss the highlight.
 TEST_P(TextFragmentAnchorScrollTest, DontDismissTextHighlightOnUserScroll) {
   SimRequest request(
       "https://example.com/"
@@ -1645,8 +1644,7 @@
       url.GetString());
 }
 
-// Test not dismissing the text highlight with a click, if the
-// SharedHighlightingV2 flag is enabled.
+// Test not dismissing the text highlight with a click.
 TEST_F(TextFragmentAnchorTest, DontDismissTextHighlightWithClick) {
   SimRequest request(
       "https://example.com/"
@@ -1749,8 +1747,7 @@
       url.GetString());
 }
 
-// Test not dismissing the text highlight with a tap, if the
-// SharedHighlightingV2 flag is enabled.
+// Test not dismissing the text highlight with a tap.
 TEST_F(TextFragmentAnchorTest, DontDismissTextHighlightWithTap) {
   SimRequest request(
       "https://example.com/"
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
index e5e7e449..0cfa0fc 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
@@ -96,9 +96,6 @@
 
 // TODO(http://crbug/1262141): look into using PageBroadcast Mojo.
 void TextFragmentHandler::RemoveFragments() {
-  DCHECK(
-      base::FeatureList::IsEnabled(shared_highlighting::kSharedHighlightingV2));
-
   if (GetTextFragmentAnchor()) {
     GetFrame()->View()->DismissFragmentAnchor();
   } else if (GetFrame()->IsOutermostMainFrame()) {
@@ -135,8 +132,6 @@
 
 void TextFragmentHandler::ExtractTextFragmentsMatches(
     ExtractTextFragmentsMatchesCallback callback) {
-  DCHECK(
-      base::FeatureList::IsEnabled(shared_highlighting::kSharedHighlightingV2));
   Vector<String> text_fragment_matches;
 
   TextFragmentAnchor* anchor = GetTextFragmentAnchor();
@@ -158,8 +153,6 @@
 
 void TextFragmentHandler::ExtractFirstFragmentRect(
     ExtractFirstFragmentRectCallback callback) {
-  DCHECK(
-      base::FeatureList::IsEnabled(shared_highlighting::kSharedHighlightingV2));
   gfx::Rect rect_in_viewport;
 
   TextFragmentAnchor* anchor = GetTextFragmentAnchor();
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler_test.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler_test.cc
index f2a98f3..1f2eb62 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler_test.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler_test.cc
@@ -38,9 +38,6 @@
   void SetUp() override {
     SimTest::SetUp();
     WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
-
-    feature_list_.InitWithFeatures({shared_highlighting::kSharedHighlightingV2},
-                                   {});
   }
 
   void BeginEmptyFrame() {
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc
index 3877be23..ab0a266 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.cc
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -685,9 +685,6 @@
 
   mouse_down_ = event.Event();
 
-  if (frame_->View() && SelectorFragmentAnchor::ShouldDismissOnScrollOrClick())
-    frame_->View()->DismissFragmentAnchor();
-
   if (frame_->GetDocument()->IsSVGDocument() &&
       frame_->GetDocument()->AccessSVGExtensions().ZoomAndPanEnabled()) {
     if ((event.Event().GetModifiers() & WebInputEvent::Modifiers::kShiftKey) &&
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 6dcb901..754c4c2 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -4140,6 +4140,10 @@
     // are removed or not is irrelevant.
     if (destroy_root_parent->IsLayoutFlowThread())
       break;
+    // The anonymous fieldset contents wrapper should be kept.
+    if (destroy_root_parent->Parent() &&
+        destroy_root_parent->Parent()->IsLayoutNGFieldset())
+      break;
 
     // We need to keep the anonymous parent, if it won't become empty by the
     // removal of this LayoutObject.
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
index 8e2e6be..d5195064 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
@@ -59,45 +59,42 @@
     return;
   }
   LayoutBlock* fieldset_content = FindAnonymousFieldsetContentBox();
-  if (!fieldset_content) {
-    // We wrap everything inside an anonymous child, which will take care of the
-    // fieldset contents. This parent will only be responsible for the fieldset
-    // border and the rendered legend, if there is one. Everything else will be
-    // done by the anonymous child. This includes display type, multicol,
-    // scrollbars, and even padding. Note that the rendered legend (if any) will
-    // also be a child of the anonymous object, although it'd be more natural to
-    // have it as the first child of this object. The reason is that our layout
-    // object tree builder cannot handle such discrepancies between DOM tree and
-    // layout tree. Inserting anonymous wrappers is one thing (that is
-    // supported). Removing it from its actual DOM siblings and putting it
-    // elsewhere, on the other hand, does not work well.
-
-    // TODO(crbug.com/875235): Consider other display types not mentioned in the
-    // spec (ex. EDisplay::kLayoutCustom).
-    EDisplay display = EDisplay::kFlowRoot;
-    switch (StyleRef().Display()) {
-      case EDisplay::kFlex:
-      case EDisplay::kInlineFlex:
-        display = EDisplay::kFlex;
-        break;
-      case EDisplay::kGrid:
-      case EDisplay::kInlineGrid:
-        display = EDisplay::kGrid;
-        break;
-      default:
-        break;
-    }
-
-    fieldset_content =
-        LayoutBlock::CreateAnonymousWithParentAndDisplay(this, display);
-    LayoutBox::AddChild(fieldset_content);
-  }
+  DCHECK(fieldset_content);
   fieldset_content->AddChild(new_child, before_child);
 }
 
-// TODO(mstensho): Should probably remove the anonymous child if it becomes
-// childless. While an empty anonymous child should have no effect, it doesn't
-// seem right to leave it around.
+void LayoutNGFieldset::InsertedIntoTree() {
+  LayoutNGBlockFlow::InsertedIntoTree();
+
+  if (FindAnonymousFieldsetContentBox())
+    return;
+
+  // We wrap everything inside an anonymous child, which will take care of the
+  // fieldset contents. This parent will only be responsible for the fieldset
+  // border and the rendered legend, if there is one. Everything else will be
+  // done by the anonymous child. This includes display type, multicol,
+  // scrollbars, and even padding.
+
+  // TODO(crbug.com/875235): Consider other display types not mentioned in the
+  // spec (ex. EDisplay::kLayoutCustom).
+  EDisplay display = EDisplay::kFlowRoot;
+  switch (StyleRef().Display()) {
+    case EDisplay::kFlex:
+    case EDisplay::kInlineFlex:
+      display = EDisplay::kFlex;
+      break;
+    case EDisplay::kGrid:
+    case EDisplay::kInlineGrid:
+      display = EDisplay::kGrid;
+      break;
+    default:
+      break;
+  }
+
+  LayoutBlock* fieldset_content =
+      LayoutBlock::CreateAnonymousWithParentAndDisplay(this, display);
+  LayoutBox::AddChild(fieldset_content);
+}
 
 void LayoutNGFieldset::UpdateAnonymousChildStyle(
     const LayoutObject*,
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h b/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h
index 34d9720..91f0632 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h
@@ -31,6 +31,7 @@
 
  protected:
   bool IsOfType(LayoutObjectType) const override;
+  void InsertedIntoTree() override;
   void UpdateAnonymousChildStyle(const LayoutObject* child,
                                  ComputedStyle& child_style) const override;
   void InvalidatePaint(const PaintInvalidatorContext& context) const final;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
index f6b4ca25..ab26378 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -225,8 +225,9 @@
 
   // Proceed with normal fieldset children (excluding the rendered legend). They
   // all live inside an anonymous child box of the fieldset container.
-  auto fieldset_content = Node().GetFieldsetContent();
-  if (fieldset_content && (content_break_token || !has_seen_all_children)) {
+  if (content_break_token || !has_seen_all_children) {
+    NGBlockNode fieldset_content = Node().GetFieldsetContent();
+    DCHECK(fieldset_content);
     NGBreakStatus break_status =
         LayoutFieldsetContent(fieldset_content, content_break_token,
                               adjusted_padding_box_size, !!legend);
@@ -234,13 +235,6 @@
       return break_status;
   }
 
-  if (!fieldset_content) {
-    container_builder_.SetHasSeenAllChildren();
-    // There was no anonymous child to provide the padding, so we have to add it
-    // ourselves.
-    intrinsic_block_size_ += Padding().BlockSum();
-  }
-
   return NGBreakStatus::kContinue;
 }
 
@@ -483,22 +477,21 @@
 
   // Size containment does not consider the content for sizing.
   if (!has_inline_size_containment) {
-    if (NGBlockNode content = Node().GetFieldsetContent()) {
-      NGMinMaxConstraintSpaceBuilder builder(ConstraintSpace(), Style(),
-                                             content,
-                                             /* is_new_fc */ true);
-      builder.SetAvailableBlockSize(kIndefiniteSize);
-      const auto space = builder.ToConstraintSpace();
+    NGBlockNode content = Node().GetFieldsetContent();
+    DCHECK(content);
+    NGMinMaxConstraintSpaceBuilder builder(ConstraintSpace(), Style(), content,
+                                           /* is_new_fc */ true);
+    builder.SetAvailableBlockSize(kIndefiniteSize);
+    const auto space = builder.ToConstraintSpace();
 
-      MinMaxSizesResult content_result =
-          ComputeMinAndMaxContentContribution(Style(), content, space);
-      content_result.sizes +=
-          ComputeMarginsFor(space, content.Style(), ConstraintSpace())
-              .InlineSum();
-      result.sizes.Encompass(content_result.sizes);
-      result.depends_on_block_constraints |=
-          content_result.depends_on_block_constraints;
-    }
+    MinMaxSizesResult content_result =
+        ComputeMinAndMaxContentContribution(Style(), content, space);
+    content_result.sizes +=
+        ComputeMarginsFor(space, content.Style(), ConstraintSpace())
+            .InlineSum();
+    result.sizes.Encompass(content_result.sizes);
+    result.depends_on_block_constraints |=
+        content_result.depends_on_block_constraints;
   }
 
   result.sizes += ComputeBorders(ConstraintSpace(), Node()).InlineSum();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
index 2d5b9ffc..e653a45 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
@@ -75,6 +75,7 @@
   String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
   offset:unplaced size:1000x26
     offset:0,0 size:126x26
+      offset:3,3 size:120x20
 )DUMP";
   EXPECT_EQ(expectation, dump);
 }
@@ -633,6 +634,7 @@
   String dump = DumpFragmentTree(fragment);
   String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
   offset:unplaced size:120x10
+    offset:10,10 size:100x0
 )DUMP";
   EXPECT_EQ(expectation, dump);
 
@@ -805,7 +807,7 @@
 
   String dump = DumpFragmentTree(fragment);
   String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
-  offset:unplaced size:176x520
+  offset:unplaced size:176x500
     offset:13,0 size:50x500
 )DUMP";
   EXPECT_EQ(expectation, dump);
@@ -817,6 +819,7 @@
   dump = DumpFragmentTree(fragment);
   expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
   offset:unplaced size:176x23
+    offset:3,0 size:170x20
 )DUMP";
   EXPECT_EQ(expectation, dump);
 }
@@ -854,7 +857,7 @@
 
   String dump = DumpFragmentTree(fragment);
   String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
-  offset:unplaced size:176x520
+  offset:unplaced size:176x500
     offset:13,0 size:50x500
 )DUMP";
   EXPECT_EQ(expectation, dump);
@@ -866,6 +869,7 @@
   dump = DumpFragmentTree(fragment);
   expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
   offset:unplaced size:176x23
+    offset:3,0 size:170x20
 )DUMP";
   EXPECT_EQ(expectation, dump);
 }
@@ -1384,6 +1388,7 @@
   offset:unplaced size:1000x60
     offset:0,0 size:100x60
       offset:0,0 size:10x60
+      offset:0,60 size:100x0
 )DUMP";
   EXPECT_EQ(expectation, dump);
 }
@@ -1490,6 +1495,7 @@
   offset:unplaced size:1000x45
     offset:0,0 size:120x45
       offset:20,0 size:10x25
+      offset:10,35 size:100x0
 )DUMP";
   EXPECT_EQ(expectation, dump);
 }
@@ -1689,6 +1695,7 @@
   dump = DumpFragmentTree(fragment);
   expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
   offset:unplaced size:220x10
+    offset:60,0 size:100x10
 )DUMP";
   EXPECT_EQ(expectation, dump);
 
@@ -1745,6 +1752,7 @@
   dump = DumpFragmentTree(fragment);
   expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
   offset:unplaced size:220x10
+    offset:60,0 size:100x10
 )DUMP";
   EXPECT_EQ(expectation, dump);
 
@@ -1855,6 +1863,7 @@
   dump = DumpFragmentTree(fragment);
   expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
   offset:unplaced size:220x10
+    offset:60,0 size:100x10
 )DUMP";
   EXPECT_EQ(expectation, dump);
 
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.cc b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.cc
index 5673bdb..bc5981e8 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.cc
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.cc
@@ -4,10 +4,14 @@
 
 #include "third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h"
 
+#include "base/callback_forward.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/geometry/dom_point.h"
 #include "third_party/blink/renderer/core/geometry/dom_rect.h"
 #include "third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace blink {
@@ -19,6 +23,31 @@
 static constexpr char kWindowStateMinimized[] = "minimized";
 static constexpr char kWindowStateNormal[] = "normal";
 
+namespace {
+
+void OnResponse(ScriptPromiseResolver* resolver,
+                mojom::blink::CrosWindowManagementStatus status) {
+  switch (status) {
+    case mojom::blink::CrosWindowManagementStatus::kSuccess:
+      resolver->Resolve();
+      break;
+    case mojom::blink::CrosWindowManagementStatus::kWindowNoWindowState:
+      resolver->Reject(MakeGarbageCollected<DOMException>(
+          DOMExceptionCode::kInvalidStateError,
+          "Operation couldn't be performed on window."));
+      break;
+    case mojom::blink::CrosWindowManagementStatus::kWindowNotFound:
+    case mojom::blink::CrosWindowManagementStatus::kWindowNoWidget:
+      resolver->Reject(MakeGarbageCollected<DOMException>(
+          DOMExceptionCode::kNotFoundError, "Window not found."));
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+}
+}  // namespace
+
 CrosWindow::CrosWindow(CrosWindowManagement* manager,
                        mojom::blink::CrosWindowInfoPtr window)
     : window_management_(manager), window_(std::move(window)) {}
@@ -75,67 +104,86 @@
                          window_->bounds.width(), window_->bounds.height());
 }
 
-bool CrosWindow::setOrigin(double x, double y) {
+ScriptPromise CrosWindow::setOrigin(ScriptState* script_state,
+                                    double x,
+                                    double y) {
   auto* cros_window_management =
       window_management_->GetCrosWindowManagementOrNull();
   if (!cros_window_management) {
-    return false;
+    return ScriptPromise();
   }
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   cros_window_management->SetWindowBounds(
-      window_->id, x, y, window_->bounds.width(), window_->bounds.height());
-  return true;
+      window_->id, x, y, window_->bounds.width(), window_->bounds.height(),
+      WTF::Bind(&OnResponse, WrapPersistent(resolver)));
+  return resolver->Promise();
 }
 
-bool CrosWindow::setBounds(double x, double y, double width, double height) {
+ScriptPromise CrosWindow::setBounds(ScriptState* script_state,
+                                    double x,
+                                    double y,
+                                    double width,
+                                    double height) {
   auto* cros_window_management =
       window_management_->GetCrosWindowManagementOrNull();
   if (!cros_window_management) {
-    return false;
+    return ScriptPromise();
   }
-  cros_window_management->SetWindowBounds(window_->id, x, y, width, height);
-  return true;
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  cros_window_management->SetWindowBounds(
+      window_->id, x, y, width, height,
+      WTF::Bind(&OnResponse, WrapPersistent(resolver)));
+  return resolver->Promise();
 }
 
-// TODO(crbug.com/1253318): Refactor to trace errors through return value or
-// otherwise.
-void CrosWindow::setFullscreen(bool fullscreen) {
+ScriptPromise CrosWindow::setFullscreen(ScriptState* script_state,
+                                        bool fullscreen) {
   auto* cros_window_management =
       window_management_->GetCrosWindowManagementOrNull();
   if (!cros_window_management) {
-    return;
+    return ScriptPromise();
   }
-  cros_window_management->SetFullscreen(window_->id, fullscreen);
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  cros_window_management->SetFullscreen(
+      window_->id, fullscreen,
+      WTF::Bind(&OnResponse, WrapPersistent(resolver)));
+  return resolver->Promise();
 }
 
-void CrosWindow::maximize() {
+ScriptPromise CrosWindow::maximize(ScriptState* script_state) {
   auto* cros_window_management =
       window_management_->GetCrosWindowManagementOrNull();
   if (!cros_window_management) {
-    return;
+    return ScriptPromise();
   }
-  cros_window_management->Maximize(window_->id);
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  cros_window_management->Maximize(
+      window_->id, WTF::Bind(&OnResponse, WrapPersistent(resolver)));
+  return resolver->Promise();
 }
 
-void CrosWindow::minimize() {
+ScriptPromise CrosWindow::minimize(ScriptState* script_state) {
   auto* cros_window_management =
       window_management_->GetCrosWindowManagementOrNull();
   if (!cros_window_management) {
-    return;
+    return ScriptPromise();
   }
-  cros_window_management->Minimize(window_->id);
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  cros_window_management->Minimize(
+      window_->id, WTF::Bind(&OnResponse, WrapPersistent(resolver)));
+  return resolver->Promise();
 }
 
-bool CrosWindow::raise() {
-  return false;
-}
-
-void CrosWindow::focus() {
+ScriptPromise CrosWindow::focus(ScriptState* script_state) {
   auto* cros_window_management =
       window_management_->GetCrosWindowManagementOrNull();
   if (!cros_window_management) {
-    return;
+    return ScriptPromise();
   }
-  cros_window_management->Focus(window_->id);
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  cros_window_management->Focus(
+      window_->id, WTF::Bind(&OnResponse, WrapPersistent(resolver)));
+  return resolver->Promise();
 }
 
 void CrosWindow::close() {
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h
index 9d5eb51d..8733eb9 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h
@@ -13,6 +13,7 @@
 class DOMPoint;
 class DOMRect;
 class CrosWindowManagement;
+class ScriptPromise;
 
 class CrosWindow : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
@@ -33,13 +34,16 @@
   DOMPoint* origin();
   DOMRect* bounds();
 
-  bool setOrigin(double x, double y);
-  bool setBounds(double x, double y, double width, double height);
-  void setFullscreen(bool fullscreen);
-  void maximize();
-  void minimize();
-  bool raise();
-  void focus();
+  ScriptPromise setOrigin(ScriptState* script_state, double x, double y);
+  ScriptPromise setBounds(ScriptState* script_state,
+                          double x,
+                          double y,
+                          double width,
+                          double height);
+  ScriptPromise setFullscreen(ScriptState* script_state, bool fullscreen);
+  ScriptPromise maximize(ScriptState* script_state);
+  ScriptPromise minimize(ScriptState* script_state);
+  ScriptPromise focus(ScriptState* script_state);
   void close();
 
  private:
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.idl b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.idl
index 7be942c..1ad40bb5 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.idl
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.idl
@@ -32,16 +32,36 @@
   readonly attribute DOMPoint origin;
   readonly attribute DOMRect bounds;
 
-  boolean setOrigin(double x, double y);
-  boolean setBounds(double x, double y, double width, double height);
-  void setFullscreen(boolean fullscreen);
-  // Sets window state to maximized.
-  void maximize();
-  // Sets window state to minimized.
-  void minimize();
-  boolean raise();
+  // Moves the window such that the window's top left corner is at coordinates
+  // (x, y) relative to the top left corner of the current screen. Measured in
+  // CSS pixels of the window. The top left corner of the screen corresponds to
+  // (0, 0). This might change once we support multiple screens and we use the
+  // multi-screen origin:
+  // https://w3c.github.io/window-placement/#multi-screen-origin
+  [CallWith=ScriptState] Promise<void> setOrigin(double x, double y);
+
+  // Moves the window such that the window's top left corner is at coordinates
+  // (x, y) relative to the top left corner of the current screen and sets the
+  // window's dimensions to  width  and  height . Measured in CSS pixels of the
+  // window. The top left corner of the screen corresponds to (0, 0). This might
+  // change once we support multiple screens and we use the multi-screen origin:
+  // https://w3c.github.io/window-placement/#multi-screen-origin
+  [CallWith=ScriptState] Promise<void> setBounds(double x, double y, double width, double height);
+
+  // Sets or unsets window to fullscreen.
+  [CallWith=ScriptState] Promise<void> setFullscreen(boolean fullscreen);
+
+  // Sets window state to maximized. Promise resolves when window starts
+  // maximizing. Promise rejects with an error if the window can't be maximized.
+  [CallWith=ScriptState] Promise<void> maximize();
+
+  // Sets window state to minimized. Promise resolves when window starts
+  // minimizing. Promise rejects with an error if the window can't be minimized.
+  [CallWith=ScriptState] Promise<void> minimize();
+
   // Allocates focus to the CrosWindow identified by id and brings to front.
-  void focus();
+  [CallWith=ScriptState] Promise<void> focus();
+
   // Closes the window.
   void close();
 };
diff --git a/third_party/blink/renderer/modules/presentation/BUILD.gn b/third_party/blink/renderer/modules/presentation/BUILD.gn
index 5f7178f..4be16de 100644
--- a/third_party/blink/renderer/modules/presentation/BUILD.gn
+++ b/third_party/blink/renderer/modules/presentation/BUILD.gn
@@ -35,4 +35,11 @@
     "presentation_request.cc",
     "presentation_request.h",
   ]
+  if (is_android) {
+    sources += [
+      "presentation_metrics.cc",
+      "presentation_metrics.h",
+    ]
+    deps = [ "//services/metrics/public/cpp:ukm_builders" ]
+  }
 }
diff --git a/third_party/blink/renderer/modules/presentation/DEPS b/third_party/blink/renderer/modules/presentation/DEPS
index 6b995a84..ec7c785 100644
--- a/third_party/blink/renderer/modules/presentation/DEPS
+++ b/third_party/blink/renderer/modules/presentation/DEPS
@@ -6,4 +6,5 @@
     "+third_party/blink/renderer/modules/event_target_modules_names.h",
     "+third_party/blink/renderer/modules/modules_export.h",
     "+third_party/blink/renderer/modules/presentation",
+    "+services/metrics/public/cpp",
 ]
diff --git a/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.cc b/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.cc
index b1e01c0..833a0b9 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.cc
@@ -11,6 +11,10 @@
 #include "third_party/blink/renderer/modules/presentation/presentation_error.h"
 #include "third_party/blink/renderer/modules/presentation/presentation_request.h"
 
+#if BUILDFLAG(IS_ANDROID)
+#include "third_party/blink/renderer/modules/presentation/presentation_metrics.h"
+#endif
+
 namespace blink {
 
 PresentationConnectionCallbacks::PresentationConnectionCallbacks(
@@ -75,6 +79,9 @@
                     std::move(connection_receiver));
 
   resolver_->Resolve(connection_);
+#if BUILDFLAG(IS_ANDROID)
+  PresentationMetrics::RecordPresentationConnectionResult(request_, true);
+#endif
 }
 
 void PresentationConnectionCallbacks::OnError(
@@ -82,6 +89,16 @@
   resolver_->Reject(CreatePresentationError(
       resolver_->GetScriptState()->GetIsolate(), error));
   connection_ = nullptr;
+#if BUILDFLAG(IS_ANDROID)
+  // These two error types are not recorded because it's likely that they don't
+  // represent an actual error.
+  if (error.error_type !=
+          mojom::blink::PresentationErrorType::PRESENTATION_REQUEST_CANCELLED &&
+      error.error_type !=
+          mojom::blink::PresentationErrorType::NO_PRESENTATION_FOUND) {
+    PresentationMetrics::RecordPresentationConnectionResult(request_, false);
+  }
+#endif
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/presentation/presentation_metrics.cc b/third_party/blink/renderer/modules/presentation/presentation_metrics.cc
new file mode 100644
index 0000000..acb9ee74
--- /dev/null
+++ b/third_party/blink/renderer/modules/presentation/presentation_metrics.cc
@@ -0,0 +1,40 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/presentation/presentation_metrics.h"
+
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/presentation/presentation_request.h"
+
+namespace blink {
+
+// static
+void PresentationMetrics::RecordPresentationConnectionResult(
+    PresentationRequest* request,
+    bool success) {
+  if (!request)
+    return;
+
+  // Only record when |request| has at least one Presentation URL with "cast:"
+  // scheme.
+  bool has_cast_protocol = false;
+  for (auto url : request->Urls()) {
+    if (url.ProtocolIs("cast")) {
+      has_cast_protocol = true;
+      break;
+    }
+  }
+  if (!has_cast_protocol)
+    return;
+
+  ExecutionContext* execution_context = request->GetExecutionContext();
+  auto* ukm_recorder = execution_context->UkmRecorder();
+  const ukm::SourceId source_id = execution_context->UkmSourceID();
+  ukm::builders::Presentation_StartResult(source_id)
+      .SetPresentationRequest(success)
+      .Record(ukm_recorder);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/presentation/presentation_metrics.h b/third_party/blink/renderer/modules/presentation/presentation_metrics.h
new file mode 100644
index 0000000..fcaea83
--- /dev/null
+++ b/third_party/blink/renderer/modules/presentation/presentation_metrics.h
@@ -0,0 +1,19 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PRESENTATION_PRESENTATION_METRICS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PRESENTATION_PRESENTATION_METRICS_H_
+
+namespace blink {
+class PresentationRequest;
+
+class PresentationMetrics {
+ public:
+  static void RecordPresentationConnectionResult(PresentationRequest* request,
+                                                 bool success);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_PRESENTATION_PRESENTATION_METRICS_H_
diff --git a/third_party/blink/renderer/modules/remoteplayback/BUILD.gn b/third_party/blink/renderer/modules/remoteplayback/BUILD.gn
index a4fb5b9..5b495365a 100644
--- a/third_party/blink/renderer/modules/remoteplayback/BUILD.gn
+++ b/third_party/blink/renderer/modules/remoteplayback/BUILD.gn
@@ -15,5 +15,8 @@
     "remote_playback_metrics.cc",
     "remote_playback_metrics.h",
   ]
-  deps = [ "//third_party/blink/renderer/modules/presentation" ]
+  deps = [
+    "//services/metrics/public/cpp:ukm_builders",
+    "//third_party/blink/renderer/modules/presentation",
+  ]
 }
diff --git a/third_party/blink/renderer/modules/remoteplayback/DEPS b/third_party/blink/renderer/modules/remoteplayback/DEPS
index fdf4734..eacfc6c0 100644
--- a/third_party/blink/renderer/modules/remoteplayback/DEPS
+++ b/third_party/blink/renderer/modules/remoteplayback/DEPS
@@ -5,4 +5,5 @@
     "+third_party/blink/renderer/modules/modules_export.h",
     "+third_party/blink/renderer/modules/presentation",
     "+third_party/blink/renderer/modules/remoteplayback",
+    "+services/metrics/public/cpp",
 ]
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
index b898375..68649ba 100644
--- a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
+++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
@@ -566,10 +566,16 @@
   presentation_connection_receiver_.Bind(
       std::move(result->connection_receiver),
       GetExecutionContext()->GetTaskRunner(TaskType::kMediaElementEvent));
+  RemotePlaybackMetrics::RecordRemotePlaybackStartSessionResult(
+      GetExecutionContext(), true);
 }
 
 void RemotePlayback::OnConnectionError(
     const mojom::blink::PresentationError& error) {
+  // This is called when:
+  // (1) A request to start a presentation failed.
+  // (2) A PresentationRequest is cancelled. i.e. the user closed the device
+  // selection or the route controller dialog.
   presentation_id_ = "";
   presentation_url_ = KURL();
   if (error.error_type ==
@@ -579,6 +585,8 @@
   }
 
   StateChanged(mojom::blink::PresentationConnectionState::CLOSED);
+  RemotePlaybackMetrics::RecordRemotePlaybackStartSessionResult(
+      GetExecutionContext(), false);
 }
 
 void RemotePlayback::HandlePresentationResponse(
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.cc
index e5212b1..c5a1912 100644
--- a/third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.cc
+++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.cc
@@ -5,6 +5,8 @@
 #include "third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.h"
 
 #include "base/metrics/histogram_macros.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
 
 namespace blink {
 // static
@@ -15,4 +17,15 @@
                             RemotePlaybackInitiationLocation::kMaxValue);
 }
 
+// static
+void RemotePlaybackMetrics::RecordRemotePlaybackStartSessionResult(
+    ExecutionContext* execution_context,
+    bool success) {
+  auto* ukm_recorder = execution_context->UkmRecorder();
+  const ukm::SourceId source_id = execution_context->UkmSourceID();
+  ukm::builders::Presentation_StartResult(source_id)
+      .SetRemotePlayback(success)
+      .Record(ukm_recorder);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.h b/third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.h
index 46bdbb6..38b2a1d6 100644
--- a/third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.h
+++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback_metrics.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_REMOTEPLAYBACK_REMOTE_PLAYBACK_METRICS_H_
 
 namespace blink {
+class ExecutionContext;
 
 // Do not remove or renumber enums as this is used for metrics. When making
 // changes, also update the enum list in tools/metrics/histograms/enums.xml to
@@ -20,6 +21,10 @@
  public:
   static void RecordRemotePlaybackLocation(
       RemotePlaybackInitiationLocation location);
+
+  static void RecordRemotePlaybackStartSessionResult(
+      ExecutionContext* execution_context,
+      bool success);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index db8bd1f..322f2f2 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -527,12 +527,6 @@
       status: "experimental",
     },
     {
-      // Support the 'only' keyword for the color-scheme property.
-      name: "CSSColorSchemeOnly",
-      origin_trial_feature_name: "AutoDarkMode",
-      status: "stable",
-    },
-    {
       name: "CSSColorTypedOM",
       status:  "experimental",
     },
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 80e3a17..5afbaca 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -6927,3 +6927,6 @@
 crbug.com/1309533 [ Win ] virtual/threaded-prefer-compositing/external/wpt/css/cssom-view/idlharness.html [ Failure ]
 
 crbug.com/1320290 http/tests/devtools/storage-panel-dom-storage-update.js [ Skip ]
+
+crbug.com/1322405 external/wpt/fetch/metadata/generated/window-history.https.sub.html [ Timeout Pass ]
+crbug.com/1322405 virtual/plz-dedicated-worker/external/wpt/fetch/metadata/generated/window-history.https.sub.html [ Timeout Pass ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/empty-fieldset-tall-bottom-padding-crash.html b/third_party/blink/web_tests/external/wpt/css/css-break/empty-fieldset-tall-bottom-padding-crash.html
new file mode 100644
index 0000000..170a744b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/empty-fieldset-tall-bottom-padding-crash.html
@@ -0,0 +1,6 @@
+<!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=1322426">
+<div style="columns:2; height:100px; column-fill:auto;">
+  <fieldset style="margin:0; border:none; padding:0; border-bottom:1px solid; padding-bottom:200px;"></fieldset>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/first-child.html b/third_party/blink/web_tests/external/wpt/css/selectors/first-child.html
new file mode 100644
index 0000000..c06aff3f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/first-child.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :first-child</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-first-child-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+  See also:
+  * child-indexed-pseudo-class.html
+  * child-indexed-no-parent.html
+  * invalidation/first-child-last-child.html
+-->
+<body>
+
+<div>
+  <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+  <div id="target2">There is the second child element.</div>
+  <blockquote></blockquote>
+</div>
+
+<div>
+  <!-- -->
+  <div id="target3">A comment node should be ignored.</div>
+</div>
+
+<div>
+  .
+  <div id="target4">Non-whitespace text node should be ignored.</div>
+</div>
+
+<div>
+  <blockquote></blockquote>
+  <div id="target5" data-expected="false">The second child should not be matched.</div>
+</div>
+
+<script>
+for (let i = 1; i <= 5; ++i) {
+  let target = document.querySelector(`#target${i}`);
+  test(() => {
+    if (target.dataset.expected == 'false')
+      assert_false(target.matches(':first-child'));
+    else
+      assert_true(target.matches(':first-child'));
+  }, target.textContent);
+}
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/first-of-type.html b/third_party/blink/web_tests/external/wpt/css/selectors/first-of-type.html
new file mode 100644
index 0000000..b585ed2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/first-of-type.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :first-of-type</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-first-of-type-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+  See also:
+  * of-type-selectors.html
+  * child-indexed-pseudo-class.html
+  * child-indexed-no-parent.html
+-->
+<body>
+
+<div>
+  <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+  <div id="target2">Thre is another child element of the same type.</div>
+  <div></div>
+</div>
+
+<div>
+  <blockquote></blockquote>
+  <div id="target3">There is a prior child element of another type.</div>
+</div>
+
+<div>
+  <div></div>
+  <blockquote>
+    <div id="target4">A previous element of the parent should not affect.</div>
+  </blockquote>
+</div>
+
+<div>
+  <div>
+    <div id="target5">The parent element of the same type should not affect.</div>
+  </div>
+</div>
+
+<div>
+  <blockquote>
+    <div></div>
+  </blockquote>
+  <div id="target6">A child of the previous element should not affect.</div>
+</div>
+
+<div>
+  <div></div>
+  <div id="target7" data-expected="false">The second child element of the same
+type should not match.</div>
+</div>
+
+<div>
+  <DIV></DIV>
+  <div id="target8" data-expected="false">The second child element of the same
+type should not match, the first child has case-different tag name.</div>
+</div>
+
+<div>
+  <div id="insertBefore1"></div>
+</div>
+
+<script>
+for (let i = 1; i <= 8; ++i) {
+  let target = document.querySelector(`#target${i}`);
+  test(() => {
+    if (target.dataset.expected == 'false')
+      assert_false(target.matches('div:first-of-type'));
+    else
+      assert_true(target.matches('div:first-of-type'));
+  }, target.textContent.replaceAll('\n', ' '));
+}
+
+test(() => {
+  const ib1 = document.querySelector('#insertBefore1');
+  const target = document.createElement('div');
+  assert_true(ib1.matches('div:first-of-type'));
+  ib1.parentNode.insertBefore(target, ib1);
+  assert_true(target.matches('div:first-of-type'));
+  assert_false(ib1.matches('div:first-of-type'));
+
+  target.remove();
+  assert_true(ib1.matches('div:first-of-type'));
+}, 'Dynamic insertion and removal');
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/last-child.html b/third_party/blink/web_tests/external/wpt/css/selectors/last-child.html
new file mode 100644
index 0000000..423ccf8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/last-child.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :last-child</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-last-child-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+  See also:
+  * child-indexed-pseudo-class.html
+  * child-indexed-no-parent.html
+  * invalidation/first-child-last-child.html
+-->
+<body>
+
+<div>
+  <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+  <blockquote></blockquote>
+  <div id="target2">There is a prior child element.</div>
+</div>
+
+<div>
+  <div id="target3">A comment node should be ignored.</div>
+  <!-- -->
+</div>
+
+<div>
+  <div id="target4">Non-whitespace text node should be ignored.</div>
+  .
+</div>
+
+<div>
+  <div id="target5" data-expected="false">The first child should not be matched.</div>
+  <blockquote></blockquote>
+</div>
+
+<script>
+for (let i = 1; i <= 5; ++i) {
+  let target = document.querySelector(`#target${i}`);
+  test(() => {
+    if (target.dataset.expected == 'false')
+      assert_false(target.matches(':last-child'));
+    else
+      assert_true(target.matches(':last-child'));
+  }, target.textContent);
+}
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/last-of-type.html b/third_party/blink/web_tests/external/wpt/css/selectors/last-of-type.html
new file mode 100644
index 0000000..35328313
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/last-of-type.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :last-of-type</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-last-of-type-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+  See also:
+  * child-indexed-pseudo-class.html
+  * child-indexed-no-parent.html
+-->
+<body>
+
+<div>
+  <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+  <div></div>
+  <div id="target2">Thre is another child element of the same type.</div>
+</div>
+
+<div>
+  <div id="target3">There is a posterior child element of another type.</div>
+  <blockquote></blockquote>
+</div>
+
+<div>
+  <blockquote>
+    <div id="target4">A next element of the parent should not affect.</div>
+  </blockquote>
+  <div></div>
+</div>
+
+<div>
+  <div>
+    <div id="target5">The parent element of the same type should not affect.</div>
+  </div>
+</div>
+
+<div>
+  <div id="target6">A child of the next element should not affect.</div>
+  <blockquote>
+    <div></div>
+  </blockquote>
+</div>
+
+<div>
+  <div id="target7" data-expected="false">The first child element of the same
+type should not match.</div>
+  <div></div>
+</div>
+
+<div>
+  <div id="target8" data-expected="false">The first child element of the same
+type should not match, the last child has a case-different tag name.</div>
+  <DIV></DIV>
+</div>
+
+<div>
+  <div id="insertAfter1"></div>
+</div>
+
+<script>
+for (let i = 1; i <= 8; ++i) {
+  let target = document.querySelector(`#target${i}`);
+  test(() => {
+    if (target.dataset.expected == 'false')
+      assert_false(target.matches('div:last-of-type'));
+    else
+      assert_true(target.matches('div:last-of-type'));
+  }, target.textContent.replaceAll('\n', ' '));
+}
+
+test(() => {
+  const ia1 = document.querySelector('#insertAfter1');
+  const target = document.createElement('div');
+  assert_true(ia1.matches('div:last-of-type'));
+  ia1.parentNode.insertBefore(target, ia1.nextSibling);
+  assert_true(target.matches('div:last-of-type'));
+  assert_false(ia1.matches('div:last-of-type'));
+
+  target.remove();
+  assert_true(ia1.matches('div:last-of-type'));
+}, 'Dynamic insertion and removal');
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/empty-scrollable-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/empty-scrollable-ref.html
new file mode 100644
index 0000000..7fa15da1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/empty-scrollable-ref.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<div style="all:initial; display:block; overflow:scroll; width:100px; height:100px; background:blue;"></div>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/empty-scrollable.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/empty-scrollable.html
new file mode 100644
index 0000000..c968ed3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/empty-scrollable.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements">
+<link rel="match" href="empty-scrollable-ref.html">
+<fieldset style="all:initial; display:block; overflow:scroll; width:100px; height:100px; background:blue;"></fieldset>
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/resources/web-usb.https.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/web-usb.https.html
similarity index 100%
rename from third_party/blink/web_tests/wpt_internal/prerender/resources/web-usb.https.html
rename to third_party/blink/web_tests/external/wpt/speculation-rules/prerender/resources/web-usb.https.html
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/restriction-web-usb.https.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-usb.https.html
similarity index 96%
rename from third_party/blink/web_tests/wpt_internal/prerender/restriction-web-usb.https.html
rename to third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-usb.https.html
index cca2216..9d96a39 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/restriction-web-usb.https.html
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-usb.https.html
@@ -7,6 +7,7 @@
 <script src="/speculation-rules/prerender/resources/utils.js"></script>
 <body>
 <script>
+setup(() => assertSpeculationRulesIsSupported());
 
 promise_test(async t => {
   const uid = token();
diff --git a/third_party/blink/web_tests/fast/arraybuffer/size_check_of_web_api.html b/third_party/blink/web_tests/fast/arraybuffer/size_check_of_web_api.html
new file mode 100644
index 0000000..83e5251
--- /dev/null
+++ b/third_party/blink/web_tests/fast/arraybuffer/size_check_of_web_api.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html crossorigin>
+<head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+  <script>
+test(() => {
+  let mem;
+  try {
+    mem = new WebAssembly.Memory({initial: 33000, maximum: 33000});
+  } catch (e) {
+    // We failed to allocate the WebAssembly memory. We can just return.
+    assert_equals(e.constructor, RangeError);
+    assert_equals(e.message,
+      "WebAssembly.Memory(): could not allocate memory");
+    return;
+  }
+  let canvas = document.createElement("canvas");
+  let context = canvas.getContext("webgl");
+  let data = new Uint8Array(mem.buffer);
+  assert_throws_js(RangeError,
+    () => context.bufferSubData(context.ARRAY_BUFFER, 0, data));
+}, "Test that webgl rejects an ArrayBuffer bigger than 2GB.");
+
+test(() => {
+  let mem;
+  try {
+    mem = new WebAssembly.Memory({initial: 33000, maximum: 33000});
+  } catch (e) {
+    // We failed to allocate the WebAssembly memory. We can just return.
+    assert_equals(e.constructor, RangeError);
+    assert_equals(e.message,
+      "WebAssembly.Memory(): could not allocate memory");
+    return;
+  }
+  let canvas = document.createElement("canvas");
+  let context = canvas.getContext("webgl");
+  let data = new Uint8Array(mem.buffer, 10, 16);
+  context.bufferSubData(context.ARRAY_BUFFER, 0, data);
+}, "Test that webgl accepts a small view of ArrayBuffer bigger than 2GB.");
+  </script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/fast/block/float/float-avoidance.html b/third_party/blink/web_tests/fast/block/float/float-avoidance.html
index 72f5dcca..1ae9ebc 100644
--- a/third_party/blink/web_tests/fast/block/float/float-avoidance.html
+++ b/third_party/blink/web_tests/fast/block/float/float-avoidance.html
@@ -1,36 +1,55 @@
+<style>
+.no-break {
+  break-inside: avoid;
+}
+p {
+  margin-top: 2px;
+}
+</style>
+<body>
 Test of objects that avoid floats to see what they do with percentage and auto widths.  This test is designed to illustrate that we have removed
 the WinIE quirk and are behaving more like Firefox.
 
 <hr>
+<div style="columns:3; zoom:0.6;">
 
+<div class="no-break">
 The inline-level button should be below the select and fill the width of the block.
 
 <p style="border:10px solid red; width:200px">Line One<br>
 <select style="width:50%; float:left"><option>One</select>
 <input type=button value="Hi" style="width:100%">
 </p>
+</div>
 
+<div class="no-break">
 The floating button with a percentage width should be even with the select.
 <p style="border:10px solid red; width:200px">Line One<br>
 <select style="width:50%; float:left"><option>One</select>
 <input type=button value="Hi" style="float:left; width:50%">
 <br clear=all>
 </p>
+</div>
 
+<div class="no-break">
 The block-level button with an auto width should be even with the select.
 <p style="border:10px solid red; width:200px">Line One<br>
 <select style="width:50%; float:left"><option>One</select>
 <input type=button value="Hi" style="display:block">
 <br clear=all>
 </p>
+</div>
 
+<div class="no-break">
 The block-level button with a percentage width should be even with the select.
 <p style="border:10px solid red; width:200px">Line One<br>
 <select style="width:50%; float:left"><option>One</select>
 <input type=button value="Hi" style="display:block; width:50%">
 <br clear=all>
 </p>
+</div>
 
+<div class="no-break">
 The floating table with a percentage width should be even with the select.
 
 <p style="border:10px solid red; width:200px">Line One<br>
@@ -38,7 +57,9 @@
 <table border=2 style="float:left; width:50%"><tr><td>Table</table>
 <br clear=all>
 </p>
+</div>
 
+<div class="no-break">
 The floating table with an auto width should be even with the select and shrinks to use the available line width.
 THIS IS CURRENTLY BUGGY.
 
@@ -47,7 +68,9 @@
 <table border=2 style="float:right"><tr><td>Floating table that should shrink so it can be next to previous float.</table>
 <br clear=all>
 </p>
+</div>
 
+<div class="no-break">
 The block-level table below has a percentage width and should still be even with the select.  It spills out of the block.
 
 <p style="border:10px solid red; width:200px">Line One<br>
@@ -55,8 +78,10 @@
 <table border=2 style="width:100%"><tr><td>Floating table that should shrink so it can be next to previous float.</table>
 <br clear=all>
 </p>
+</div>
 
 
+<div class="no-break">
 The block-level table below has an auto width and should still be even with the select.  It shrinks to fit inside the block.
 
 <p style="border:10px solid red; width:200px">Line One<br>
@@ -64,11 +89,13 @@
 <table border=2><tr><td>Floating table that should shrink so it can be next to previous float.</table>
 <br clear=all>
 </p>
+</div>
 
 
 
 
 
+<div class="no-break">
 The floating overflow section with a percentage width should be even with the select.
 
 <div style="border:10px solid red; width:200px">Line One<br>
@@ -76,7 +103,9 @@
 <div border=2 style="float:left; width:50%; overflow:auto">This is an overflow section with enough text to have to wrap to multiple lines.</div>
 <br clear=all>
 </div>
+</div>
 
+<div class="no-break">
 The floating overflow section with an auto width should be even with the select and shrinks to use the available line width.
 THIS IS CURRENTLY BUGGY.
 
@@ -85,7 +114,9 @@
 <div border=2 style="float:left; overflow:auto">This is an overflow section with enough text to have to wrap to multiple lines.</div>
 <br clear=all>
 </div>
+</div>
 
+<div class="no-break">
 The block-level overflow section below has a percentage width and should still be even with the select.
 
 <div style="border:10px solid red; width:200px">Line One<br>
@@ -93,8 +124,10 @@
 <div border=2 style="width:50%; overflow:auto">This is an overflow section with enough text to have to wrap to multiple lines.</div>
 <br clear=all>
 </div>
+</div>
 
 
+<div class="no-break">
 The block-level overflow section below has an auto width and should still be even with the select.  It shrinks to fit inside the block.
 
 <div style="border:10px solid red; width:200px">Line One<br>
@@ -102,9 +135,11 @@
 <div border=2 style="overflow:auto">This is an overflow section with enough text to have to wrap to multiple lines.</div>
 <br clear=all>
 </div>
+</div>
 
 
 
+<div class="no-break">
 The floating hr with a percentage width should be even with the select.
 
 <div style="border:10px solid red; width:200px">Line One<br>
@@ -112,7 +147,9 @@
 <hr style="float:left; width:40%; margin:2px">
 <br clear=all>
 </div>
+</div>
 
+<div class="no-break">
 The floating hr below should still be even with the select and shrinks to use its intrinsic width (which is basically like 1-2px).
 
 <div style="border:10px solid red; width:200px">Line One<br>
@@ -121,7 +158,9 @@
 
 <br clear=all>
 </div>
+</div>
 
+<div class="no-break">
 The block-level hr below has a percentage width and should still be even with the select.
 
 <div style="border:10px solid red; width:200px">Line One<br>
@@ -129,7 +168,9 @@
 <hr style="width:100%">
 <br clear=all>
 </div>
+</div>
 
+<div class="no-break">
 The block-level hr below has an auto width and should still be even with the select.  It shrinks to fit.
 
 <div style="border:10px solid red; width:200px">Line One<br>
@@ -137,4 +178,7 @@
 <hr>
 <br clear=all>
 </div>
+</div>
 
+</div>
+</body>
diff --git a/third_party/blink/web_tests/fast/block/float/shrink-to-avoid-float-complexity.html b/third_party/blink/web_tests/fast/block/float/shrink-to-avoid-float-complexity.html
index cb2bbc1..b629155 100644
--- a/third_party/blink/web_tests/fast/block/float/shrink-to-avoid-float-complexity.html
+++ b/third_party/blink/web_tests/fast/block/float/shrink-to-avoid-float-complexity.html
@@ -12,9 +12,10 @@
   {
   background-color: silver; 
   /* height: 200px; */
-  margin: 1em 0em;
+  margin: 0em 0em;
   overflow: hidden;
   width: 100%;
+  font-size: 14px;
   }
 
   div.float
@@ -22,9 +23,9 @@
   background-color: yellow;
   border: green solid 4px;
   float: left;
-  height: 128px;
-  padding: 2em;
-  width: 128px;
+  height: 80px;
+  padding: 4px;
+  width: 100px;
   }
   
   /*
@@ -34,15 +35,15 @@
   
       4px (border-top)
   +
-     32px (padding-top)
+      4px (padding-top)
   +    
-    128px (height)
+     80px (height)
   +
-     32px (padding-bottom)
+      4px (padding-bottom)
   +
       4px (border-bottom)
    =======
-    200px
+     96px
 
 
   offsetWidth of div.float
@@ -50,15 +51,15 @@
   
       4px (border-left)
   +
-     32px (padding-left)
+      4px (padding-left)
   +    
-    128px (width)
+    100px (width)
   +
-     32px (padding-right)
+      4px (padding-right)
   +
       4px (border-right)
    =======
-    200px
+    116px
 
   */
 
@@ -79,14 +80,16 @@
   {
   color: red;
   font-weight: bolder;
-  }  
-  
-  hr {margin: 3em;}
+  }
+
+  h2 {
+  margin: 0;
+  }
   </style>
 
  </head>
 
- <body>
+ <body style="columns: 2">
 
  
   <!--
@@ -105,12 +108,9 @@
 
   <div class="container">
     <div class="float">This yellow square is floated left and it has no margin.</div>
-    <div style="margin: 0px 100px" class="overflow">This orange rectangle:<br>
+    <div style="margin: 0px 50px" class="overflow">This orange rectangle:<br>
         – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 100px left margin and a 100px right margin;<br><br>
-        This orange rectangle:<br>
-        – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 100px left margin and a 100px right margin;
+        – has a 50px left margin and a 50px right margin;
     </div>
   </div><!-- .container -->
 
@@ -121,12 +121,9 @@
 
   <div class="container">
     <div class="float">This yellow square is floated left and it has no margin.</div>
-    <div style="margin-left: 200px;" class="overflow">This orange rectangle:<br>
+    <div style="margin-left: 116px;" class="overflow">This orange rectangle:<br>
         – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 200px left margin;<br><br>
-        This orange rectangle:<br>
-        – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 200px left margin;
+        – has a 116px left margin;
     </div>
   </div><!-- .container -->
 
@@ -136,46 +133,39 @@
   <h2 id="test3">Test 3 (1 float)</h2>
 
   <div class="container">
-    <div style="margin-right: 100px;" class="float">This yellow square is a floated left and it has a right margin of 100px.</div>
+    <div style="margin-right: 50px;" class="float">This yellow square is a floated left and it has a right margin of 50px.</div>
 
-    <div style="margin-right: 100px;" class="overflow">This orange rectangle:<br>
+    <div style="margin-right: 50px;" class="overflow">This orange rectangle:<br>
         – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 0px left margin and a 100px right margin;<br><br>
-        This orange rectangle:<br>
-        – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 0px left margin and a 100px right margin;
+        – has a 0px left margin and a 50px right margin;
     </div>
   </div><!-- .container -->
 
  
   <hr>
 
+  <div style="break-inside: avoid">
   <h2 id="test4">Test 4 (2 floats)</h2>
 
   <div class="container">
     <div class="float">This yellow square is floated left and it has no margin.</div>
     <div style="float: right;" class="float">This yellow square is a floated right and it has no margin.</div>
-    <div style="margin: 0px 100px;" class="overflow">This orange rectangle:<br>
+    <div style="margin: 0px 50px;" class="overflow">This orange rectangle:<br>
         – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 100px left margin and a 100px right margin;<br><br>
-        This orange rectangle:<br>
-        – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 100px left margin and a 100px right margin;
+        – has a 50px left margin and a 50px right margin;
     </div>
   </div><!-- .container -->
   <hr>
+  </div>
 
   <h2 id="test5">Test 5 (2 floats)</h2>
 
   <div class="container">
     <div class="float">This yellow square is floated left and it has no margin.</div>
     <div style="float: right;" class="float">This yellow square is a floated right and it has no margin.</div>
-    <div style="margin-right: 200px;" class="overflow">This orange rectangle:<br>
+    <div style="margin-right: 100px;" class="overflow">This orange rectangle:<br>
         – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 200px right margin;<br><br>
-        This orange rectangle:<br>
-        – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 200px right margin;
+        – has a 100px right margin;
     </div>
   </div><!-- .container -->
 
@@ -185,13 +175,10 @@
   <h2 id="test6">Test 6 (2 floats)</h2>
 
   <div class="container">
-    <div style="margin-right: 100px;" class="float">This yellow square is floated left and it has a right margin of 100px.</div>
-    <div style="float: right; margin-left: 100px;" class="float">This yellow square is floated right and it has a left margin of 100px.</div>
+    <div style="margin-right: 20px;" class="float">This yellow square is floated left and it has a right margin of 20px.</div>
+    <div style="float: right; margin-left: 20px;" class="float">This yellow square is floated right and it has a left margin of 20px.</div>
     <div class="overflow">This orange rectangle:<br>
         – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
-        – has a 0px left margin and a 0px right margin;<br><br>
-        This orange rectangle:<br>
-        – establishes a <strong>new block formating context</strong> thanks to the CSS declaration <code>overflow: hidden</code>;<br>
         – has a 0px left margin and a 0px right margin;
     </div>
   </div><!-- .container -->
@@ -211,4 +198,4 @@
  
 
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/fast/css/first-child-pseudo-class.html b/third_party/blink/web_tests/fast/css/first-child-pseudo-class.html
deleted file mode 100644
index 24c55e9..0000000
--- a/third_party/blink/web_tests/fast/css/first-child-pseudo-class.html
+++ /dev/null
@@ -1,197 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-	<head>
-		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-		<title>:first-child</title>
-		
-		<style type='text/css'>
-		<!--
-
-			body { background: #fff; color: 000; font-family: Arial, Helvetica, sans-serif; }
-			pre { background: #fff; padding: 0.5em; }
-			li { background: #aaa; padding: 1em; width: 80%; margin: 0 0 3em; }
-			.test { display: block; padding: 0.75em; }
-			.base, .defaultgreen { background-color: #090; }
-			.defaultred { background-color: #900; }
-			
-			.defaultred :first-child {
-				background-color: #090;
-			}
-
-			.defaultgreen :first-child {
-				background-color: #900;
-			}
-
-			blockquote {
-				margin: 0;
-			}
-
-		-->			
-		</style>
-	</head>
-
-	<body>
-		<p>This page is part of the <a href="http://www.css3.info">CSS3.info</a> <a href="http://www.css3.info/selectors-test/">CSS selectors test</a>. See more info on <a href="http://www.css3.info/preview/attribute-selectors.html">CSS3 selectors</a>.</p>
-		
-		<div class='base'></div>
-	
-		<ol>
-			<li>
-				<div class='defaultred'>
-					<div class='test required'></div>
-				</div>
-				
-				<pre>div :first-child {
-}
-
-&lt;div&gt;
-   &lt;div&gt;&lt;/div&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the inner div element, because it is the only child of the outer div element
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<div class='test'></div>
-					<blockquote></blockquote>
-				</div>
-				
-				<pre>div :first-child {
-}
-
-&lt;div&gt; 
-   &lt;div&gt;&lt;/div&gt;
-   &lt;blockquote&gt;&lt;/blockquote&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the inner div element, because it is the first child of the outer div element
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<!-- Just a comment -->
-					<div class='test'></div>
-				</div>
-				
-				<pre>div :first-child {
-}
-
-&lt;div&gt; 
-   &lt;!-- Just a comment --&gt;
-   &lt;div&gt;&lt;/div&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the inner div element, because it is the first child of the outer div element
-					Comments are not elements, so they should not be considered when determining the first child.
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					.
-					<div class='test'></div>
-				</div>
-				
-				<pre>div :first-child {
-}
-
-&lt;div&gt; 
-   How about regular text...
-   &lt;div&gt;&lt;/div&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the inner div element, because it is the first child of the outer div element.
-					Regular text is not an element, so it should not be considered when determining the first child.
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultgreen'>
-					<blockquote></blockquote>
-					<div class='test default required'></div>
-				</div>
-				
-				<pre>div :first-child {
-}
-
-&lt;div&gt; 
-   &lt;blockquote&gt;&lt;/blockquote&gt;
-   &lt;div&gt;&lt;/div&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should not match the inner div element, because it is the second child of the outer div element
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<div id='insertBefore1'></div>
-				</div>
-
-				<script type="text/javascript">
-				<!--
-
-					var ib = document.getElementById('insertBefore1');
-					var el = document.createElement("div");
-					el.className = 'test';
-					ib.parentNode.insertBefore(el, ib);
-
-				
-				//-->
-				</script>
-				
-				<pre>div :first-child {
-}
-
-&lt;div&gt;
-   &lt;div id='insertBefore'&gt;&lt;/div&gt;
-&lt;/div&gt;
-
-var ib = document.getElementById('insertBefore');
-ib.parentElement.insertBefore(document.createElement("div"), ib);</pre>
-
-				<p>
-					The CSS selector should match the div element that is inserted by the Javascript code. 
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultgreen'>
-					<div id='insertBefore2' class='test default'></div>
-				</div>
-
-				<script type="text/javascript">
-				<!--
-
-					var ib = document.getElementById('insertBefore2');
-					ib.parentNode.insertBefore(document.createElement("div"), ib);
-				
-				//-->
-				</script>
-				
-				<pre>div :first-child {
-}
-
-&lt;div&gt;
-   &lt;div id='insertBefore'&gt;&lt;/div&gt;
-&lt;/div&gt;
-
-var ib = document.getElementById('insertBefore');
-ib.parentElement.insertBefore(document.createElement("div"), ib);</pre>
-
-				<p>
-					The original div element should not be a match for the :first-child selector.
-				</p>
-			</li>
-		</ol>
-	</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/first-of-type-pseudo-class.html b/third_party/blink/web_tests/fast/css/first-of-type-pseudo-class.html
deleted file mode 100644
index ad7510fb..0000000
--- a/third_party/blink/web_tests/fast/css/first-of-type-pseudo-class.html
+++ /dev/null
@@ -1,242 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-	<head>
-		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-		<title>:first-of-type</title>
-		
-		<style type='text/css'>
-		<!--
-
-			body { background: #fff; color: 000; font-family: Arial, Helvetica, sans-serif; }
-			pre { background: #fff; padding: 0.5em; }
-			li { background: #aaa; padding: 1em; width: 80%; margin: 0 0 3em; }
-			.test { display: block; padding: 0.75em; }
-			.base, .defaultgreen { background-color: #090; }
-			.defaultred { background-color: #900; }
-			
-			.defaultred :first-of-type {
-				background-color: #090;
-			}
-
-			.defaultgreen :first-of-type {
-				background-color: #900;
-			}
-
-			blockquote {
-				margin: 0;
-			}
-
-		-->
-		</style>
-	</head>
-
-	<body>
-		<p>This page is part of the <a href="http://www.css3.info">CSS3.info</a> <a href="http://www.css3.info/selectors-test/">CSS selectors test</a>. See more info on <a href="http://www.css3.info/preview/attribute-selectors.html">CSS3 selectors</a>.</p>
-		
-		<div class='base'></div>
-	
-		<ol>
-			<li>
-				<div class='defaultred'>
-					<div class='test required'></div>
-				</div>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;div&gt;Does this element match?&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the only element of this type
-				</p>
-			</li>
-			
-			<li>
-				<div class='defaultred'>
-					<div class='test'></div>
-					<div></div>
-				</div>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;div&gt;&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the first element of this type
-				</p>
-			</li>
-			
-			<li>
-				<div class='defaultred'>
-					<blockquote></blockquote>
-					<div class='test required'></div>
-				</div>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;blockquote&gt;&lt;/blockquote&gt;
-&lt;div&gt;Does this element match?&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the first element of this type
-				</p>
-			</li>
-	
-			<li>
-				<div class='defaultred'>
-					<div></div>
-					<blockquote>
-						<div class='test'></div>
-					</blockquote>
-				</div>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;div&gt;&lt;/div&gt;
-&lt;blockquote&gt;
-   &lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;/blockquote&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the first element of this type in this scope
-				</p>
-			</li>
-	
-			<li>
-				<div class='defaultred'>
-					<div>
-						<div class='test'></div>
-					</div>
-				</div>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;div&gt;
-   &lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the first element of this type in the current scope
-				</p>
-			</li>
-			
-			<li>
-				<div class='defaultred'>
-					<blockquote>
-						<div></div>
-					</blockquote>
-					<div class='test'></div>
-				</div>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;blockquote&gt;
-   &lt;div&gt;&lt;/div&gt;
-&lt;/blockquote&gt;
-&lt;div&gt;Does this element match?&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the first element of this type in the current scope
-				</p>
-			</li>
-	
-			<li>
-				<div class='defaultgreen'>
-					<div></div>
-					<div class='test default required'></div>
-				</div>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;div&gt;&lt;/div&gt;
-&lt;div&gt;Does this element match?&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should not match the marked div element, because it is the second element of this type
-				</p>
-			</li>
-			
-			<li>
-				<div class='defaultgreen'>
-					<DIV></DIV>
-					<div class='test default'></div>
-				</div>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;DIV&gt;&lt;/DIV&gt;
-&lt;div&gt;Does this element match?&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should not match the marked div element, because it is the second element of this type
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<div id='insertBefore1'></div>
-				</div>
-
-				<script type="text/javascript">
-				<!--
-
-					var ib = document.getElementById('insertBefore1');
-					var el = document.createElement("div");
-					el.className = 'test';
-					ib.parentNode.insertBefore(el, ib);
-
-				
-				//-->
-				</script>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;div id='insertBefore'&gt;&lt;/div&gt;
-
-var ib = document.getElementById('insertBefore');
-ib.parentElement.insertBefore(document.createElement("div"), ib);</pre>
-
-				<p>
-					The CSS selector should match the div element that is inserted by the Javascript code. 
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultgreen'>
-					<div id='insertBefore2' class='test default'></div>
-				</div>
-
-				<script type="text/javascript">
-				<!--
-
-					var ib = document.getElementById('insertBefore2');
-					ib.parentNode.insertBefore(document.createElement("div"), ib);
-				
-				//-->
-				</script>
-				
-				<pre>div:first-of-type {
-}
-
-&lt;div id='insertBefore'&gt;&lt;/div&gt;
-
-var ib = document.getElementById('insertBefore');
-ib.parentElement.insertBefore(document.createElement("div"), ib);</pre>
-
-				<p>
-					The original div element should not be a match for the :first-of-type selector.
-				</p>
-			</li>
-		</ol>	
-	</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/last-child-pseudo-class.html b/third_party/blink/web_tests/fast/css/last-child-pseudo-class.html
deleted file mode 100644
index 32b1a53..0000000
--- a/third_party/blink/web_tests/fast/css/last-child-pseudo-class.html
+++ /dev/null
@@ -1,197 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-	<head>
-		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-		<title>:last-child</title>
-		
-		<style type='text/css'>
-		<!--
-
-			body { background: #fff; color: 000; font-family: Arial, Helvetica, sans-serif; }
-			pre { background: #fff; padding: 0.5em; }
-			li { background: #aaa; padding: 1em; width: 80%; margin: 0 0 3em; }
-			.test { display: block; padding: 0.75em; }
-			.base, .defaultgreen { background-color: #090; }
-			.defaultred { background-color: #900; }
-			
-			.defaultred :last-child {
-				background-color: #090;
-			}
-
-			.defaultgreen :last-child {
-				background-color: #900;
-			}
-
-			blockquote {
-				margin: 0;
-			}
-			
-		-->
-		</style>
-	</head>
-
-	<body>
-		<p>This page is part of the <a href="http://www.css3.info">CSS3.info</a> <a href="http://www.css3.info/selectors-test/">CSS selectors test</a>. See more info on <a href="http://www.css3.info/preview/attribute-selectors.html">CSS3 selectors</a>.</p>
-		
-		<div class='base'></div>
-	
-		<ol>
-			<li>
-				<div class='defaultred'>
-					<div class='test required'></div>
-				</div>
-				
-				<pre>div :last-child {
-}
-
-&lt;div&gt;
-   &lt;div&gt;&lt;/div&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the inner div element, because it is the only child of the outer div element
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<blockquote></blockquote>
-					<div class='test'></div>
-				</div>
-				
-				<pre>div :last-child {
-}
-
-&lt;div&gt; 
-   &lt;blockquote&gt;&lt;/blockquote&gt;
-   &lt;div&gt;&lt;/div&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the inner div element, because it is the last child of the outer div element
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<!-- Just a comment -->
-					<div class='test'></div>
-				</div>
-				
-				<pre>div :last-child {
-}
-
-&lt;div&gt; 
-   &lt;div&gt;&lt;/div&gt;
-   &lt;!-- Just a comment --&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the inner div element, because it is the last child of the outer div element
-					Comments are not elements, so they should not be considered when determining the last child.
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<div class='test'></div>
-					.
-				</div>
-				
-				<pre>div :last-child {
-}
-
-&lt;div&gt; 
-   &lt;div&gt;&lt;/div&gt;
-   How about regular text...
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the inner div element, because it is the last child of the outer div element.
-					Regular text is not an element, so it should not be considered when determining the last child.
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultgreen'>
-					<div class='test default required'></div>
-					<blockquote></blockquote>
-				</div>
-				
-				<pre>div :last-child {
-}
-
-&lt;div&gt; 
-   &lt;div&gt;&lt;/div&gt;
-   &lt;blockquote&gt;&lt;/blockquote&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should not match the inner div element, because it is the first child of the outer div element
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<div id='insertAfter1'></div>
-				</div>
-
-				<script type="text/javascript">
-				<!--
-
-					var ib = document.getElementById('insertAfter1');
-					var el = document.createElement("div");
-					el.className = 'test';
-					ib.parentNode.appendChild(el);
-
-				
-				//-->
-				</script>
-				
-				<pre>div :last-child {
-}
-
-&lt;div&gt;
-   &lt;div id='insertAfter'&gt;&lt;/div&gt;
-&lt;/div&gt;
-
-var ib = document.getElementById('insertAfter');
-ib.parentElement.appendChild(document.createElement("div"));</pre>
-
-				<p>
-					The CSS selector should match the div element that is inserted by the Javascript code. 
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultgreen'>
-					<div id='insertAfter2' class='test default'></div>
-				</div>
-
-				<script type="text/javascript">
-				<!--
-
-					var ib = document.getElementById('insertAfter2');
-					ib.parentNode.appendChild(document.createElement("div"));
-				
-				//-->
-				</script>
-				
-				<pre>div :last-child {
-}
-
-&lt;div&gt;
-   &lt;div id='insertAfter'&gt;&lt;/div&gt;
-&lt;/div&gt;
-
-var ib = document.getElementById('insertAfter');
-ib.parentElement.appendChild(document.createElement("div"));</pre>
-
-				<p>
-					The original div element should not be a match for the :last-child selector.
-				</p>
-			</li>
-		</ol>
-	</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/last-of-type-pseudo-class.html b/third_party/blink/web_tests/fast/css/last-of-type-pseudo-class.html
deleted file mode 100644
index 2a22c33..0000000
--- a/third_party/blink/web_tests/fast/css/last-of-type-pseudo-class.html
+++ /dev/null
@@ -1,242 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-	<head>
-		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-		<title>:last-of-type</title>
-		
-		<style type='text/css'>
-		<!--
-
-			body { background: #fff; color: 000; font-family: Arial, Helvetica, sans-serif; }
-			pre { background: #fff; padding: 0.5em; }
-			li { background: #aaa; padding: 1em; width: 80%; margin: 0 0 3em; }
-			.test { display: block; padding: 0.75em; }
-			.base, .defaultgreen { background-color: #090; }
-			.defaultred { background-color: #900; }
-			
-			.defaultred :last-of-type {
-				background-color: #090;
-			}
-
-			.defaultgreen :last-of-type {
-				background-color: #900;
-			}
-
-			blockquote {
-				margin: 0;
-			}
-
-		-->
-		</style>
-	</head>
-
-	<body>
-		<p>This page is part of the <a href="http://www.css3.info">CSS3.info</a> <a href="http://www.css3.info/selectors-test/">CSS selectors test</a>. See more info on <a href="http://www.css3.info/preview/attribute-selectors.html">CSS3 selectors</a>.</p>
-		
-		<div class='base'></div>
-	
-		<ol>
-			<li>
-				<div class='defaultred'>
-					<div class='test required'></div>
-				</div>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div&gt;Does this element match?&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the only element of this type
-				</p>
-			</li>
-			
-			<li>
-				<div class='defaultred'>
-					<div></div>
-					<div class='test'></div>
-				</div>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div&gt;&lt;/div&gt;
-&lt;div&gt;Does this element match?&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the last element of this type
-				</p>
-			</li>
-			
-			<li>
-				<div class='defaultred'>
-					<div class='test required'></div>
-					<blockquote></blockquote>
-				</div>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;blockquote&gt;&lt;/blockquote&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the last element of this type
-				</p>
-			</li>
-	
-			<li>
-				<div class='defaultred'>
-					<blockquote>
-						<div class='test'></div>
-					</blockquote>
-					<div></div>
-				</div>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;blockquote&gt;
-   &lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;/blockquote&gt;
-&lt;div&gt;&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the last element of this type in this scope
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<div>
-						<div class='test'></div>
-					</div>
-				</div>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div&gt;
-   &lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the last element of this type in the current scope
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<div class='test'></div>
-					<blockquote>
-						<div></div>
-					</blockquote>
-				</div>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;blockquote&gt;
-   &lt;div&gt;&lt;/div&gt;
-&lt;/blockquote&gt;</pre>
-
-				<p>
-					The CSS selector should match the marked div element, because it is the last element of this type in the current scope
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultgreen'>
-					<div class='test default required'></div>
-					<div></div>
-				</div>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;div&gt;&lt;/div&gt;</pre>
-
-				<p>
-					The CSS selector should not match the marked div element, because it is the first element of this type
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultgreen'>
-					<div class='test default'></div>
-					<DIV></DIV>
-				</div>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div&gt;Does this element match?&lt;/div&gt;
-&lt;DIV&gt;&lt;/DIV&gt;</pre>
-
-				<p>
-					The CSS selector should not match the marked div element, because it is the first element of this type
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultred'>
-					<div id='insertAfter1'></div>
-				</div>
-
-				<script type="text/javascript">
-				<!--
-
-					var ib = document.getElementById('insertAfter1');
-					var el = document.createElement("div");
-					el.className = 'test';
-					ib.parentNode.appendChild(el);
-
-				
-				//-->
-				</script>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div id='insertAfter'&gt;&lt;/div&gt;
-
-var ib = document.getElementById('insertAfter');
-ib.parentElement.appendChild(document.createElement("div"));</pre>
-
-				<p>
-					The CSS selector should match the div element that is inserted by the Javascript code. 
-				</p>
-			</li>
-
-			<li>
-				<div class='defaultgreen'>
-					<div id='insertAfter2' class='test default'></div>
-				</div>
-
-				<script type="text/javascript">
-				<!--
-
-					var ib = document.getElementById('insertAfter2');
-					ib.parentNode.appendChild(document.createElement("div"));
-				
-				//-->
-				</script>
-				
-				<pre>div:last-of-type {
-}
-
-&lt;div id='insertAfter'&gt;&lt;/div&gt;
-
-var ib = document.getElementById('insertAfter');
-ib.parentElement.appendChild(document.createElement("div"));</pre>
-
-				<p>
-					The original div element should not be a match for the :last-of-type selector.
-				</p>
-			</li>
-		</ol>
-	</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/lists/008.html b/third_party/blink/web_tests/fast/lists/008.html
index 8f6c491..f18c4bec 100644
--- a/third_party/blink/web_tests/fast/lists/008.html
+++ b/third_party/blink/web_tests/fast/lists/008.html
@@ -5,9 +5,13 @@
 <style>
 li { border:5px solid orange; padding:5px; }
 .img { list-style-image: url(resources/white.gif) }
+ul, ol {
+  font-size:14px;
+  margin: 0.5em;
+}
 </style>
 </HEAD>
-<BODY>
+<BODY style="columns:3;">
 <UL style="width:20ex; border:1px blue solid;">
 <LI>First item
 <LI>Second and very very long item
@@ -68,4 +72,4 @@
 </OL>
 
 </BODY>
-</HTML>
\ No newline at end of file
+</HTML>
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/block/float/float-avoidance-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/block/float/float-avoidance-expected.png
new file mode 100644
index 0000000..1bd5c92
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/block/float/float-avoidance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/block/float/shrink-to-avoid-float-complexity-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/block/float/shrink-to-avoid-float-complexity-expected.png
new file mode 100644
index 0000000..f831fc0
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/block/float/shrink-to-avoid-float-complexity-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/lists/008-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/lists/008-expected.png
new file mode 100644
index 0000000..af7cfda
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/lists/008-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/text-antialias/international/bidi-neutral-run-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/text-antialias/international/bidi-neutral-run-expected.png
new file mode 100644
index 0000000..1143ad7
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/text-antialias/international/bidi-neutral-run-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/block/float/float-avoidance-expected.png b/third_party/blink/web_tests/platform/linux/fast/block/float/float-avoidance-expected.png
index 71a6c5d..1bd5c92 100644
--- a/third_party/blink/web_tests/platform/linux/fast/block/float/float-avoidance-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/block/float/float-avoidance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/block/float/shrink-to-avoid-float-complexity-expected.png b/third_party/blink/web_tests/platform/linux/fast/block/float/shrink-to-avoid-float-complexity-expected.png
index 431f1321..d521a1b4 100644
--- a/third_party/blink/web_tests/platform/linux/fast/block/float/shrink-to-avoid-float-complexity-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/block/float/shrink-to-avoid-float-complexity-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css/first-child-pseudo-class-expected.png b/third_party/blink/web_tests/platform/linux/fast/css/first-child-pseudo-class-expected.png
deleted file mode 100644
index 800ac42..0000000
--- a/third_party/blink/web_tests/platform/linux/fast/css/first-child-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css/first-of-type-pseudo-class-expected.png b/third_party/blink/web_tests/platform/linux/fast/css/first-of-type-pseudo-class-expected.png
deleted file mode 100644
index b2ccb266..0000000
--- a/third_party/blink/web_tests/platform/linux/fast/css/first-of-type-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css/last-child-pseudo-class-expected.png b/third_party/blink/web_tests/platform/linux/fast/css/last-child-pseudo-class-expected.png
deleted file mode 100644
index 60466a6b..0000000
--- a/third_party/blink/web_tests/platform/linux/fast/css/last-child-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css/last-of-type-pseudo-class-expected.png b/third_party/blink/web_tests/platform/linux/fast/css/last-of-type-pseudo-class-expected.png
deleted file mode 100644
index f38bf0b..0000000
--- a/third_party/blink/web_tests/platform/linux/fast/css/last-of-type-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/lists/008-expected.png b/third_party/blink/web_tests/platform/linux/fast/lists/008-expected.png
index 9fd0371..e313b48 100644
--- a/third_party/blink/web_tests/platform/linux/fast/lists/008-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/lists/008-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/international/bidi-neutral-run-expected.png b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/international/bidi-neutral-run-expected.png
index 20bb85f6e..1143ad7 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/international/bidi-neutral-run-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/international/bidi-neutral-run-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/block/float/shrink-to-avoid-float-complexity-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/block/float/shrink-to-avoid-float-complexity-expected.png
index 1a55dfc..d699830b 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/block/float/shrink-to-avoid-float-complexity-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/block/float/shrink-to-avoid-float-complexity-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/international/bidi-neutral-run-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/international/bidi-neutral-run-expected.png
index a97c510..f6faf41 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/international/bidi-neutral-run-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/international/bidi-neutral-run-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/international/bidi-neutral-run-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/international/bidi-neutral-run-expected.png
index 2639729..a52d1dd 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/international/bidi-neutral-run-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/international/bidi-neutral-run-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/content-type/script.window-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/content-type/script.window-expected.txt
deleted file mode 100644
index d2ddfa3..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/fetch/content-type/script.window-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-This is a testharness.js-based test.
-PASS Loading JSON…
-PASS separate text/javascript;charset=windows-1252
-PASS separate text/javascript;";charset=windows-1252
-PASS separate text/javascript
-PASS separate "text/javascript"
-PASS separate text/ javascript
-PASS separate text /javascript
-FAIL separate x/x text/javascript assert_unreached: Reached unreachable code
-FAIL combined x/x text/javascript assert_unreached: Reached unreachable code
-FAIL separate x/x;charset=windows-1252 text/javascript assert_unreached: Reached unreachable code
-FAIL combined x/x;charset=windows-1252 text/javascript assert_unreached: Reached unreachable code
-FAIL separate text/javascript x/x assert_unreached: Reached unreachable code
-FAIL combined text/javascript x/x assert_unreached: Reached unreachable code
-PASS separate text/javascript; charset=windows-1252 text/javascript
-PASS combined text/javascript; charset=windows-1252 text/javascript
-PASS separate text/javascript;" x/x
-PASS combined text/javascript;" x/x
-PASS separate text/javascript 
-PASS combined text/javascript 
-PASS separate text/javascript error
-PASS combined text/javascript error
-PASS separate text/javascript;charset=windows-1252 x/x text/javascript
-PASS combined text/javascript;charset=windows-1252 x/x text/javascript
-PASS separate text/javascript;charset=windows-1252 error text/javascript
-PASS combined text/javascript;charset=windows-1252 error text/javascript
-PASS separate text/javascript;charset=windows-1252  text/javascript
-PASS combined text/javascript;charset=windows-1252  text/javascript
-FAIL separate text/javascript;charset=windows-1252;" \" x/x assert_equals: expected "€" but got "€"
-PASS combined text/javascript;charset=windows-1252;" \" x/x
-FAIL separate x/x;" x/y;\" text/javascript;charset=windows-1252;" text/javascript assert_unreached: Reached unreachable code
-FAIL combined x/x;" x/y;\" text/javascript;charset=windows-1252;" text/javascript assert_unreached: Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/fast/block/float/float-avoidance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/fast/block/float/float-avoidance-expected.png
new file mode 100644
index 0000000..1a2fec16
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/fast/block/float/float-avoidance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/fast/lists/008-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/fast/lists/008-expected.png
new file mode 100644
index 0000000..0f133f2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/fast/lists/008-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/block/float/float-avoidance-expected.png b/third_party/blink/web_tests/platform/mac/fast/block/float/float-avoidance-expected.png
index 1a2fec16..a9af768 100644
--- a/third_party/blink/web_tests/platform/mac/fast/block/float/float-avoidance-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/block/float/float-avoidance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/block/float/shrink-to-avoid-float-complexity-expected.png b/third_party/blink/web_tests/platform/mac/fast/block/float/shrink-to-avoid-float-complexity-expected.png
index 894c984..11821eb8 100644
--- a/third_party/blink/web_tests/platform/mac/fast/block/float/shrink-to-avoid-float-complexity-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/block/float/shrink-to-avoid-float-complexity-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css/first-child-pseudo-class-expected.png b/third_party/blink/web_tests/platform/mac/fast/css/first-child-pseudo-class-expected.png
deleted file mode 100644
index 3242ec0d..0000000
--- a/third_party/blink/web_tests/platform/mac/fast/css/first-child-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css/first-of-type-pseudo-class-expected.png b/third_party/blink/web_tests/platform/mac/fast/css/first-of-type-pseudo-class-expected.png
deleted file mode 100644
index 745c583..0000000
--- a/third_party/blink/web_tests/platform/mac/fast/css/first-of-type-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css/last-child-pseudo-class-expected.png b/third_party/blink/web_tests/platform/mac/fast/css/last-child-pseudo-class-expected.png
deleted file mode 100644
index d563a40..0000000
--- a/third_party/blink/web_tests/platform/mac/fast/css/last-child-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css/last-of-type-pseudo-class-expected.png b/third_party/blink/web_tests/platform/mac/fast/css/last-of-type-pseudo-class-expected.png
deleted file mode 100644
index 6b46c69..0000000
--- a/third_party/blink/web_tests/platform/mac/fast/css/last-of-type-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/lists/008-expected.png b/third_party/blink/web_tests/platform/mac/fast/lists/008-expected.png
index 0f133f2..f2d440f 100644
--- a/third_party/blink/web_tests/platform/mac/fast/lists/008-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/lists/008-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/international/bidi-neutral-run-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/international/bidi-neutral-run-expected.png
index 22b70a75..016d628 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/international/bidi-neutral-run-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/international/bidi-neutral-run-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/block/float/float-avoidance-expected.png b/third_party/blink/web_tests/platform/win/fast/block/float/float-avoidance-expected.png
index e23fea3..fc44c5e 100644
--- a/third_party/blink/web_tests/platform/win/fast/block/float/float-avoidance-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/block/float/float-avoidance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/block/float/shrink-to-avoid-float-complexity-expected.png b/third_party/blink/web_tests/platform/win/fast/block/float/shrink-to-avoid-float-complexity-expected.png
index 25b8665..32a41b53 100644
--- a/third_party/blink/web_tests/platform/win/fast/block/float/shrink-to-avoid-float-complexity-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/block/float/shrink-to-avoid-float-complexity-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css/first-child-pseudo-class-expected.png b/third_party/blink/web_tests/platform/win/fast/css/first-child-pseudo-class-expected.png
deleted file mode 100644
index b8337ac..0000000
--- a/third_party/blink/web_tests/platform/win/fast/css/first-child-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css/first-of-type-pseudo-class-expected.png b/third_party/blink/web_tests/platform/win/fast/css/first-of-type-pseudo-class-expected.png
deleted file mode 100644
index f76b0379..0000000
--- a/third_party/blink/web_tests/platform/win/fast/css/first-of-type-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css/last-child-pseudo-class-expected.png b/third_party/blink/web_tests/platform/win/fast/css/last-child-pseudo-class-expected.png
deleted file mode 100644
index e0f3c9e..0000000
--- a/third_party/blink/web_tests/platform/win/fast/css/last-child-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css/last-of-type-pseudo-class-expected.png b/third_party/blink/web_tests/platform/win/fast/css/last-of-type-pseudo-class-expected.png
deleted file mode 100644
index ae0d4b7..0000000
--- a/third_party/blink/web_tests/platform/win/fast/css/last-of-type-pseudo-class-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/lists/008-expected.png b/third_party/blink/web_tests/platform/win/fast/lists/008-expected.png
index 8ef3d40..8020921 100644
--- a/third_party/blink/web_tests/platform/win/fast/lists/008-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/lists/008-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/text-antialias/international/bidi-neutral-run-expected.png b/third_party/blink/web_tests/platform/win/virtual/text-antialias/international/bidi-neutral-run-expected.png
index a83d3f0..5deb1a20 100644
--- a/third_party/blink/web_tests/platform/win/virtual/text-antialias/international/bidi-neutral-run-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/text-antialias/international/bidi-neutral-run-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/wpt_internal/wasm/postmessage_big_wasm_memory.https-expected.txt b/third_party/blink/web_tests/platform/win/wpt_internal/wasm/postmessage_big_wasm_memory.https-expected.txt
deleted file mode 100644
index 0459d1f..0000000
--- a/third_party/blink/web_tests/platform/win/wpt_internal/wasm/postmessage_big_wasm_memory.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test that WebAssembly memories greater than 2GB can be postmessaged. WebAssembly.Memory(): could not allocate memory
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/international/bidi-neutral-run-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/international/bidi-neutral-run-expected.png
index a892d74..157427c 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/international/bidi-neutral-run-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/international/bidi-neutral-run-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/text-antialias/international/bidi-neutral-run.html b/third_party/blink/web_tests/virtual/text-antialias/international/bidi-neutral-run.html
index e792fd5..69aa7db 100644
--- a/third_party/blink/web_tests/virtual/text-antialias/international/bidi-neutral-run.html
+++ b/third_party/blink/web_tests/virtual/text-antialias/international/bidi-neutral-run.html
@@ -1,6 +1,15 @@
+<style>
+.content {
+  columns: 8;
+}
+p {
+  margin: 6px 0em;
+}
+</style>
 <p>
     Tests the resolved level of runs of neutral types.
 </p>
+<div class="content"">
 <div style="direction: ltr;">
     <!-- ON run followed by L -->
     <p>
@@ -740,3 +749,4 @@
         &#x202a;&#x202b;?&#x202c;(^&#x202c;
     </p>
 </div>
+</div>
diff --git a/third_party/blink/web_tests/wpt_internal/wasm/postmessage_big_wasm_memory.https.html b/third_party/blink/web_tests/wpt_internal/wasm/postmessage_big_wasm_memory.https.html
new file mode 100644
index 0000000..589ea1e
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/wasm/postmessage_big_wasm_memory.https.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+  <script>
+test(() => {
+  // WebAssembly memory greater than 2GB.
+  let mem;
+  try {
+    mem =
+      new WebAssembly.Memory({initial: 33000, maximum: 33000, shared: true});
+  } catch (e) {
+    // We failed to allocate the WebAssembly memory. We can just return.
+    assert_equals(e.constructor, RangeError);
+    assert_equals(e.message,
+      "WebAssembly.Memory(): could not allocate memory");
+    return;
+  }
+  window.postMessage(mem, "*");
+}, "Test that WebAssembly memories greater than 2GB can be postmessaged.");
+  </script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/wasm/postmessage_big_wasm_memory.https.html.headers b/third_party/blink/web_tests/wpt_internal/wasm/postmessage_big_wasm_memory.https.html.headers
new file mode 100644
index 0000000..4b06ac7c
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/wasm/postmessage_big_wasm_memory.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy:same-origin
+Cross-Origin-Embedder-Policy:require-corp
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index e08f486..d58534d 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -680,7 +680,7 @@
       'win-swangle-tot-swiftshader-x64': 'angle_deqp_release_trybot_reclient',
       'win-swangle-tot-swiftshader-x86': 'angle_deqp_release_bot_dcheck_always_on_x86',
       'win-swangle-x64': 'angle_deqp_release_trybot_reclient',
-      'win-swangle-x86': 'angle_deqp_release_bot_dcheck_always_on_x86',
+      'win-swangle-x86': 'angle_deqp_release_bot_dcheck_always_on_x86_reclient',
     },
 
     'chromium.updater': {
@@ -2162,7 +2162,7 @@
 
     # Keep in sync with chromeos_with_codecs_release_trybot.
     'chromeos_with_codecs_release_trybot_code_coverage': [
-      'chromeos_with_codecs', 'release_trybot', 'no_symbols', 'also_build_lacros_chrome',
+      'chromeos_with_codecs', 'release_trybot', 'no_symbols',
       'use_clang_coverage', 'partial_code_coverage_instrumentation',
     ],
 
diff --git a/tools/mb/mb_config_expectations/chromium.swangle.json b/tools/mb/mb_config_expectations/chromium.swangle.json
index a8d999f..1f77f9f 100644
--- a/tools/mb/mb_config_expectations/chromium.swangle.json
+++ b/tools/mb/mb_config_expectations/chromium.swangle.json
@@ -132,7 +132,8 @@
       "is_debug": false,
       "symbol_level": 1,
       "target_cpu": "x86",
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   }
 }
\ No newline at end of file
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.chromiumos.json b/tools/mb/mb_config_expectations/tryserver.chromium.chromiumos.json
index 5e93911..41b363b 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.chromiumos.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.chromiumos.json
@@ -194,7 +194,6 @@
   },
   "linux-chromeos-annotator-rel": {
     "gn_args": {
-      "also_build_lacros_chrome": true,
       "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt",
       "dcheck_always_on": true,
       "ffmpeg_branding": "ChromeOS",
@@ -272,7 +271,6 @@
   },
   "linux-chromeos-rel": {
     "gn_args": {
-      "also_build_lacros_chrome": true,
       "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt",
       "dcheck_always_on": true,
       "ffmpeg_branding": "ChromeOS",
@@ -287,7 +285,6 @@
   },
   "linux-chromeos-rel-rts": {
     "gn_args": {
-      "also_build_lacros_chrome": true,
       "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt",
       "dcheck_always_on": true,
       "ffmpeg_branding": "ChromeOS",
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index ad80147..3f072c3d58 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -38166,6 +38166,7 @@
   <int value="4220" label="GestureScrollStart"/>
   <int value="4221" label="GestureScrollUpdate"/>
   <int value="4222" label="GestureScrollEnd"/>
+  <int value="4223" label="ArrayBufferTooBigForWebAPI"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index 613057c..74c5d57d 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -876,6 +876,7 @@
     expires_after="M110">
   <owner>miketaylr@chromium.org</owner>
   <owner>victortan@chromium.org</owner>
+  <owner>potassium-katabolism@google.com</owner>
   <summary>
     Whether the User-Agent header that was sent for a subresource request had a
     reduced user agent string value. The reduced user agent string is only sent
@@ -1824,8 +1825,8 @@
 
 <histogram name="Blink.Navigator.ReducedUserAgent" enum="Boolean"
     expires_after="2022-09-25">
-  <owner>abeyad@chromium.org</owner>
-  <owner>aarontag@chromium.org</owner>
+  <owner>miketaylr@chromium.org</owner>
+  <owner>potassium-katabolism@google.com</owner>
   <summary>
     Whether the navigator.userAgent and navigator.appVersion JavaScript getters
     returned a reduced user agent string value. The reduced user agent string is
diff --git a/tools/metrics/histograms/metadata/language/histograms.xml b/tools/metrics/histograms/metadata/language/histograms.xml
index 34f6d98..4a71357 100644
--- a/tools/metrics/histograms/metadata/language/histograms.xml
+++ b/tools/metrics/histograms/metadata/language/histograms.xml
@@ -211,7 +211,7 @@
 <histogram name="LanguageUsage.AcceptLanguageAndContentLanguageUsage"
     enum="AcceptLanguageAndContentLanguageUsage" expires_after="2023-03-01">
   <owner>victortan@chromium.org</owner>
-  <owner>abeyad@chromium.org</owner>
+  <owner>potassium-katabolism@google.com</owner>
   <summary>
     Metrics that record matches between the Content-Language response header and
     Accept-Language request header values. This is recorded every time
@@ -222,7 +222,7 @@
 <histogram name="LanguageUsage.AcceptLanguageAndXmlHtmlLangUsage"
     enum="AcceptLanguageAndXmlHtmlLangUsage" expires_after="2023-03-01">
   <owner>victortan@chromium.org</owner>
-  <owner>abeyad@chromium.org</owner>
+  <owner>potassium-katabolism@google.com</owner>
   <summary>
     Metrics that record matches between the xml:lang, html lang and
     Accept-Language request header values. This is recorded every time the
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 50b9d7c..1cd947c 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -1293,8 +1293,8 @@
 
 <histogram name="Navigation.UserAgentStringType" enum="UserAgentStringType"
     expires_after="2022-10-16">
-  <owner>abeyad@chromium.org</owner>
-  <owner>aarontag@chromium.org</owner>
+  <owner>miketaylr@chromium.org</owner>
+  <owner>potassium-katabolism@google.com</owner>
   <summary>
     The type of the user agent string value sent in the User-Agent header on a
     navigation request. The reduced user agent string is only sent in the
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index a18cb5f..d45d093 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -2667,8 +2667,8 @@
 
 <histogram name="ClientHints.FetchLatency" units="ms"
     expires_after="2022-10-16">
-  <owner>abeyad@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
+  <owner>potassium-katabolism@google.com</owner>
   <summary>
     The latency (in milliseconds) to fetch the client hints for a given origin
     from the Accept-CH cache.
@@ -2693,8 +2693,8 @@
 
 <histogram name="ClientHints.StoreLatency" units="ms"
     expires_after="2022-10-16">
-  <owner>abeyad@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
+  <owner>potassium-katabolism@google.com</owner>
   <summary>
     The latency (in milliseconds) to store the client hints for a given origin
     in the Accept-CH cache.
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index b55d71d..a8686ed 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -12066,7 +12066,7 @@
 </event>
 
 <event name="Navigation.ReceivedResponse">
-  <owner>abeyad@chromium.org</owner>
+  <owner>miketaylr@chromium.org</owner>
   <owner>potassium-katabolism@google.com</owner>
   <summary>
     Recorded when the navigation receives a response from the networking layer.
@@ -16529,6 +16529,42 @@
   </metric>
 </event>
 
+<event name="Presentation.StartResult">
+  <owner>muyaoxu@google.com</owner>
+  <owner>openscreen-eng@google.com</owner>
+  <summary>
+    Records when users start a Presentation and receive a response from the
+    receiver. Android only. The following failures are not recorded because they
+    don't represent an actual error: (1)
+    PresentationErrorType::PRESENTATION_REQUEST_CANCELLED This error is created
+    when users close the dialog without starting a Presentation. (2)
+    PresentationErrorType::NO_PRESENTATION_FOUND This error might happen when a
+    website implemnting CastSDK try to join a route every time the page loads.
+  </summary>
+  <metric name="PresentationRequest" enum="Boolean">
+    <summary>
+      Records whether the users' request to start a Presentation with a
+      &quot;cast:&quot; presentation URL succeed.
+    </summary>
+    <aggregation>
+      <history>
+        <statistics/>
+      </history>
+    </aggregation>
+  </metric>
+  <metric name="RemotePlayback" enum="Boolean">
+    <summary>
+      Records whether the users' request to start a Presentation through
+      RemotePlayback succeed.
+    </summary>
+    <aggregation>
+      <history>
+        <statistics/>
+      </history>
+    </aggregation>
+  </metric>
+</event>
+
 <event name="Previews" singular="True">
   <obsolete>
     Obsoleted 01/2022.
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js
index 982da34..4b9dffb 100644
--- a/ui/file_manager/file_manager/background/js/background.js
+++ b/ui/file_manager/file_manager/background/js/background.js
@@ -371,6 +371,7 @@
    */
   async onLaunched_(launchData) {
     metrics.startInterval('Load.BackgroundLaunch');
+    console.warn('onLaunched: ' + (launchData ? launchData.source : ''));
     if (!launchData || !launchData.items || launchData.items.length == 0) {
       this.launch_(undefined);
       return;
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_impl.js b/ui/file_manager/file_manager/background/js/volume_manager_impl.js
index db16054..0c95da1 100644
--- a/ui/file_manager/file_manager/background/js/volume_manager_impl.js
+++ b/ui/file_manager/file_manager/background/js/volume_manager_impl.js
@@ -153,6 +153,7 @@
         return;
       }
       finished = true;
+      console.warn('Volumes initialization finished');
       this.finishInitialization_();
     };
 
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js
index d201a31c..f0e73c6 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -915,7 +915,7 @@
    * @return {!Promise<void>}
    */
   async initializeUI(dialogDom) {
-    console.warn('Files app starting up');
+    console.warn(`Files app starting up: ${this.dialogType}`);
     this.dialogDom_ = dialogDom;
     this.document_ = this.dialogDom_.ownerDocument;